#pragma once #include #include #include "locks.h" #include "types.h" #define PREBUFFER_LEN 4096 * 6 #define POSTBUFFER_LEN 128 #define MAX_NR_SYSCALL 1024 enum ioctl_struct_type { STRUCT_undefined = 0, // QSEECOM STRUCT_qseecom_register_listener_req, STRUCT_qseecom_send_cmd_req, STRUCT_qseecom_send_modfd_cmd_req, STRUCT_qseecom_load_img_req, STRUCT_qseecom_set_sb_mem_param_req, STRUCT_qseecom_qseos_version_req, STRUCT_qseecom_qseos_app_load_query, }; enum syscallstate { UNKNOWN, /* new child */ PREP, /* doing sanitize */ BEFORE, /* about to do syscall */ GOING_AWAY, /* used when we don't expect to come back (execve for eg) */ AFTER, /* returned from doing syscall. */ DONE, /* moved to previous */ }; struct syscallrecord { struct timeval tv; unsigned int nr; unsigned long a1; unsigned long a2; unsigned long a3; unsigned long a4; unsigned long a5; unsigned long a6; unsigned long retval; int errno_post; /* what errno was after the syscall. */ unsigned long op_nr; /* used to tell if we're making progress. */ bool do32bit; lock_t lock; enum syscallstate state; char prebuffer[PREBUFFER_LEN]; char postbuffer[POSTBUFFER_LEN]; bool is_ioctl_call; enum ioctl_struct_type ioctl_struct_type; }; enum argtype { ARG_UNDEFINED, ARG_FD, ARG_LEN, ARG_ADDRESS, ARG_MODE_T, ARG_NON_NULL_ADDRESS, ARG_PID, ARG_RANGE, ARG_OP, ARG_LIST, ARG_CPU, ARG_PATHNAME, ARG_IOVEC, ARG_IOVECLEN, ARG_SOCKADDR, ARG_SOCKADDRLEN, ARG_MMAP, }; enum struct_argtype { STRUCT_ARG_timespec = 1, STRUCT_ARG_timeval, STRUCT_ARG_timezone, STRUCT_ARG_itimerspec, STRUCT_ARG_itimerval, STRUCT_ARG_sigevent, STRUCT_ARG_stat64, STRUCT_ARG_rlimit64, STRUCT_ARG_msghdr, STRUCT_ARG_iovec, STRUCT_ARG_mmsghdr, STRUCT_ARG_tms, STRUCT_ARG_epoll_even, STRUCT_ARG_getcpu_cache, STRUCT_ARG_rlimi, STRUCT_ARG_iocb, STRUCT_ARG_perf_event_attr, STRUCT_ARG_new_utsname, STRUCT_ARG_stat, STRUCT_ARG_linux_dirent64, STRUCT_ARG_linux_dirent, STRUCT_ARG_sembuf, STRUCT_ARG_statfs64, STRUCT_ARG_shmid_ds, STRUCT_ARG_pollfd, STRUCT_ARG_msgbu, STRUCT_ARG_file_handle, STRUCT_ARG_robust_list_head, STRUCT_ARG_robust_list, STRUCT_ARG_rusage, STRUCT_ARG_ustat, STRUCT_ARG_timex, STRUCT_ARG_statfs, STRUCT_ARG_msqid_ds, STRUCT_ARG_ipc_per, STRUCT_ARG_msg, STRUCT_ARG_sysctl_args, STRUCT_ARG_mq_attr, STRUCT_ARG_io_event, STRUCT_ARG_sched_param, STRUCT_ARG_kexec_segment, STRUCT_ARG_utimbuf, STRUCT_ARG_sockaddr, STRUCT_ARG_sel_arg_struct, STRUCT_ARG_epoll_event, STRUCT_ARG_rlimit, STRUCT_ARG_msgbuf, STRUCT_ARG___sysctl_args, STRUCT_ARG_mmap_arg_struct, STRUCT_ARG_siginfo }; struct arglist { unsigned int num; unsigned long values[32]; }; struct errnos { unsigned int num; int values[32]; }; struct misc_arg_info { enum struct_argtype struct_type; }; struct syscallentry { void (*sanitise)(struct syscallrecord *rec); void (*post)(struct syscallrecord *rec); int (*init)(void); char * (*decode)(struct syscallrecord *rec, unsigned int argnum); unsigned int number; unsigned int active_number; const char name[80]; const unsigned int num_args; unsigned int flags; const enum argtype arg1type; const enum argtype arg2type; const enum argtype arg3type; const enum argtype arg4type; const enum argtype arg5type; const enum argtype arg6type; const char *arg1name; const char *arg2name; const char *arg3name; const char *arg4name; const char *arg5name; const char *arg6name; struct misc_arg_info arg1misc; struct misc_arg_info arg2misc; struct misc_arg_info arg3misc; struct misc_arg_info arg4misc; struct misc_arg_info arg5misc; struct misc_arg_info arg6misc; /* FIXME: At some point, if we grow more type specific parts here, * it may be worth union-ising this */ /* ARG_RANGE */ const unsigned int low1range, hi1range; const unsigned int low2range, hi2range; const unsigned int low3range, hi3range; const unsigned int low4range, hi4range; const unsigned int low5range, hi5range; const unsigned int low6range, hi6range; /* ARG_OP / ARG_LIST */ const struct arglist arg1list; const struct arglist arg2list; const struct arglist arg3list; const struct arglist arg4list; const struct arglist arg5list; const struct arglist arg6list; const unsigned int group; const int rettype; struct errnos errnos; }; #define RET_BORING -1 #define RET_NONE 0 #define RET_ZERO_SUCCESS 1 #define RET_FD 2 #define RET_KEY_SERIAL_T 3 #define RET_PID_T 4 #define RET_PATH 5 #define RET_NUM_BYTES 6 #define RET_GID_T 7 #define RET_UID_T 8 #define GROUP_NONE 0 #define GROUP_VM 1 #define GROUP_VFS 2 struct syscalltable { struct syscallentry *entry; }; #define AVOID_SYSCALL (1<<0) #define NI_SYSCALL (1<<1) #define BORING (1<<2) #define ACTIVE (1<<3) #define TO_BE_DEACTIVATED (1<<4) #define NEED_ALARM (1<<5) #define EXTRA_FORK (1<<6) #define IGNORE_ENOSYS (1<<7) void do_syscall(struct syscallrecord *rec); void handle_syscall_ret(struct syscallrecord *rec); #define for_each_arg(i) \ for (i = 1; i <= entry->num_args; i++) .