diff --git a/compel/arch/x86/plugins/include/asm/std/syscall-types.h b/compel/arch/x86/plugins/include/asm/std/syscall-types.h new file mode 100644 index 000000000..744809d07 --- /dev/null +++ b/compel/arch/x86/plugins/include/asm/std/syscall-types.h @@ -0,0 +1,53 @@ +#ifndef COMPEL_ARCH_SYSCALL_TYPES_H__ +#define COMPEL_ARCH_SYSCALL_TYPES_H__ + +/* Types for sigaction, sigprocmask syscalls */ +typedef void rt_signalfn_t(int, siginfo_t *, void *); +typedef rt_signalfn_t *rt_sighandler_t; + +typedef void rt_restorefn_t(void); +typedef rt_restorefn_t *rt_sigrestore_t; + +#define _KNSIG 64 +# define _NSIG_BPW 64 + +#define _KNSIG_WORDS (_KNSIG / _NSIG_BPW) + +typedef struct { + u64 sig[_KNSIG_WORDS]; +} k_rtsigset_t; + +typedef struct { + rt_sighandler_t rt_sa_handler; + unsigned long rt_sa_flags; + rt_sigrestore_t rt_sa_restorer; + k_rtsigset_t rt_sa_mask; +} rt_sigaction_t; + +/* + * Note: there is unaligned access on x86_64 and it's fine. + * However, when porting this code -- keep in mind about possible issues + * with unaligned rt_sa_mask. + */ +typedef struct __attribute__((packed)) { + u32 rt_sa_handler; + u32 rt_sa_flags; + u32 rt_sa_restorer; + k_rtsigset_t rt_sa_mask; +} rt_sigaction_t_compat; + +/* Types for set_thread_area, get_thread_area syscalls */ +typedef struct { + unsigned int entry_number; + unsigned int base_addr; + unsigned int limit; + unsigned int seg_32bit:1; + unsigned int contents:2; + unsigned int read_exec_only:1; + unsigned int limit_in_pages:1; + unsigned int seg_not_present:1; + unsigned int useable:1; + unsigned int lm:1; +} user_desc_t; + +#endif /* COMPEL_ARCH_SYSCALL_TYPES_H__ */ diff --git a/compel/arch/x86/plugins/std/call32.S b/compel/arch/x86/plugins/std/call32.S new file mode 100644 index 000000000..935461dcd --- /dev/null +++ b/compel/arch/x86/plugins/std/call32.S @@ -0,0 +1,71 @@ +/* + * call32.S - assembly helpers for mixed-bitness code + * From kernel selftests originally: tools/testing/selftests/x86/thunks.S + * Copyright (c) 2015 Andrew Lutomirski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * These are little helpers that make it easier to switch bitness on + * the fly. + */ + +#include "asm/linkage.h" + +#define __USER32_CS 0x23 +#define __USER_CS 0x33 + + .text + +/* + * @rdi: Stack to use + * @esi: Pointer to function for calling + */ +ENTRY(call32_from_64) + /* Callee-saving registers due to ABI */ + pushq %rbx + pushq %rbp + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + pushfq + + /* Switch stacks */ + sub $8, %rdi + mov %rsp,(%rdi) + mov %rdi,%rsp + + /* Switch into compatibility mode */ + pushq $__USER32_CS + pushq $1f + lretq + +1: + .code32 + /* Run function and switch back */ + call *%esi + jmp $__USER_CS,$1f + .code64 + +1: + /* Restore the stack */ + mov (%rsp),%rsp + add $8, %rdi + + /* Restore registers */ + popfq + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbp + popq %rbx + ret +END(call32_from_64) diff --git a/compel/arch/x86/plugins/std/syscalls/syscall-common-x86-32.S b/compel/arch/x86/plugins/std/syscalls/syscall-common-x86-32.S new file mode 100644 index 000000000..ae6d594dc --- /dev/null +++ b/compel/arch/x86/plugins/std/syscalls/syscall-common-x86-32.S @@ -0,0 +1,36 @@ +#include "asm/linkage.h" + +#define SYSCALL(name, opcode) \ + ENTRY(name); \ + movl $opcode, %eax; \ + jmp __syscall_common; \ + END(name) + +ENTRY(__syscall_common) + pushl %ebx + pushl %esi + pushl %edi + pushl %ebp + +#define __arg(n) (4 * (n) + 20)(%esp) + movl __arg(0),%ebx + movl __arg(1),%ecx + movl __arg(2),%edx + movl __arg(3),%esi + movl __arg(4),%edi + movl __arg(5),%ebp +#undef __arg + + int $0x80 + + popl %ebp + popl %edi + popl %esi + popl %ebx + ret +END(__syscall_common) + +ENTRY(__cr_restore_rt) + movl $__NR_rt_sigreturn, %eax + jmp __syscall_common +END(__cr_restore_rt) diff --git a/compel/arch/x86/plugins/std/syscalls/syscall-common-x86-64.S b/compel/arch/x86/plugins/std/syscalls/syscall-common-x86-64.S new file mode 100644 index 000000000..b93c31288 --- /dev/null +++ b/compel/arch/x86/plugins/std/syscalls/syscall-common-x86-64.S @@ -0,0 +1,21 @@ +#include "asm/linkage.h" + +#define SYSCALL(name, opcode) \ + ENTRY(name); \ + movl $opcode, %eax; \ + jmp __syscall_common; \ + END(name) + + .text + .align 4 + +ENTRY(__syscall_common) + movq %rcx, %r10 + syscall + ret +END(__syscall_common) + +ENTRY(__cr_restore_rt) + movq $__NR_rt_sigreturn, %rax + syscall +END(__cr_restore_rt) diff --git a/compel/arch/x86/plugins/std/syscalls/syscall32.c b/compel/arch/x86/plugins/std/syscalls/syscall32.c new file mode 100644 index 000000000..88af59330 --- /dev/null +++ b/compel/arch/x86/plugins/std/syscalls/syscall32.c @@ -0,0 +1,85 @@ +#include "asm/types.h" +#include "syscall-32.h" + +#define SYS_SOCKET 1 /* sys_socket(2) */ +#define SYS_BIND 2 /* sys_bind(2) */ +#define SYS_CONNECT 3 /* sys_connect(2) */ +#define SYS_SENDTO 11 /* sys_sendto(2) */ +#define SYS_RECVFROM 12 /* sys_recvfrom(2) */ +#define SYS_SHUTDOWN 13 /* sys_shutdown(2) */ +#define SYS_SETSOCKOPT 14 /* sys_setsockopt(2) */ +#define SYS_GETSOCKOPT 15 /* sys_getsockopt(2) */ +#define SYS_SENDMSG 16 /* sys_sendmsg(2) */ +#define SYS_RECVMSG 17 /* sys_recvmsg(2) */ + +long sys_socket(int domain, int type, int protocol) +{ + u32 a[] = { (u32)domain, (u32)type, (u32)protocol }; + return sys_socketcall(SYS_SOCKET, (unsigned long *)a); +} + +long sys_connect(int sockfd, struct sockaddr *addr, int addrlen) +{ + u32 a[] = {(u32)sockfd, (u32)addr, (u32)addrlen}; + return sys_socketcall(SYS_CONNECT, (unsigned long *)a); +} + +long sys_sendto(int sockfd, void *buff, size_t len, unsigned int flags, struct sockaddr *addr, int addr_len) +{ + u32 a[] = {(u32)sockfd, (u32)buff, (u32)len, (u32)flags, (u32)addr, (u32)addr_len}; + return sys_socketcall(SYS_SENDTO, (unsigned long *)a); +} + +long sys_recvfrom(int sockfd, void *ubuf, size_t size, unsigned int flags, struct sockaddr *addr, int *addr_len) +{ + u32 a[] = {(u32)sockfd, (u32)ubuf, (u32)size, (u32)flags, (u32)addr, (u32)addr_len}; + return sys_socketcall(SYS_RECVFROM, (unsigned long *)a); +} + +long sys_sendmsg(int sockfd, const struct msghdr *msg, int flags) +{ + u32 a[] = {(u32)sockfd, (u32)msg, (u32)flags}; + return sys_socketcall(SYS_SENDMSG, (unsigned long *)a); +} + +long sys_recvmsg(int sockfd, struct msghdr *msg, int flags) +{ + u32 a[] = {(u32)sockfd, (u32)msg, (u32)flags}; + return sys_socketcall(SYS_RECVMSG, (unsigned long *)a); +} + +long sys_shutdown(int sockfd, int how) +{ + u32 a[] = {(u32)sockfd, (u32)how}; + return sys_socketcall(SYS_SHUTDOWN, (unsigned long *)a); +} + +long sys_bind(int sockfd, const struct sockaddr *addr, int addrlen) +{ + u32 a[] = {(u32)sockfd, (u32)addr, (u32)addrlen}; + return sys_socketcall(SYS_BIND, (unsigned long *)a); +} + +long sys_setsockopt(int sockfd, int level, int optname, const void *optval, unsigned int optlen) +{ + u32 a[] = {(u32)sockfd, (u32)level, (u32)optname, (u32)optval, (u32)optlen}; + return sys_socketcall(SYS_SETSOCKOPT, (unsigned long *)a); +} + +long sys_getsockopt(int sockfd, int level, int optname, const void *optval, unsigned int *optlen) +{ + u32 a[] = {(u32)sockfd, (u32)level, (u32)optname, (u32)optval, (u32)optlen}; + return sys_socketcall(SYS_GETSOCKOPT, (unsigned long *)a); +} + +#define SHMAT 21 + +long sys_shmat(int shmid, void *shmaddr, int shmflag) +{ + return sys_ipc(SHMAT, shmid, shmflag, 0, shmaddr, 0); +} + +long sys_pread(unsigned int fd, char *ubuf, u32 count, u64 pos) +{ + return sys_pread64(fd, ubuf, count, (u32)(pos & 0xffffffffu), (u32)(pos >> 32)); +} diff --git a/compel/arch/x86/plugins/std/syscalls/syscall_32.tbl b/compel/arch/x86/plugins/std/syscalls/syscall_32.tbl new file mode 100644 index 000000000..4f7e42194 --- /dev/null +++ b/compel/arch/x86/plugins/std/syscalls/syscall_32.tbl @@ -0,0 +1,95 @@ +# +# System calls table, please make sure the table consist only the syscalls +# really used somewhere in project. +# +# code name arguments +# ------------------------------------------------------------------------------------------------------------------------------------------------------------- +__NR_restart_syscall 0 sys_restart_syscall (void) +__NR_exit 1 sys_exit (unsigned long error_code) +__NR_read 3 sys_read (int fd, void *buf, unsigned long count) +__NR_write 4 sys_write (int fd, const void *buf, unsigned long count) +__NR_open 5 sys_open (const char *filename, int flags, unsigned int mode) +__NR_close 6 sys_close (int fd) +__NR_unlink 10 sys_unlink (char *pathname) +__NR_lseek 19 sys_lseek (int fd, s32 offset, unsigned int origin) +__NR_getpid 20 sys_getpid (void) +__NR_mount 21 sys_mount (const char *dev_name, const char *dir_name, const char *type, unsigned long flags, const void *data) +__NR_ptrace 26 sys_ptrace (long request, pid_t pid, void *addr, void *data) +__NR_kill 37 sys_kill (long pid, int sig) +__NR_mkdir 39 sys_mkdir (const char *name, int mode) +__NR_rmdir 40 sys_rmdir (const char *name) +__NR_brk 45 sys_brk (void *addr) +__NR_umount2 52 sys_umount2 (char *name, int flags) +__NR_ioctl 54 sys_ioctl (unsigned int fd, unsigned int cmd, unsigned long arg) +__NR_fcntl 55 sys_fcntl (unsigned int fd, unsigned int cmd, unsigned long arg) +__NR_umask 60 sys_umask (int mask) +__NR_setrlimit 75 sys_setrlimit (unsigned int resource, struct krlimit *rlim) +__NR_gettimeofday 78 sys_gettimeofday (struct timeval *tv, struct timezone *tz) +__NR_munmap 91 sys_munmap (void *addr, unsigned long len) +__NR_setpriority 97 sys_setpriority (int which, int who, int nice) +__NR_socketcall 102 sys_socketcall (int call, unsigned long *args) +__NR_setitimer 104 sys_setitimer (int which, struct itimerval *in, struct itimerval *out) +__NR_getitimer 105 sys_getitimer (int which, struct itimerval *it) +__NR_wait4 114 sys_wait4 (pid_t pid, int *stat_addr, int options, struct rusage *ru) +__NR_ipc 117 sys_ipc (unsigned int call, int first, unsigned long second, unsigned long third, void *ptr, long fifth) +__NR_clone 120 sys_clone (unsigned long flags, void *child_stack, void *parent_tid, void *child_tid) +__NR_mprotect 125 sys_mprotect (const void *addr, unsigned long len, unsigned long prot) +__NR_getpgid 132 sys_getpgid (pid_t pid) +__NR_personality 136 sys_personality (unsigned int personality) +__NR_flock 143 sys_flock (int fd, unsigned long cmd) +__NR_getsid 147 sys_getsid (void) +__NR_sched_setscheduler 156 sys_sched_setscheduler (int pid, int policy, struct sched_param *p) +__NR_nanosleep 162 sys_nanosleep (struct timespec *rqtp, struct timespec *rmtp) +__NR_mremap 163 sys_mremap (unsigned long addr, unsigned long old_len, unsigned long new_len, unsigned long flags, unsigned long new_addr) +__NR_prctl 172 sys_prctl (int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) +__NR_rt_sigreturn 173 sys_rt_sigreturn (void) +__NR_rt_sigaction 174 sys_sigaction (int signum, const rt_sigaction_t *act, rt_sigaction_t *oldact, size_t sigsetsize) +__NR_rt_sigprocmask 175 sys_sigprocmask (int how, k_rtsigset_t *set, k_rtsigset_t *oset, size_t sigsetsize) +__NR_rt_sigqueueinfo 178 sys_rt_sigqueueinfo (pid_t pid, int sig, siginfo_t *uinfo) +__NR_pread64 180 sys_pread64 (unsigned int fd, char *ubuf, u32 count, u32 poslo, u32 poshi) +__NR_capget 184 sys_capget (struct cap_header *h, struct cap_data *d) +__NR_capset 185 sys_capset (struct cap_header *h, struct cap_data *d) +__NR_sigaltstack 186 sys_sigaltstack (const void *uss_ptr, void *uoss_ptr) +__NR_mmap2 192 sys_mmap (void *addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) +__NR_getgroups32 205 sys_getgroups (int gsize, unsigned int *groups) +__NR_setgroups32 206 sys_setgroups (int gsize, unsigned int *groups) +__NR_setresuid32 208 sys_setresuid (int uid, int euid, int suid) +__NR_getresuid32 209 sys_getresuid (int *uid, int *euid, int *suid) +__NR_setresgid32 210 sys_setresgid (int gid, int egid, int sgid) +__NR_getresgid32 211 sys_getresgid (int *gid, int *egid, int *sgid) +__NR_setfsuid32 215 sys_setfsuid (int fsuid) +__NR_setfsgid32 216 sys_setfsgid (int fsgid) +__NR_mincore 218 sys_mincore (void *addr, unsigned long size, unsigned char *vec) +__NR_madvise 219 sys_madvise (unsigned long start, size_t len, int behavior) +__NR_gettid 224 sys_gettid (void) +__NR_futex 240 sys_futex (u32 *uaddr, int op, u32 val, struct timespec *utime, u32 *uaddr2, u32 val3) +__NR_set_thread_area 243 sys_set_thread_area (user_desc_t *info) +__NR_get_thread_area 244 sys_get_thread_area (user_desc_t *info) +__NR_io_setup 245 sys_io_setup (unsigned nr_reqs, aio_context_t *ctx32p) +__NR_io_getevents 247 sys_io_getevents (aio_context_t ctx_id, long min_nr, long nr, struct io_event *events, struct timespec *timeout) +__NR_io_submit 248 sys_io_submit (aio_context_t ctx_id, long nr, struct iocb **iocbpp) +__NR_exit_group 252 sys_exit_group (int error_code) +__NR_set_tid_address 258 sys_set_tid_address (int *tid_addr) +__NR_timer_create 259 sys_timer_create (clockid_t which_clock, struct sigevent *timer_event_spec, kernel_timer_t *created_timer_id) +__NR_timer_settime 260 sys_timer_settime (kernel_timer_t timer_id, int flags, struct itimerspec *new, struct itimerspec *old) +__NR_timer_gettime 261 sys_timer_gettime (int timer_id, struct itimerspec *setting) +__NR_timer_getoverrun 262 sys_timer_getoverrun (int timer_id) +__NR_timer_delete 263 sys_timer_delete (kernel_timer_t timer_id) +__NR_clock_gettime 265 sys_clock_gettime (int which_clock, struct timespec *tp) +__NR_waitid 284 sys_waitid (int which, pid_t pid, struct siginfo *infop, int options, struct rusage *ru) +__NR_openat 295 sys_openat (int dfd, const char *filename, int flags, int mode) +__NR_readlinkat 305 sys_readlinkat (int fd, const char *path, char *buf, int bufsize) +__NR_set_robust_list 311 sys_set_robust_list (struct robust_list_head *head, size_t len) +__NR_get_robust_list 312 sys_get_robust_list (int pid, struct robust_list_head **head_ptr, size_t *len_ptr) +__NR_vmsplice 316 sys_vmsplice (int fd, const struct iovec *iov, unsigned int nr_segs, unsigned int flags) +__NR_signalfd 321 sys_signalfd (int ufd, const k_rtsigset_t *sigmask, size_t sigsetsize) +__NR_timerfd_settime 325 sys_timerfd_settime (int ufd, int flags, const struct itimerspec *utmr, struct itimerspec *otmr) +__NR_rt_tgsigqueueinfo 335 sys_rt_tgsigqueueinfo (pid_t tgid, pid_t pid, int sig, siginfo_t *uinfo) +__NR_fanotify_init 338 sys_fanotify_init (unsigned int flags, unsigned int event_f_flags) +__NR_fanotify_mark 339 sys_fanotify_mark (int fanotify_fd, unsigned int flag, u32 mask, int dfd, const char *pathname) +__NR_open_by_handle_at 342 sys_open_by_handle_at (int mountdirfd, struct file_handle *handle, int flags) +__NR_setns 346 sys_setns (int fd, int nstype) +__NR_kcmp 349 sys_kcmp (pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2) +__NR_seccomp 354 sys_seccomp (unsigned int op, unsigned int flags, const char *uargs) +__NR_memfd_create 356 sys_memfd_create (const char *name, unsigned int flags) +__NR_userfaultfd 374 sys_userfaultfd (int flags) diff --git a/compel/arch/x86/plugins/std/syscalls/syscall_64.tbl b/compel/arch/x86/plugins/std/syscalls/syscall_64.tbl new file mode 100644 index 000000000..9a36b6826 --- /dev/null +++ b/compel/arch/x86/plugins/std/syscalls/syscall_64.tbl @@ -0,0 +1,106 @@ +# +# System calls table, please make sure the table consist only the syscalls +# really used somewhere in project. +# +# __NR_name code name arguments +# ------------------------------------------------------------------------------------------------------------------------------------------------------------- +__NR_read 0 sys_read (int fd, void *buf, unsigned long count) +__NR_write 1 sys_write (int fd, const void *buf, unsigned long count) +__NR_open 2 sys_open (const char *filename, unsigned long flags, unsigned long mode) +__NR_close 3 sys_close (int fd) +__NR_lseek 8 sys_lseek (int fd, unsigned long offset, unsigned long origin) +__NR_mmap 9 sys_mmap (void *addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long offset) +__NR_mprotect 10 sys_mprotect (const void *addr, unsigned long len, unsigned long prot) +__NR_munmap 11 sys_munmap (void *addr, unsigned long len) +__NR_brk 12 sys_brk (void *addr) +__NR_rt_sigaction 13 sys_sigaction (int signum, const rt_sigaction_t *act, rt_sigaction_t *oldact, size_t sigsetsize) +__NR_rt_sigprocmask 14 sys_sigprocmask (int how, k_rtsigset_t *set, k_rtsigset_t *old, size_t sigsetsize) +__NR_rt_sigreturn 15 sys_rt_sigreturn (void) +__NR_ioctl 16 sys_ioctl (unsigned int fd, unsigned int cmd, unsigned long arg) +__NR_pread64 17 sys_pread (unsigned int fd, char *buf, size_t count, loff_t pos) +__NR_mremap 25 sys_mremap (unsigned long addr, unsigned long old_len, unsigned long new_len, unsigned long flags, unsigned long new_addr) +__NR_mincore 27 sys_mincore (void *addr, unsigned long size, unsigned char *vec) +__NR_madvise 28 sys_madvise (unsigned long start, size_t len, int behavior) +__NR_shmat 30 sys_shmat (int shmid, void *shmaddr, int shmflag) +__NR_dup2 33 sys_dup2 (int oldfd, int newfd) +__NR_nanosleep 35 sys_nanosleep (struct timespec *req, struct timespec *rem) +__NR_getitimer 36 sys_getitimer (int which, const struct itimerval *val) +__NR_setitimer 38 sys_setitimer (int which, const struct itimerval *val, struct itimerval *old) +__NR_getpid 39 sys_getpid (void) +__NR_socket 41 sys_socket (int domain, int type, int protocol) +__NR_connect 42 sys_connect (int sockfd, struct sockaddr *addr, int addrlen) +__NR_sendto 44 sys_sendto (int sockfd, void *buff, size_t len, unsigned int flags, struct sockaddr *addr, int addr_len) +__NR_recvfrom 45 sys_recvfrom (int sockfd, void *ubuf, size_t size, unsigned int flags, struct sockaddr *addr, int *addr_len) +__NR_sendmsg 46 sys_sendmsg (int sockfd, const struct msghdr *msg, int flags) +__NR_recvmsg 47 sys_recvmsg (int sockfd, struct msghdr *msg, int flags) +__NR_shutdown 48 sys_shutdown (int sockfd, int how) +__NR_bind 49 sys_bind (int sockfd, const struct sockaddr *addr, int addrlen) +__NR_setsockopt 54 sys_setsockopt (int sockfd, int level, int optname, const void *optval, socklen_t optlen) +__NR_getsockopt 55 sys_getsockopt (int sockfd, int level, int optname, const void *optval, socklen_t *optlen) +__NR_clone 56 sys_clone (unsigned long flags, void *child_stack, void *parent_tid, void *child_tid) +__NR_exit 60 sys_exit (unsigned long error_code) +__NR_wait4 61 sys_wait4 (int pid, int *status, int options, struct rusage *ru) +__NR_kill 62 sys_kill (long pid, int sig) +__NR_fcntl 72 sys_fcntl (int fd, int type, long arg) +__NR_flock 73 sys_flock (int fd, unsigned long cmd) +__NR_mkdir 83 sys_mkdir (const char *name, int mode) +__NR_rmdir 84 sys_rmdir (const char *name) +__NR_unlink 87 sys_unlink (char *pathname) +__NR_umask 95 sys_umask (int mask) +__NR_gettimeofday 96 sys_gettimeofday (struct timeval *tv, struct timezone *tz) +__NR_ptrace 101 sys_ptrace (long request, pid_t pid, void *addr, void *data) +__NR_getgroups 115 sys_getgroups (int gsize, unsigned int *groups) +__NR_setgroups 116 sys_setgroups (int gsize, unsigned int *groups) +__NR_setresuid 117 sys_setresuid (int uid, int euid, int suid) +__NR_getresuid 118 sys_getresuid (int *uid, int *euid, int *suid) +__NR_setresgid 119 sys_setresgid (int gid, int egid, int sgid) +__NR_getresgid 120 sys_getresgid (int *gid, int *egid, int *sgid) +__NR_getpgid 121 sys_getpgid (pid_t pid) +__NR_setfsuid 122 sys_setfsuid (int fsuid) +__NR_setfsgid 123 sys_setfsgid (int fsgid) +__NR_getsid 124 sys_getsid (void) +__NR_capget 125 sys_capget (struct cap_header *h, struct cap_data *d) +__NR_capset 126 sys_capset (struct cap_header *h, struct cap_data *d) +__NR_rt_sigqueueinfo 129 sys_rt_sigqueueinfo (pid_t pid, int sig, siginfo_t *info) +__NR_sigaltstack 131 sys_sigaltstack (const void *uss, void *uoss) +__NR_personality 135 sys_personality (unsigned int personality) +__NR_setpriority 141 sys_setpriority (int which, int who, int nice) +__NR_sched_setscheduler 144 sys_sched_setscheduler (int pid, int policy, struct sched_param *p) +__NR_prctl 157 sys_prctl (int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) +__NR_arch_prctl 158 sys_arch_prctl (int option, unsigned long addr) +__NR_setrlimit 160 sys_setrlimit (int resource, struct krlimit *rlim) +__NR_mount 165 sys_mount (char *dev_nmae, char *dir_name, char *type, unsigned long flags, void *data) +__NR_umount2 166 sys_umount2 (char *name, int flags) +__NR_gettid 186 sys_gettid (void) +__NR_futex 202 sys_futex (u32 *uaddr, int op, u32 val, struct timespec *utime, u32 *uaddr2, u32 val3) +__NR_set_thread_area 205 sys_set_thread_area (user_desc_t *info) +__NR_io_setup 206 sys_io_setup (unsigned nr_events, aio_context_t *ctx) +__NR_io_getevents 208 sys_io_getevents (aio_context_t ctx, long min_nr, long nr, struct io_event *evs, struct timespec *tmo) +__NR_io_submit 209 sys_io_submit (aio_context_t ctx, long nr, struct iocb **iocbpp) +__NR_get_thread_area 211 sys_get_thread_area (user_desc_t *info) +__NR_set_tid_address 218 sys_set_tid_address (int *tid_addr) +__NR_restart_syscall 219 sys_restart_syscall (void) +__NR_sys_timer_create 222 sys_timer_create (clockid_t which_clock, struct sigevent *timer_event_spec, kernel_timer_t *created_timer_id) +__NR_sys_timer_settime 223 sys_timer_settime (kernel_timer_t timer_id, int flags, const struct itimerspec *new_setting, struct itimerspec *old_setting) +__NR_sys_timer_gettime 224 sys_timer_gettime (int timer_id, const struct itimerspec *setting) +__NR_sys_timer_getoverrun 225 sys_timer_getoverrun (int timer_id) +__NR_sys_timer_delete 226 sys_timer_delete (kernel_timer_t timer_id) +__NR_clock_gettime 228 sys_clock_gettime (const clockid_t which_clock, const struct timespec *tp) +__NR_exit_group 231 sys_exit_group (int error_code) +__NR_openat 257 sys_openat (int dfd, const char *filename, int flags, int mode) +__NR_waitid 247 sys_waitid (int which, pid_t pid, struct siginfo *infop, int options, struct rusage *ru) +__NR_readlinkat 267 sys_readlinkat (int fd, const char *path, char *buf, int bufsize) +__NR_set_robust_list 273 sys_set_robust_list (struct robust_list_head *head, size_t len) +__NR_get_robust_list 274 sys_get_robust_list (int pid, struct robust_list_head **head_ptr, size_t *len_ptr) +__NR_seccomp 317 sys_seccomp (unsigned int op, unsigned int flags, const char *uargs) +__NR_vmsplice 278 sys_vmsplice (int fd, const struct iovec *iov, unsigned long nr_segs, unsigned int flags) +__NR_timerfd_settime 286 sys_timerfd_settime (int ufd, int flags, const struct itimerspec *utmr, struct itimerspec *otmr) +__NR_signalfd4 289 sys_signalfd (int fd, k_rtsigset_t *mask, size_t sizemask, int flags) +__NR_rt_tgsigqueueinfo 297 sys_rt_tgsigqueueinfo (pid_t tgid, pid_t pid, int sig, siginfo_t *info) +__NR_fanotify_init 300 sys_fanotify_init (unsigned int flags, unsigned int event_f_flags) +__NR_fanotify_mark 301 sys_fanotify_mark (int fanotify_fd, unsigned int flags, u64 mask, int dfd, const char *pathname) +__NR_open_by_handle_at 304 sys_open_by_handle_at (int mountdirfd, struct file_handle *handle, int flags) +__NR_setns 308 sys_setns (int fd, int nstype) +__NR_kcmp 312 sys_kcmp (pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2) +__NR_memfd_create 319 sys_memfd_create (const char *name, unsigned int flags) +__NR_userfaultfd 323 sys_userfaultfd (int flags) diff --git a/compel/arch/x86/scripts/pack.lds.S b/compel/arch/x86/scripts/pack.lds.S new file mode 100644 index 000000000..3b94b3ecd --- /dev/null +++ b/compel/arch/x86/scripts/pack.lds.S @@ -0,0 +1,30 @@ +OUTPUT_ARCH(i386:x86-64) +SECTIONS +{ + . = ALIGN(64); + .text : { + *(.compel.prologue.text) + *(.text*) + } =0x0 + + . = ALIGN(64); + .compel.init : { + *(.compel.init) + } =0xff + + . = ALIGN(64); + .data : { + *(.data*) + *(.bss*) + *(.rodata*) + } =0x0 + + /DISCARD/ : { + *(.debug*) + *(.comment*) + *(.note*) + *(.group*) + *(.eh_frame*) + *(*) + } +} diff --git a/compel/plugins/Makefile b/compel/plugins/Makefile new file mode 100644 index 000000000..f0b1de802 --- /dev/null +++ b/compel/plugins/Makefile @@ -0,0 +1,127 @@ +.PHONY: .FORCE + +ARCH_DIR := compel/arch/$(ARCH)/plugins + +ccflags-y += -iquote $(obj)/include/ +ccflags-y += -iquote $(obj)/include/uapi +ccflags-y += -iquote $(SRC_DIR)/criu/include +ccflags-y += -iquote $(SRC_DIR)/criu/arch/$(ARCH)/include +ccflags-y += -iquote $(SRC_DIR)/compel/include +ccflags-y += -iquote $(SRC_DIR)/$(ARCH_DIR)/include + +asflags-y += -iquote $(SRC_DIR)/criu/arch/$(ARCH)/include +asflags-y += -iquote $(SRC_DIR)/compel/plugins/include/uapi +asflags-y += -iquote $(SRC_DIR)/$(ARCH_DIR) + +# +# STD plugin +target += std +std-obj-y += std/std.o +std-obj-y += std/string.o +std-obj-y += arch/$(ARCH)/plugins/std/syscalls-64.o +std-obj-y += arch/$(ARCH)/plugins/std/calls32.o + +sys-proto-generic := $(obj)/include/uapi/std/syscall.h +sys-codes-generic := $(obj)/include/uapi/std/syscall-codes.h +sys-codes = $(obj)/include/uapi/std/syscall-codes-$(1).h +sys-proto = $(obj)/include/uapi/std/syscall-$(1).h +sys-def = $(ARCH_DIR)/std/syscalls/syscall_$(1).tbl +sys-asm = $(ARCH_DIR)/std/syscalls-$(1).S +sys-asm-common-name = std/syscalls/syscall-common-x86-$(1).S +sys-asm-common = $(ARCH_DIR)/$(sys-asm-common-name) + +sys-bits := 64 + +AV := $$$$ + +define gen-rule-sys-codes +$(sys-codes): $(sys-def) + $(call msg-gen, $$@) + $(Q) echo "/* Autogenerated, don't edit */" > $$@ + $(Q) echo "#ifndef ASM_SYSCALL_CODES_H_$(1)__" >> $$@ + $(Q) echo "#define ASM_SYSCALL_CODES_H_$(1)__" >> $$@ + $(Q) cat $$< | awk '/^__NR/{SYSN=$(AV)1; \ + sub("^__NR", "SYS", SYSN); \ + print "\n#ifndef ", $(AV)1; \ + print "#define", $(AV)1, $(AV)2; \ + print "#endif"; \ + print "\n#ifndef ", SYSN; \ + print "#define ", SYSN, $(AV)1; \ + print "#endif";}' >> $$@ + $(Q) echo "#endif /* ASM_SYSCALL_CODES_H_$(1)__ */" >> $$@ +endef + +define gen-rule-sys-proto +$(sys-proto): $(sys-def) + $(call msg-gen, $$@) + $(Q) echo "/* Autogenerated, don't edit */" > $$@ + $(Q) echo "#ifndef ASM_SYSCALL_PROTO_H_$(1)__" >> $$@ + $(Q) echo "#define ASM_SYSCALL_PROTO_H_$(1)__" >> $$@ + $(Q) echo '#include "std/syscall-codes-$(1).h"' >> $$@ + $(Q) echo '#include "syscall-types.h"' >> $$@ +ifeq ($(1),32) + $(Q) echo '#include "asm/syscall32.h"' >> $$@ +endif + $(Q) cat $$< | awk '/^__NR/{print "extern long", $(AV)3, \ + substr($(AV)0, index($(AV)0,$(AV)4)), ";"}' >> $$@ + $(Q) echo "#endif /* ASM_SYSCALL_PROTO_H_$(1)__ */" >> $$@ +endef + +define gen-rule-sys-asm +$(sys-asm): $(sys-def) $(sys-asm-common) $(sys-codes) $(sys-proto) + $(call msg-gen, $$@) + $(Q) echo "/* Autogenerated, don't edit */" > $$@ + $(Q) echo '#include "std/syscall-codes-$(1).h"' >> $$@ + $(Q) echo '#include "$(sys-asm-common-name)"' >> $$@ + $(Q) cat $$< | awk '/^__NR/{print "SYSCALL(", $(AV)3, ",", $(AV)2, ")"}' >> $$@ +endef + +define gen-rule-sys-exec-tbl +$(sys-exec-tbl): $(sys-def) $(sys-codes) $(sys-proto) $(sys-proto-generic) + $(call msg-gen, $$@) + $(Q) echo "/* Autogenerated, don't edit */" > $$@ + $(Q) cat $$< | awk '/^__NR/{print \ + "SYSCALL(", substr($(AV)3, 5), ",", $(AV)2, ")"}' >> $$@ +endef + +$(sys-codes-generic): $(ARCH_DIR)/std/syscalls/syscall_32.tbl + $(call msg-gen, $@) + $(Q) echo "/* Autogenerated, don't edit */" > $@ + $(Q) echo "#ifndef __ASM_CR_SYSCALL_CODES_H__" >> $@ + $(Q) echo "#define __ASM_CR_SYSCALL_CODES_H__" >> $@ + $(Q) echo '#include "std/syscall-codes-64.h"' >> $@ + $(Q) cat $< | awk '/^__NR/{NR32=$$1; \ + sub("^__NR", "__NR32", NR32); \ + print "\n#ifndef ", NR32; \ + print "#define ", NR32, $$2; \ + print "#endif";}' >> $@ + $(Q) echo "#endif /* __ASM_CR_SYSCALL_CODES_H__ */" >> $@ + +$(sys-proto-generic): $(strip $(call map,sys-proto,$(sys-bits))) + $(call msg-gen, $@) + $(Q) echo "/* Autogenerated, don't edit */" > $@ + $(Q) echo "#ifndef __ASM_CR_SYSCALL_PROTO_H__" >> $@ + $(Q) echo "#define __ASM_CR_SYSCALL_PROTO_H__" >> $@ + $(Q) echo "" >> $@ + $(Q) echo "#ifdef CONFIG_X86_32" >> $@ + $(Q) echo '#include "std/syscall-32.h"' >> $@ + $(Q) echo "#else" >> $@ + $(Q) echo '#include "std/syscall-64.h"' >> $@ + $(Q) echo "#endif /* CONFIG_X86_32 */" >> $@ + $(Q) echo "" >> $@ + $(Q) echo "#endif /* __ASM_CR_SYSCALL_PROTO_H__ */" >> $@ + +$(eval $(call map,gen-rule-sys-codes,$(sys-bits))) +$(eval $(call map,gen-rule-sys-proto,$(sys-bits))) +$(eval $(call map,gen-rule-sys-asm,$(sys-bits))) + +std-headers-deps += $(call sys-codes,$(sys-bits)) +std-headers-deps += $(call sys-proto,$(sys-bits)) +std-headers-deps += $(call sys-asm,$(sys-bits)) +std-headers-deps += $(sys-codes-generic) +std-headers-deps += $(sys-proto-generic) + +$(addprefix $(obj)/,$(std-obj-y:%.o=%.d)): | $(std-headers-deps) +$(addprefix $(obj)/,$(std-obj-y:%.o=%.i)): | $(std-headers-deps) +$(addprefix $(obj)/,$(std-obj-y:%.o=%.s)): | $(std-headers-deps) +$(addprefix $(obj)/,$(std-obj-y)): | $(std-headers-deps) diff --git a/compel/plugins/include/uapi/plugin-std.h b/compel/plugins/include/uapi/plugin-std.h new file mode 100644 index 000000000..292db8839 --- /dev/null +++ b/compel/plugins/include/uapi/plugin-std.h @@ -0,0 +1,6 @@ +#ifndef COMPEL_PLUGIN_STD_STD_H__ +#define COMPEL_PLUGIN_STD_STD_H__ + +#include "uapi/std/syscall.h" + +#endif /* COMPEL_PLUGIN_STD_STD_H__ */ diff --git a/compel/plugins/include/uapi/std/string.h b/compel/plugins/include/uapi/std/string.h new file mode 100644 index 000000000..8aec886bd --- /dev/null +++ b/compel/plugins/include/uapi/std/string.h @@ -0,0 +1,28 @@ +#ifndef COMPEL_PLUGIN_STD_STRING_H__ +#define COMPEL_PLUGIN_STD_STRING_H__ + +#include +#include +#include + +/* Standard file descriptors. */ +#define STDIN_FILENO 0 /* Standard input. */ +#define STDOUT_FILENO 1 /* Standard output. */ +#define STDERR_FILENO 2 /* Standard error output. */ + + +extern void __std_putc(int fd, char c); +extern void __std_puts(int fd, const char *s); +extern void __std_printk(int fd, const char *format, va_list args); +extern void __std_printf(int fd, const char *format, ...); + +#define std_printf(fmt, ...) __std_printf(STDOUT_FILENO, fmt, ##__VA_ARGS__) +#define std_puts(s) __std_puts(STDOUT_FILENO, s) +#define std_putchar(c) __std_putc(STDOUT_FILENO, c) + +extern unsigned long std_strtoul(const char *nptr, char **endptr, int base); +extern void *std_memcpy(void *to, const void *from, unsigned int n); +extern int std_memcmp(const void *cs, const void *ct, size_t count); +extern int std_strcmp(const char *cs, const char *ct); + +#endif /* COMPEL_PLUGIN_STD_STRING_H__ */ diff --git a/compel/plugins/include/uapi/std/syscall-types.h b/compel/plugins/include/uapi/std/syscall-types.h new file mode 100644 index 000000000..1b8188299 --- /dev/null +++ b/compel/plugins/include/uapi/std/syscall-types.h @@ -0,0 +1,55 @@ +/* + * Please add here type definitions if + * syscall prototypes need them. + */ + +#ifndef COMPEL_SYSCALL_TYPES_H__ +#define COMPEL_SYSCALL_TYPES_H__ + +#include +#include +#include +#include +#include +#include +#include + +struct cap_header { + u32 version; + int pid; +}; + +struct cap_data { + u32 eff; + u32 prm; + u32 inh; +}; + +struct robust_list_head; +struct file_handle; +struct itimerspec; +struct io_event; +struct sockaddr; +struct timespec; +struct siginfo; +struct msghdr; +struct rusage; +struct iocb; + +typedef unsigned long aio_context_t; + +#ifndef F_GETFD +# define F_GETFD 1 +#endif + +struct krlimit { + unsigned long rlim_cur; + unsigned long rlim_max; +}; + +/* Type of timers in the kernel. */ +typedef int kernel_timer_t; + +#include "asm/std/syscall-types.h" + +#endif /* COMPEL_SYSCALL_TYPES_H__ */ diff --git a/compel/plugins/std/std.c b/compel/plugins/std/std.c new file mode 100644 index 000000000..b3ea971f9 --- /dev/null +++ b/compel/plugins/std/std.c @@ -0,0 +1,89 @@ +#include + +#include "uapi/int.h" +#include "uapi/plugins.h" +#include "uapi/plugin-std.h" + +extern int main(void *arg_p, unsigned int arg_s); + +static struct prologue_init_args *init_args; +static int ctl_socket = -1; + +int std_ctl_sock(void) +{ + return ctl_socket; +} + +static int init_socket(struct prologue_init_args *args) +{ + int ret; + + ctl_socket = sys_socket(PF_UNIX, SOCK_SEQPACKET, 0); + if (ctl_socket < 0) + return ctl_socket; + + ret = sys_connect(ctl_socket, (struct sockaddr *)&args->ctl_sock_addr, args->ctl_sock_addr_len); + if (ret < 0) + return ret; + + return 0; +} + +static int fini_socket(void) +{ + char buf[32]; + int ret = 0; + + ret = sys_shutdown(ctl_socket, SHUT_WR); + if (ret) + goto err; + + ret = sys_recvfrom(ctl_socket, buf, sizeof(buf), MSG_WAITALL, 0, 0); + if (ret) + goto err; +err: + sys_close(ctl_socket); + ctl_socket = -1; + return ret; +} + +#define plugin_init_count(size) ((size) / (sizeof(plugin_init_t *))) + +int __export_std_compel_start(struct prologue_init_args *args, + const plugin_init_t * const *init_array, + size_t init_size) +{ + unsigned int i; + int ret = 0; + + init_args = args; + + ret = init_socket(args); + if (ret) + return ret; + + for (i = 0; i < plugin_init_count(init_size); i++) { + const plugin_init_t *d = init_array[i]; + + if (d && d->init) { + ret = d->init(); + if (ret) + break; + } + } + + if (!ret) + ret = main(args->arg_p, args->arg_s); + + for (; i > 0; i--) { + const plugin_init_t *d = init_array[i - 1]; + + if (d && d->exit) + d->exit(); + } + + fini_socket(); + return ret; +} + +PLUGIN_REGISTER_DUMMY(std) diff --git a/compel/plugins/std/string.c b/compel/plugins/std/string.c new file mode 100644 index 000000000..f4181f92a --- /dev/null +++ b/compel/plugins/std/string.c @@ -0,0 +1,262 @@ +#include +#include +#include + +#include "uapi/std/syscall.h" +#include "uapi/std/string.h" + +static const char conv_tab[] = "0123456789abcdefghijklmnopqrstuvwxyz"; + +void __std_putc(int fd, char c) +{ + sys_write(fd, &c, 1); +} + +void __std_puts(int fd, const char *s) +{ + for (; *s; s++) + __std_putc(fd, *s); +} + +static size_t __std_vprint_long_hex(char *buf, size_t blen, unsigned long num, char **ps) +{ + char *s = &buf[blen - 2]; + + buf[blen - 1] = '\0'; + + if (num == 0) { + *s = '0', s--; + goto done; + } + + while (num > 0) { + *s = conv_tab[num % 16], s--; + num /= 16; + } + +done: + s++; + *ps = s; + return blen - (s - buf); +} + +static size_t __std_vprint_long(char *buf, size_t blen, long num, char **ps) +{ + char *s = &buf[blen - 2]; + int neg = 0; + + buf[blen - 1] = '\0'; + + if (num < 0) { + neg = 1; + num = -num; + } else if (num == 0) { + *s = '0'; + s--; + goto done; + } + + while (num > 0) { + *s = (num % 10) + '0'; + s--; + num /= 10; + } + + if (neg) { + *s = '-'; + s--; + } +done: + s++; + *ps = s; + return blen - (s - buf); +} + +void __std_printk(int fd, const char *format, va_list args) +{ + const char *s = format; + + for (; *s != '\0'; s++) { + char buf[32], *t; + int along = 0; + + if (*s != '%') { + __std_putc(fd, *s); + continue; + } + + s++; + if (*s == 'l') { + along = 1; + s++; + if (*s == 'l') + s++; + } + + switch (*s) { + case 's': + __std_puts(fd, va_arg(args, char *)); + break; + case 'd': + __std_vprint_long(buf, sizeof(buf), + along ? + va_arg(args, long) : + (long)va_arg(args, int), + &t); + __std_puts(fd, t); + break; + case 'x': + __std_vprint_long_hex(buf, sizeof(buf), + along ? + va_arg(args, long) : + (long)va_arg(args, int), + &t); + __std_puts(fd, t); + break; + } + } +} + +void __std_printf(int fd, const char *format, ...) +{ + va_list args; + + va_start(args, format); + __std_printk(fd, format, args); + va_end(args); +} + +static inline bool __isspace(unsigned char c) +{ + return c == ' ' || c == '\f' || + c == '\n' || c == '\r' || + c == '\t' || c == '\v'; +} + +static unsigned char __tolower(unsigned char c) +{ + return (c <= 'Z' && c >= 'A') ? c - 'A' + 'a' : c; +} + +static inline bool __isalpha(unsigned char c) +{ + return ((c <= 'Z' && c >= 'A') || + (c <= 'z' && c >= 'a')); +} + +static inline bool __isdigit(unsigned char c) +{ + return (c <= '9' && c >= '0'); +} + +static inline bool __isalnum(unsigned char c) +{ + return (__isalpha(c) || __isdigit(c)); +} + +static unsigned int __conv_val(unsigned char c) +{ + if (__isdigit(c)) + return c - '0'; + else if (__isalpha(c)) + return &conv_tab[__tolower(c)] - conv_tab; + return -1u; +} + +unsigned long std_strtoul(const char *nptr, char **endptr, int base) +{ + const char *s = nptr; + bool neg = false; + unsigned int v; + long num = 0; + + if (base < 0 || base == 1 || base > 36) + goto fin; + + while (__isspace(*s)) + s++; + if (!*s) + goto fin; + + if (*s == '-') + neg = true, s++; + + if (base == 0) { + if (s[0] == '0') { + unsigned char p = __tolower(s[1]); + switch (p) { + case 'b': + base = 2, s += 2; + break; + case 'x': + base = 16, s += 2; + break; + default: + base = 8, s += 1; + break; + } + } else + base = 10; + } else if (base == 16) { + if (s[0] == '0' && __tolower(s[1]) == 'x') + s += 2; + } + + for (; *s; s++) { + if (__isspace(*s)) + continue; + if (!__isalnum(*s)) + goto fin; + v = __conv_val(*s); + if (v == -1u || v > base) + goto fin; + num *= base; + num += v; + } + +fin: + if (endptr) + *endptr = (char *)s; + return neg ? (unsigned long)-num : (unsigned long)num; +} + +void *std_memcpy(void *to, const void *from, unsigned int n) +{ + int d0, d1, d2; + asm volatile("rep ; movsl \n" + "movl %4,%%ecx \n" + "andl $3,%%ecx \n" + "jz 1f \n" + "rep ; movsb \n" + "1:" + : "=&c" (d0), "=&D" (d1), "=&S" (d2) + : "0" (n / 4), "g" (n), "1" ((long)to), "2" ((long)from) + : "memory"); + return to; +} + +int std_memcmp(const void *cs, const void *ct, size_t count) +{ + const unsigned char *su1, *su2; + int res = 0; + + for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--) + if ((res = *su1 - *su2) != 0) + break; + return res; +} + +int std_strcmp(const char *cs, const char *ct) +{ + unsigned char c1, c2; + + while (1) { + c1 = *cs++; + c2 = *ct++; + if (c1 != c2) + return c1 < c2 ? -1 : 1; + if (!c1) + break; + } + return 0; +}