void IR_init_File(struct IridiumContext * context) { CLASS(File) = send(CLASS(Class), "new", IR_STRING("File")); CLASS(FileNotFoundError) = send(CLASS(Class), "new", IR_STRING("FileNotFoundError"), CLASS(Exception)); CLASS(IOError) = send(CLASS(Class), "new", IR_STRING("IOError"), CLASS(Exception)); DEF_METHOD(CLASS(File), "initialize", ARGLIST(argument_new(L_ATOM(filename), NULL, 0), argument_new(L_ATOM(mode), IR_STRING("r"), 0)), iridium_method_name(File, initialize)); DEF_METHOD(CLASS(File), "read", ARGLIST(), iridium_method_name(File, read)); DEF_METHOD(CLASS(File), "write", ARGLIST(argument_new(L_ATOM(str), NULL, 0)), iridium_method_name(File, write)); DEF_METHOD(CLASS(File), "close", ARGLIST(), iridium_method_name(File, close)); DEF_FUNCTION(CLASS(File), "read", ARGLIST(argument_new(L_ATOM(filename), NULL, 0)), iridium_classmethod_name(File, read)); DEF_METHOD(CLASS(File), "each_line", ARGLIST(argument_new(L_ATOM(fn), NULL, 0)), iridium_method_name(File, each_line)); define_constant(L_ATOM(File), CLASS(File)); }
static unsigned long sync_file_range_flags[] = { SYNC_FILE_RANGE_WAIT_BEFORE, SYNC_FILE_RANGE_WRITE, SYNC_FILE_RANGE_WAIT_AFTER, }; struct syscallentry syscall_sync_file_range = { .name = "sync_file_range", .num_args = 4, .sanitise = sanitise_sync_file_range, .arg1name = "fd", .arg1type = ARG_FD, .arg2name = "offset", .arg3name = "nbytes", .arg3type = ARG_LEN, .arg4name = "flags", .arg4type = ARG_LIST, .arg4list = ARGLIST(sync_file_range_flags), .flags = NEED_ALARM, .group = GROUP_VFS, }; /* * ARM & PowerPC have different argument order. * See edd5cd4a9424f22b0fa08bef5e299d41befd5622 in kernel tree. */ struct syscallentry syscall_sync_file_range2 = { .name = "sync_file_range2", .num_args = 4, .sanitise = sanitise_sync_file_range, .arg1name = "fd", .arg1type = ARG_FD, .arg2name = "flags",
/* * SYSCALL_DEFINE4(timer_settime, timer_t, timer_id, int, flags, TIMER_ABSTIMEconst struct itimerspec __user *, new_setting, struct itimerspec __user *, old_setting) */ #include <time.h> #include "sanitise.h" static unsigned long timer_settime_flags[] = { TIMER_ABSTIME, }; struct syscallentry syscall_timer_settime = { .name = "timer_settime", .num_args = 4, .arg1name = "timer_id", .arg2name = "flags", .arg2type = ARG_LIST, .arg2list = ARGLIST(timer_settime_flags), .arg3name = "new_setting", .arg3type = ARG_ADDRESS, .arg4name = "old_setting", .arg4type = ARG_ADDRESS, };
/* * SYSCALL_DEFINE5(kcmp, pid_t, pid1, pid_t, pid2, int, type, * unsigned long, idx1, unsigned long, idx2) * */ #include "sanitise.h" #include "compat.h" static unsigned long kcmp_types[] = { KCMP_FILE, KCMP_VM, KCMP_FILES, KCMP_FS, KCMP_SIGHAND, KCMP_IO, KCMP_SYSVSEM, }; struct syscallentry syscall_kcmp = { .name = "kcmp", .num_args = 5, .arg1name = "pid1", .arg1type = ARG_PID, .arg2name = "pid2", .arg2type = ARG_PID, .arg3name = "type", .arg3type = ARG_OP, .arg3list = ARGLIST(kcmp_types), .arg4name = "idx1", .arg5name = "idx2", };
if (attr->prog_type == BPF_PROG_TYPE_SOCKET_FILTER) { void *ptr = (void *) attr->insns; free(ptr); } break; default: break; } freeptr(&rec->a2); } static unsigned long bpf_cmds[] = { BPF_MAP_CREATE, BPF_MAP_LOOKUP_ELEM, BPF_MAP_UPDATE_ELEM, BPF_MAP_DELETE_ELEM, BPF_MAP_GET_NEXT_KEY, BPF_PROG_LOAD, BPF_OBJ_PIN, BPF_OBJ_GET, }; struct syscallentry syscall_bpf = { .name = "bpf", .num_args = 3, .arg1name = "cmd", .arg1type = ARG_OP, .arg1list = ARGLIST(bpf_cmds), .arg2name = "uattr", .arg3name = "size", .sanitise = sanitise_bpf, .post = post_bpf, }; #endif
/* * SYSCALL_DEFINE4(msgsnd, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz, int, msgflg) */ #include <sys/types.h> #include <linux/msg.h> #include "compat.h" #include "sanitise.h" static unsigned long msgsnd_flags[] = { MSG_NOERROR, MSG_EXCEPT, MSG_COPY, IPC_NOWAIT, }; struct syscallentry syscall_msgsnd = { .name = "msgsnd", .num_args = 4, .arg1name = "msqid", .arg2name = "msgp", .arg2type = ARG_ADDRESS, .arg3name = "msgsz", .arg3type = ARG_LEN, .arg4name = "msgflg", .arg4type = ARG_LIST, .arg4list = ARGLIST(msgsnd_flags), };
/* * SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr, int __user *, upeer_addrlen, int, flags) * * On success, these system calls return a nonnegative integer that is a descriptor for the accepted socket. * On error, -1 is returned, and errno is set appropriately. * */ static unsigned long accept4_flags[] = { SOCK_NONBLOCK, SOCK_CLOEXEC, }; struct syscallentry syscall_accept4 = { .name = "accept4", .num_args = 4, .arg1name = "fd", .arg1type = ARG_SOCKETINFO, .arg2name = "upeer_sockaddr", .arg2type = ARG_SOCKADDR, .arg3name = "upeer_addrlen", .arg3type = ARG_SOCKADDRLEN, .arg4name = "flags", .arg4type = ARG_LIST, .arg4list = ARGLIST(accept4_flags), .rettype = RET_FD, .flags = NEED_ALARM, .sanitise = sanitise_accept, // use same as accept. };
*/ #include <sys/swap.h> #include "sanitise.h" #include "compat.h" static unsigned long swapon_flags[] = { SWAP_FLAG_PREFER, SWAP_FLAG_DISCARD, }; struct syscallentry syscall_swapon = { .name = "swapon", .num_args = 2, .arg1name = "path", .arg1type = ARG_PATHNAME, .arg2name = "swap_flags", .arg2type = ARG_LIST, .arg2list = ARGLIST(swapon_flags), .group = GROUP_VFS, }; /* * SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) */ struct syscallentry syscall_swapoff = { .name = "swapoff", .num_args = 1, .arg1name = "path", .arg1type = ARG_PATHNAME, .group = GROUP_VFS, };
/* * SYSCALL_DEFINE3(finit_module, int, fd, const char __user *, uargs, int, flags) */ #include "sanitise.h" #define MODULE_INIT_IGNORE_MODVERSIONS 1 #define MODULE_INIT_IGNORE_VERMAGIC 2 static unsigned long finit_module_flags[] = { MODULE_INIT_IGNORE_MODVERSIONS, MODULE_INIT_IGNORE_VERMAGIC, }; struct syscallentry syscall_finit_module = { .name = "finit_module", .num_args = 3, .arg1name = "fd", .arg1type = ARG_FD, .arg2name = "uargs", .arg2type = ARG_ADDRESS, .arg3name = "flags", .arg3type = ARG_LIST, .arg3list = ARGLIST(finit_module_flags), };
/* "The prot argument must be specified as 0" */ rec->a3 = 0; /* Pick a random pgoff. */ if (RAND_BOOL()) offset = rnd() & (size / page_size); else offset = 0; rec->a4 = offset; } static unsigned long remap_file_pages_flags[] = { MAP_NONBLOCK, }; struct syscallentry syscall_remap_file_pages = { .name = "remap_file_pages", .num_args = 5, .arg1name = "start", .arg1type = ARG_MMAP, .arg2name = "size", .arg3name = "prot", .arg4name = "pgoff", .arg5name = "flags", .arg5type = ARG_LIST, .arg5list = ARGLIST(remap_file_pages_flags), .group = GROUP_VM, .sanitise = sanitise_remap_file_pages, };
POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, POSIX_FADV_DONTNEED, }; struct syscallentry syscall_fadvise64 = { .name = "fadvise64", .num_args = 4, .arg1name = "fd", .arg1type = ARG_FD, .arg2name = "offset", .arg3name = "len", .arg3type = ARG_LEN, .arg4name = "advice", .arg4type = ARG_OP, .arg4list = ARGLIST(fadvise_flags), .rettype = RET_ZERO_SUCCESS, .flags = NEED_ALARM, .group = GROUP_VFS, }; #ifndef __arm__ /* * SYSCALL_DEFINE(fadvise64_64)(int fd, loff_t offset, loff_t len, int advice) * * On success, zero is returned. * On error, an error number is returned. */ struct syscallentry syscall_fadvise64_64 = { .name = "fadvise64_64",
ep->data.fd = get_random_fd(); ep->events = set_rand_bitmask(ARRAY_SIZE(epoll_flags), epoll_flags); rec->a4 = (unsigned long) ep; } static void post_epoll_ctl(struct syscallrecord *rec) { free((void *)rec->a4); } static unsigned long epoll_ctl_ops[] = { EPOLL_CTL_ADD, EPOLL_CTL_MOD, EPOLL_CTL_DEL, }; struct syscallentry syscall_epoll_ctl = { .name = "epoll_ctl", .num_args = 4, .arg1name = "epfd", .arg1type = ARG_FD, .arg2name = "op", .arg2type = ARG_OP, .arg2list = ARGLIST(epoll_ctl_ops), .arg3name = "fd", .arg3type = ARG_FD, .arg4name = "event", .rettype = RET_ZERO_SUCCESS, .flags = NEED_ALARM, .sanitise = sanitise_epoll_ctl, .post = post_epoll_ctl, };
/* (x86-64 only) * long sys_arch_prctl(int code, unsigned long addr) * * On success, arch_prctl() returns 0 * On error, -1 is returned, and errno is set to indicate the error. */ #if defined(__i386__) || defined (__x86_64__) #include "sanitise.h" #include <asm/prctl.h> #include <sys/prctl.h> static unsigned long arch_prctl_flags[] = { ARCH_SET_FS, ARCH_GET_FS, ARCH_SET_GS, ARCH_GET_GS }; struct syscallentry syscall_arch_prctl = { .name = "arch_prctl", .flags = AVOID_SYSCALL, .num_args = 2, .arg1name = "code", .arg1type = ARG_OP, .arg1list = ARGLIST(arch_prctl_flags), .arg2name = "addr", .arg2type = ARG_ADDRESS, .rettype = RET_BORING, }; #endif
#include "syscall.h" #include "trinity.h" #include "compat.h" static void sanitise_madvise(__unused__ struct syscallrecord *rec) { (void) common_set_mmap_ptr_len(); } static unsigned long madvise_advices[] = { MADV_NORMAL, MADV_RANDOM, MADV_SEQUENTIAL, MADV_WILLNEED, MADV_DONTNEED, MADV_FREE, MADV_REMOVE, MADV_DONTFORK, MADV_DOFORK, MADV_MERGEABLE, MADV_UNMERGEABLE, MADV_HUGEPAGE, MADV_NOHUGEPAGE, MADV_DONTDUMP, MADV_DODUMP, MADV_WIPEONFORK, MADV_KEEPONFORK, }; struct syscallentry syscall_madvise = { .name = "madvise", .num_args = 3, .arg1name = "start", .arg1type = ARG_MMAP, .arg2name = "len_in", .arg3name = "advice", .arg3type = ARG_OP, .arg3list = ARGLIST(madvise_advices), .group = GROUP_VM, .sanitise = sanitise_madvise, };
* SYSCALL_DEFINE3(getrandom, char __user *, buf, size_t, count, unsigned int, flags) */ #include <errno.h> #include "maps.h" #include "sanitise.h" #include "trinity.h" #define GRND_NONBLOCK 0x0001 #define GRND_RANDOM 0x0002 static void sanitise_getrandom(__unused__ struct syscallrecord *rec) { (void) common_set_mmap_ptr_len(); } static unsigned long getrandom_flags[] = { GRND_NONBLOCK, GRND_RANDOM, }; struct syscallentry syscall_getrandom = { .name = "getrandom", .num_args = 3, .arg1name = "buf", .arg1type = ARG_MMAP, .arg2name = "count", .arg3name = "flags", .arg3type = ARG_LIST, .arg3list = ARGLIST(getrandom_flags), .sanitise = sanitise_getrandom, };
#include "trinity.h" #include "compat.h" static void sanitise_tee(struct syscallrecord *rec) { if ((rand() % 10) > 0) { rec->a1 = shm->pipe_fds[rand() % MAX_PIPE_FDS]; rec->a2 = shm->pipe_fds[rand() % MAX_PIPE_FDS]; } } static unsigned long tee_flags[] = { SPLICE_F_MOVE, SPLICE_F_NONBLOCK, SPLICE_F_MORE, SPLICE_F_GIFT, }; struct syscallentry syscall_tee = { .name = "tee", .num_args = 4, .arg1name = "fdin", .arg1type = ARG_FD, .arg2name = "fdout", .arg2type = ARG_FD, .arg3name = "len", .arg3type = ARG_LEN, .arg4name = "flags", .arg4type = ARG_LIST, .arg4list = ARGLIST(tee_flags), .sanitise = sanitise_tee, .flags = NEED_ALARM, };
#include "random.h" #include "sanitise.h" #include "shm.h" #include "syscall.h" #include "tables.h" #include "trinity.h" static unsigned long copy_file_range_flags[] = { 0, // so far, no flags, MBZ. }; struct syscallentry syscall_copy_file_range = { .name = "copy_file_range", .num_args = 6, .arg1name = "fd_in", .arg1type = ARG_FD, .arg2name = "off_in", .arg2type = ARG_LEN, .arg3name = "fd_out", .arg3type = ARG_FD, .arg4name = "off_out", .arg4type = ARG_LEN, .arg5name = "len", .arg5type = ARG_LEN, .arg6name = "flags", .arg6type = ARG_LIST, .arg4list = ARGLIST(copy_file_range_flags), .flags = NEED_ALARM, .group = GROUP_VFS, };
map = common_set_mmap_ptr_len(); } /* * If we successfully did an mprotect, update our record of the mappings prot bits. */ static void post_mprotect(struct syscallrecord *rec) { if (rec->retval != 0) map->prot = rec->a3; } static unsigned long mprotect_prots[] = { PROT_READ, PROT_WRITE, PROT_EXEC, PROT_SEM, PROT_GROWSDOWN, PROT_GROWSUP, }; struct syscallentry syscall_mprotect = { .name = "mprotect", .num_args = 3, .arg1name = "start", .arg1type = ARG_MMAP, .arg2name = "len", .arg3name = "prot", .arg3type = ARG_LIST, .arg3list = ARGLIST(mprotect_prots), .sanitise = sanitise_mprotect, .group = GROUP_VM, .post = post_mprotect, };
/* * SYSCALL_DEFINE5(renameat2, int, olddfd, const char __user *, oldname, int, newdfd, const char __user *, newname, unsigned int, flags) */ #define RENAME_NOREPLACE (1 << 0) /* Don't overwrite target */ #define RENAME_EXCHANGE (1 << 1) /* Exchange source and dest */ static unsigned long renameat2_flags[] = { RENAME_NOREPLACE, RENAME_EXCHANGE, }; struct syscallentry syscall_renameat2 = { .name = "renameat2", .num_args = 5, .arg1name = "olddfd", .arg1type = ARG_FD, .arg2name = "oldname", .arg2type = ARG_PATHNAME, .arg3name = "newdfd", .arg3type = ARG_FD, .arg4name = "newname", .arg4type = ARG_PATHNAME, .arg5name = "flags", .arg5type = ARG_LIST, .arg5list = ARGLIST(renameat2_flags), .flags = NEED_ALARM, .group = GROUP_VFS, };
rec->a2 = (unsigned long) map->ptr; rec->a3 = rnd() % map->size; rec->a3 &= PAGE_MASK; } static unsigned long syslog_types[] = { SYSLOG_ACTION_CLOSE, SYSLOG_ACTION_OPEN, SYSLOG_ACTION_READ, SYSLOG_ACTION_READ_CLEAR, SYSLOG_ACTION_READ_ALL, SYSLOG_ACTION_CLEAR, SYSLOG_ACTION_CONSOLE_OFF, SYSLOG_ACTION_CONSOLE_ON, SYSLOG_ACTION_CONSOLE_LEVEL, SYSLOG_ACTION_SIZE_UNREAD, SYSLOG_ACTION_SIZE_BUFFER, }; struct syscallentry syscall_syslog = { .name = "syslog", .num_args = 3, .arg1name = "type", .arg1type = ARG_LIST, .arg1list = ARGLIST(syslog_types), .arg2name = "buf", .arg2type = ARG_MMAP, .arg3name = "len", .sanitise = sanitise_syslog, };
MSG_PROBE, MSG_TRUNC, MSG_DONTWAIT, MSG_EOR, MSG_WAITALL, MSG_FIN, MSG_SYN, MSG_CONFIRM, MSG_RST, MSG_ERRQUEUE, MSG_NOSIGNAL, MSG_MORE, MSG_WAITFORONE, MSG_FASTOPEN, MSG_CMSG_CLOEXEC, MSG_CMSG_COMPAT, }; struct syscallentry syscall_send = { .name = "send", .num_args = 4, .arg1name = "fd", .arg1type = ARG_SOCKETINFO, .arg2name = "buff", .arg3name = "len", .arg4name = "flags", .arg4type = ARG_LIST, .arg4list = ARGLIST(sendflags), .sanitise = sanitise_send, .post = post_send, }; /* * SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len, unsigned, flags, struct sockaddr __user *, addr, int, addr_len) */ struct syscallentry syscall_sendto = { .name = "sendto", .num_args = 6, .arg1name = "fd", .arg1type = ARG_SOCKETINFO,
#define PKEY_DISABLE_WRITE 0x2 static unsigned long pkey_alloc_initvals[] = { PKEY_DISABLE_ACCESS, PKEY_DISABLE_WRITE, }; static void sanitise_pkey_alloc(struct syscallrecord *rec) { // no flags defined right now. rec->a1 = 0; } struct syscallentry syscall_pkey_alloc = { .name = "pkey_alloc", .num_args = 2, .arg1name = "flags", .arg2name = "init_val", .arg2type = ARG_LIST, .arg2list = ARGLIST(pkey_alloc_initvals), .sanitise = sanitise_pkey_alloc, .group = GROUP_VM, }; struct syscallentry syscall_pkey_free = { .name = "pkey_free", .num_args = 1, .arg1name = "key", .group = GROUP_VM, };
/* * SYSCALL_DEFINE4(utimensat, int, dfd, const char __user *, filename, struct timespec __user *, utimes, int, flags) */ #include <fcntl.h> #include "sanitise.h" static unsigned long utimensat_flags[] = { AT_SYMLINK_NOFOLLOW, }; struct syscallentry syscall_utimensat = { .name = "utimensat", .num_args = 4, .arg1name = "dfd", .arg1type = ARG_FD, .arg2name = "filename", .arg2type = ARG_PATHNAME, .arg3name = "utimes", .arg3type = ARG_ADDRESS, .arg4name = "flags", .arg4type = ARG_LIST, .arg4list = ARGLIST(utimensat_flags), .flags = NEED_ALARM, };
#include "syscall.h" #include "trinity.h" #define MCL_CURRENT 1 #define MCL_FUTURE 2 static void sanitise_mlockall(struct syscallrecord *rec) { if (rec->a1 != 0) return; if (RAND_BOOL()) rec->a1 = MCL_CURRENT; else rec->a1 = MCL_FUTURE; } static unsigned long mlockall_flags[] = { MCL_CURRENT, MCL_FUTURE, }; struct syscallentry syscall_mlockall = { .name = "mlockall", .num_args = 1, .arg1name = "flags", .arg1type = ARG_LIST, .arg1list = ARGLIST(mlockall_flags), .group = GROUP_VM, .sanitise = sanitise_mlockall, };