123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020 |
- /* -*- mode:c; c-file-style:"k&r"; c-basic-offset: 4; tab-width:4; indent-tabs-mode:nil; mode:auto-fill; fill-column:78; -*- */
- /* vim: set ts=4 sw=4 et tw=78 fo=cqt wm=0: */
- /* Copyright (C) 2014 OSCAR lab, Stony Brook University
- This file is part of Graphene Library OS.
- Graphene Library OS is free software: you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation, either version 3 of the
- License, or (at your option) any later version.
- Graphene Library OS is distributed in the hope that 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.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
- /*
- * shim_parser.c
- *
- * This file contains codes for parsing system call arguements for debug
- * purpose.
- */
- #include <shim_internal.h>
- #include <shim_tls.h>
- #include <shim_table.h>
- #include <shim_thread.h>
- #include <shim_utils.h>
- #include <pal.h>
- #include <pal_error.h>
- #include <errno.h>
- #include <asm/fcntl.h>
- #include <asm/unistd.h>
- #include <asm/prctl.h>
- #include <asm/mman.h>
- #include <asm/ioctls.h>
- #include <linux/stat.h>
- #include <linux/fcntl.h>
- #include <linux/sched.h>
- #include <linux/futex.h>
- #include <linux/wait.h>
- #include <linux/in.h>
- #include <linux/in6.h>
- #include <linux/un.h>
- static void parse_open_flags (const char *, va_list *);
- static void parse_open_mode (const char *, va_list *);
- static void parse_access_mode (const char *, va_list *);
- static void parse_clone_flags (const char *, va_list *);
- static void parse_mmap_prot (const char *, va_list *);
- static void parse_mmap_flags (const char *, va_list *);
- static void parse_exec_args (const char *, va_list *);
- static void parse_exec_envp (const char *, va_list *);
- static void parse_pipe_fds (const char *, va_list *);
- static void parse_signum (const char *, va_list *);
- static void parse_sigmask (const char *, va_list *);
- static void parse_sigprocmask_how (const char *, va_list *);
- static void parse_timespec (const char *, va_list *);
- static void parse_sockaddr (const char *, va_list *);
- static void parse_futexop (const char *, va_list *);
- static void parse_ioctlop (const char *, va_list *);
- static void parse_seek (const char *, va_list *);
- static void parse_at_fdcwd (const char *, va_list *);
- static void parse_wait_option (const char *, va_list *);
- struct parser_table {
- int slow;
- int stop;
- void (*parser[6]) (const char *, va_list *);
- } syscall_parser_table[SHIM_NSYSCALLS] = {
- { .slow = 1, .parser = { NULL } }, /* read */
- { .slow = 1, .parser = { NULL } }, /* write */
- { .slow = 1, /* open */
- .parser = { NULL, &parse_open_flags, &parse_open_mode, } },
- { .slow = 0, .parser = { NULL } }, /* close */
- { .slow = 0, .parser = { NULL } }, /* stat */
- { .slow = 0, .parser = { NULL } }, /* fstat */
- { .slow = 0, .parser = { NULL } }, /* lstat */
- { .slow = 1, .parser = { NULL } }, /* poll */
- { .slow = 0, .parser = { NULL, NULL, &parse_seek } }, /* lseek */
- { .slow = 1, /* mmap */
- .parser = { NULL, NULL, &parse_mmap_prot, &parse_mmap_flags } },
- { .slow = 1, /* mprotect */
- .parser = { NULL, NULL, &parse_mmap_prot } },
- { .slow = 1, .parser = { NULL } }, /* munmap */
- { .slow = 0, .parser = { NULL } }, /* brk */
- { .slow = 0, .parser = { &parse_signum } }, /* rt_sigaction */
- { .slow = 0, /* rt_sigprocmask */
- .parser = { &parse_sigprocmask_how, &parse_sigmask, &parse_sigmask } },
- { .slow = 0, .parser = { NULL } }, /* rt_sigreturn */
- { .slow = 1, .parser = { NULL, &parse_ioctlop } }, /* ioctl */
- { .slow = 1, .parser = { NULL } }, /* pread64 */
- { .slow = 0, .parser = { NULL } }, /* pwrite64 */
- { .slow = 1, .parser = { NULL } }, /* readv */
- { .slow = 0, .parser = { NULL } }, /* writev */
- { .slow = 0, /* access */
- .parser = { NULL, &parse_access_mode } },
- { .slow = 0, /* pipe */
- .parser = { &parse_pipe_fds } },
- { .slow = 0, .parser = { NULL } }, /* select */
- { .slow = 0, .parser = { NULL } }, /* sched_yield */
- { .slow = 0, .parser = { NULL } }, /* mremap */
- { .slow = 0, .parser = { NULL } }, /* msync */
- { .slow = 0, .parser = { NULL } }, /* mincore */
- { .slow = 0, .parser = { NULL } }, /* madvise */
- { .slow = 0, .parser = { NULL } }, /* shmget */
- { .slow = 0, .parser = { NULL } }, /* shmat */
- { .slow = 0, .parser = { NULL } }, /* shmctl */
- { .slow = 0, .parser = { NULL } }, /* dup */
- { .slow = 0, .parser = { NULL } }, /* dup2 */
- { .slow = 0, .parser = { NULL } }, /* pause */
- { .slow = 1,
- .parser = { &parse_timespec } }, /* nanosleep */
- { .slow = 0, .parser = { NULL } }, /* getitimer */
- { .slow = 0, .parser = { NULL } }, /* alarm */
- { .slow = 0, .parser = { NULL } }, /* setitimer */
- { .slow = 0, .parser = { NULL } }, /* getpid */
- { .slow = 0, .parser = { NULL } }, /* sendfile */
- { .slow = 0, .parser = { NULL } }, /* socket */
- { .slow = 1, .parser = { NULL, &parse_sockaddr } }, /* connect */
- { .slow = 1, .parser = { NULL } }, /* accept */
- { .slow = 0, .parser = { NULL } }, /* sendto */
- { .slow = 0, .parser = { NULL } }, /* recvfrom */
- { .slow = 0, .parser = { NULL } }, /* sendmsg */
- { .slow = 1, .parser = { NULL } }, /* recvmsg */
- { .slow = 0, .parser = { NULL } }, /* shutdown */
- { .slow = 0, .parser = { NULL } }, /* bind */
- { .slow = 0, .parser = { NULL } }, /* listen */
- { .slow = 0, .parser = { NULL } }, /* getsockname */
- { .slow = 0, .parser = { NULL } }, /* getpeername */
- { .slow = 0, .stop = 3, /* socketpair */
- .parser = { NULL, NULL, NULL, &parse_pipe_fds } },
- { .slow = 0, .parser = { NULL } }, /* setsockopt */
- { .slow = 0, .parser = { NULL } }, /* getsockopt */
- { .slow = 1, .parser = { &parse_clone_flags } }, /* clone */
- { .slow = 1, .parser = { NULL } }, /* fork */
- { .slow = 1, .parser = { NULL } }, /* vfork */
- { .slow = 1, /* execve */
- .parser = { NULL, &parse_exec_args, &parse_exec_envp, } },
- { .slow = 0, .parser = { NULL } }, /* exit */
- { .slow = 1, .parser = { NULL, NULL,
- &parse_wait_option,
- NULL } }, /* wait4 */
- { .slow = 0, .parser = { NULL, &parse_signum, } }, /* kill */
- { .slow = 0, .parser = { NULL } }, /* uname */
- { .slow = 0, .parser = { NULL } }, /* semget */
- { .slow = 1, .parser = { NULL } }, /* semop */
- { .slow = 0, .parser = { NULL } }, /* semctl */
- { .slow = 0, .parser = { NULL } }, /* shmdt */
- { .slow = 1, .parser = { NULL } }, /* msgget */
- { .slow = 1, .parser = { NULL } }, /* msgsnd */
- { .slow = 1, .parser = { NULL } }, /* msgrcv */
- { .slow = 1, .parser = { NULL } }, /* msgctl */
- { .slow = 0, .parser = { NULL } }, /* fcntl */
- { .slow = 0, .parser = { NULL } }, /* flock */
- { .slow = 0, .parser = { NULL } }, /* fsync */
- { .slow = 0, .parser = { NULL } }, /* fdatasync */
- { .slow = 0, .parser = { NULL } }, /* truncate */
- { .slow = 0, .parser = { NULL } }, /* ftruncate */
- { .slow = 0, .parser = { NULL } }, /* getdents */
- { .slow = 0, .parser = { NULL } }, /* getcwd */
- { .slow = 0, .parser = { NULL } }, /* chdir */
- { .slow = 0, .parser = { NULL } }, /* fchdir */
- { .slow = 0, .parser = { NULL } }, /* rename */
- { .slow = 0, .parser = { NULL } }, /* mkdir */
- { .slow = 0, .parser = { NULL } }, /* rmdir */
- { .slow = 0, .parser = { NULL, &parse_open_mode } }, /* creat */
- { .slow = 0, .parser = { NULL } }, /* link */
- { .slow = 0, .parser = { NULL } }, /* unlink */
- { .slow = 0, .parser = { NULL } }, /* symlink */
- { .slow = 0, .parser = { NULL } }, /* readlink */
- { .slow = 0, .parser = { NULL } }, /* chmod */
- { .slow = 0, .parser = { NULL } }, /* fchmod */
- { .slow = 0, .parser = { NULL } }, /* chown */
- { .slow = 0, .parser = { NULL } }, /* fchown */
- { .slow = 0, .parser = { NULL } }, /* lchown */
- { .slow = 0, .parser = { NULL } }, /* umask */
- { .slow = 0, .parser = { NULL } }, /* gettimeofday */
- { .slow = 0, .parser = { NULL } }, /* getrlimit */
- { .slow = 0, .parser = { NULL } }, /* getrusage */
- { .slow = 0, .parser = { NULL } }, /* sysinfo */
- { .slow = 0, .parser = { NULL } }, /* times */
- { .slow = 0, .parser = { NULL } }, /* ptrace */
- { .slow = 0, .parser = { NULL } }, /* getuid */
- { .slow = 0, .parser = { NULL } }, /* syslog */
- { .slow = 0, .parser = { NULL } }, /* getgid */
- { .slow = 0, .parser = { NULL } }, /* setuid */
- { .slow = 0, .parser = { NULL } }, /* setgid */
- { .slow = 0, .parser = { NULL } }, /* geteuid */
- { .slow = 0, .parser = { NULL } }, /* getegid */
- { .slow = 0, .parser = { NULL } }, /* setpgid */
- { .slow = 0, .parser = { NULL } }, /* getppid */
- { .slow = 0, .parser = { NULL } }, /* getpgrp */
- { .slow = 0, .parser = { NULL } }, /* setsid */
- { .slow = 0, .parser = { NULL } }, /* setreuid */
- { .slow = 0, .parser = { NULL } }, /* setregid */
- { .slow = 0, .parser = { NULL } }, /* getgroups */
- { .slow = 0, .parser = { NULL } }, /* setgroups */
- { .slow = 0, .parser = { NULL } }, /* setresuid */
- { .slow = 0, .parser = { NULL } }, /* getresuid */
- { .slow = 0, .parser = { NULL } }, /* setresgid */
- { .slow = 0, .parser = { NULL } }, /* getresgid */
- { .slow = 0, .parser = { NULL } }, /* getpgid */
- { .slow = 0, .parser = { NULL } }, /* setfsuid */
- { .slow = 0, .parser = { NULL } }, /* setfsgid */
- { .slow = 0, .parser = { NULL } }, /* getsid */
- { .slow = 0, .parser = { NULL } }, /* capget */
- { .slow = 0, .parser = { NULL } }, /* capset */
- { .slow = 0, .parser = { NULL } }, /* rt_sigpending */
- { .slow = 0, .parser = { NULL } }, /* rt_sigtimedwait */
- { .slow = 0, .parser = { NULL } }, /* rt_sigqueueinfo */
- { .slow = 0, .parser = { NULL } }, /* rt_sigsuspend */
- { .slow = 0, .parser = { NULL } }, /* sigaltstack */
- { .slow = 0, .parser = { NULL } }, /* utime */
- { .slow = 0, .parser = { NULL } }, /* mknod */
- { .slow = 0, .parser = { NULL } }, /* uselib */
- { .slow = 0, .parser = { NULL } }, /* personality */
- { .slow = 0, .parser = { NULL } }, /* ustat */
- { .slow = 0, .parser = { NULL } }, /* statfs */
- { .slow = 0, .parser = { NULL } }, /* fstatfs */
- { .slow = 0, .parser = { NULL } }, /* sysfs */
- { .slow = 0, .parser = { NULL } }, /* getpriority */
- { .slow = 0, .parser = { NULL } }, /* setpriority */
- { .slow = 0, .parser = { NULL } }, /* sched_setparam */
- { .slow = 0, .parser = { NULL } }, /* sched_getparam */
- { .slow = 0, .parser = { NULL } }, /* sched_setscheduler */
- { .slow = 0, .parser = { NULL } }, /* sched_getscheduler */
- { .slow = 0, .parser = { NULL } }, /* sched_get_priority_max */
- { .slow = 0, .parser = { NULL } }, /* sched_get_priority_min */
- { .slow = 0, .parser = { NULL } }, /* sched_rr_get_interval */
- { .slow = 0, .parser = { NULL } }, /* mlock */
- { .slow = 0, .parser = { NULL } }, /* munlock */
- { .slow = 0, .parser = { NULL } }, /* mlockall */
- { .slow = 0, .parser = { NULL } }, /* munlockall */
- { .slow = 0, .parser = { NULL } }, /* vhangup */
- { .slow = 0, .parser = { NULL } }, /* modify_ldt */
- { .slow = 0, .parser = { NULL } }, /* pivot_root */
- { .slow = 0, .parser = { NULL } }, /* _sysctl */
- { .slow = 0, .parser = { NULL } }, /* prctl */
- { .slow = 0, .parser = { NULL } }, /* arch_prctl */
- { .slow = 0, .parser = { NULL } }, /* adjtimex */
- { .slow = 0, .parser = { NULL } }, /* setrlimit */
- { .slow = 0, .parser = { NULL } }, /* chroot */
- { .slow = 0, .parser = { NULL } }, /* sync */
- { .slow = 0, .parser = { NULL } }, /* acct */
- { .slow = 0, .parser = { NULL } }, /* settimeofday */
- { .slow = 0, .parser = { NULL } }, /* mount */
- { .slow = 0, .parser = { NULL } }, /* umount2 */
- { .slow = 0, .parser = { NULL } }, /* swapon */
- { .slow = 0, .parser = { NULL } }, /* swapoff */
- { .slow = 0, .parser = { NULL } }, /* reboot */
- { .slow = 0, .parser = { NULL } }, /* sethostname */
- { .slow = 0, .parser = { NULL } }, /* setdomainname */
- { .slow = 0, .parser = { NULL } }, /* iopl */
- { .slow = 0, .parser = { NULL } }, /* ioperm */
- { .slow = 0, .parser = { NULL } }, /* create_module */
- { .slow = 0, .parser = { NULL } }, /* init_module */
- { .slow = 0, .parser = { NULL } }, /* delete_module */
- { .slow = 0, .parser = { NULL } }, /* get_kernel_syms */
- { .slow = 0, .parser = { NULL } }, /* query_module */
- { .slow = 0, .parser = { NULL } }, /* quotactl */
- { .slow = 0, .parser = { NULL } }, /* nfsservctl */
- { .slow = 0, .parser = { NULL } }, /* getpmsg */
- { .slow = 0, .parser = { NULL } }, /* putpmsg */
- { .slow = 0, .parser = { NULL } }, /* afs_syscall */
- { .slow = 0, .parser = { NULL } }, /* tuxcall */
- { .slow = 0, .parser = { NULL } }, /* security */
- { .slow = 0, .parser = { NULL } }, /* gettid */
- { .slow = 0, .parser = { NULL } }, /* readahead */
- { .slow = 0, .parser = { NULL } }, /* setxattr */
- { .slow = 0, .parser = { NULL } }, /* lsetxattr */
- { .slow = 0, .parser = { NULL } }, /* fsetxattr */
- { .slow = 0, .parser = { NULL } }, /* getxattr */
- { .slow = 0, .parser = { NULL } }, /* lgetxattr */
- { .slow = 0, .parser = { NULL } }, /* fgetxattr */
- { .slow = 0, .parser = { NULL } }, /* listxattr */
- { .slow = 0, .parser = { NULL } }, /* llistxattr */
- { .slow = 0, .parser = { NULL } }, /* flistxattr */
- { .slow = 0, .parser = { NULL } }, /* removexattr */
- { .slow = 0, .parser = { NULL } }, /* lremovexattr */
- { .slow = 0, .parser = { NULL } }, /* fremovexattr */
- { .slow = 0, .parser = { NULL, &parse_signum } }, /* tkill */
- { .slow = 0, .parser = { NULL } }, /* time */
- { .slow = 1, .parser = { NULL, &parse_futexop } }, /* futex */
- { .slow = 0, .parser = { NULL } }, /* sched_setaffinity */
- { .slow = 0, .parser = { NULL } }, /* sched_getaffinity */
- { .slow = 0, .parser = { NULL } }, /* set_thread_area */
- { .slow = 0, .parser = { NULL } }, /* io_setup */
- { .slow = 0, .parser = { NULL } }, /* io_destroy */
- { .slow = 0, .parser = { NULL } }, /* io_getevents */
- { .slow = 0, .parser = { NULL } }, /* io_submit */
- { .slow = 0, .parser = { NULL } }, /* io_cancel */
- { .slow = 0, .parser = { NULL } }, /* get_thread_area */
- { .slow = 0, .parser = { NULL } }, /* lookup_dcookie */
- { .slow = 0, .parser = { NULL } }, /* epoll_create */
- { .slow = 0, .parser = { NULL } }, /* epoll_ctl_old */
- { .slow = 0, .parser = { NULL } }, /* epoll_wait_old */
- { .slow = 0, .parser = { NULL } }, /* remap_file_pages */
- { .slow = 0, .parser = { NULL } }, /* getdents64 */
- { .slow = 0, .parser = { NULL } }, /* set_tid_address */
- { .slow = 0, .parser = { NULL } }, /* restart_syscall */
- { .slow = 0, .parser = { NULL } }, /* semtimedop */
- { .slow = 0, .parser = { NULL } }, /* fadvise64 */
- { .slow = 0, .parser = { NULL } }, /* timer_create */
- { .slow = 0, .parser = { NULL } }, /* timer_settime */
- { .slow = 0, .parser = { NULL } }, /* timer_gettime */
- { .slow = 0, .parser = { NULL } }, /* timer_getoverrun */
- { .slow = 0, .parser = { NULL } }, /* timer_delete */
- { .slow = 0, .parser = { NULL } }, /* clock_settime */
- { .slow = 0, .parser = { NULL } }, /* clock_gettime */
- { .slow = 0, .parser = { NULL } }, /* clock_getres */
- { .slow = 0, .parser = { NULL } }, /* clock_nanosleep */
- { .slow = 0, .parser = { NULL } }, /* exit_group */
- { .slow = 1, .parser = { NULL } }, /* epoll_wait */
- { .slow = 0, .parser = { NULL } }, /* epoll_ctl */
- { .slow = 0,
- .parser = { NULL, NULL, &parse_signum } }, /* tgkill */
- { .slow = 0, .parser = { NULL } }, /* utimes */
- { .slow = 0, .parser = { NULL } }, /* vserver */
- { .slow = 0, .parser = { NULL } }, /* mbind */
- { .slow = 0, .parser = { NULL } }, /* set_mempolicy */
- { .slow = 0, .parser = { NULL } }, /* get_mempolicy */
- { .slow = 0, .parser = { NULL } }, /* mq_open */
- { .slow = 0, .parser = { NULL } }, /* mq_unlink */
- { .slow = 0, .parser = { NULL } }, /* mq_timedsend */
- { .slow = 0, .parser = { NULL } }, /* mq_timedreceive */
- { .slow = 0, .parser = { NULL } }, /* mq_notify */
- { .slow = 0, .parser = { NULL } }, /* mq_getsetattr */
- { .slow = 0, .parser = { NULL } }, /* kexec_load */
- { .slow = 1, .parser = { NULL } }, /* waitid */
- { .slow = 0, .parser = { NULL } }, /* add_key */
- { .slow = 0, .parser = { NULL } }, /* request_key */
- { .slow = 0, .parser = { NULL } }, /* keyctl */
- { .slow = 0, .parser = { NULL } }, /* ioprio_set */
- { .slow = 0, .parser = { NULL } }, /* ioprio_get */
- { .slow = 0, .parser = { NULL } }, /* inotify_init */
- { .slow = 0, .parser = { NULL } }, /* inotify_add_watch */
- { .slow = 0, .parser = { NULL } }, /* inotify_rm_watch */
- { .slow = 0, .parser = { NULL } }, /* migrate_pages */
- { .slow = 0, .parser = { &parse_at_fdcwd, NULL,
- &parse_open_flags,
- &parse_open_mode } }, /* openat */
- { .slow = 0, .parser = { &parse_at_fdcwd, } }, /* mkdirat */
- { .slow = 0, .parser = { &parse_at_fdcwd, } }, /* mknodat */
- { .slow = 0, .parser = { &parse_at_fdcwd, } }, /* fchownat */
- { .slow = 0, .parser = { &parse_at_fdcwd, } }, /* futimesat */
- { .slow = 0, .parser = { &parse_at_fdcwd, } }, /* newfstatat */
- { .slow = 0, .parser = { &parse_at_fdcwd, } }, /* unlinkat */
- { .slow = 0, .parser = { &parse_at_fdcwd, } }, /* renameat */
- { .slow = 0, .parser = { &parse_at_fdcwd, } }, /* linkat */
- { .slow = 0, .parser = { &parse_at_fdcwd, } }, /* symlinkat */
- { .slow = 0, .parser = { &parse_at_fdcwd, } }, /* readlinkat */
- { .slow = 0, .parser = { &parse_at_fdcwd, } }, /* fchmodat */
- { .slow = 0, .parser = { &parse_at_fdcwd, } }, /* faccessat */
- { .slow = 0, .parser = { NULL } }, /* pselect6 */
- { .slow = 1, .parser = { NULL } }, /* ppoll */
- { .slow = 0, .parser = { NULL } }, /* unshare */
- { .slow = 0, .parser = { NULL } }, /* set_robust_list */
- { .slow = 0, .parser = { NULL } }, /* get_robust_list */
- { .slow = 0, .parser = { NULL } }, /* splice */
- { .slow = 0, .parser = { NULL } }, /* tee */
- { .slow = 0, .parser = { NULL } }, /* sync_file_range */
- { .slow = 0, .parser = { NULL } }, /* vmsplice */
- { .slow = 0, .parser = { NULL } }, /* move_pages */
- { .slow = 0, .parser = { NULL } }, /* utimensat */
- { .slow = 1, .parser = { NULL } }, /* epoll_pwait */
- { .slow = 0, .parser = { NULL } }, /* signalfd */
- { .slow = 0, .parser = { NULL } }, /* timerfd_create */
- { .slow = 0, .parser = { NULL } }, /* eventfd */
- { .slow = 0, .parser = { NULL } }, /* fallocate */
- { .slow = 0, .parser = { NULL } }, /* timerfd_settime */
- { .slow = 0, .parser = { NULL } }, /* timerfd_gettime */
- { .slow = 1, .parser = { NULL } }, /* accept4 */
- { .slow = 0, .parser = { NULL } }, /* signalfd4 */
- { .slow = 0, .parser = { NULL } }, /* eventfd2 */
- { .slow = 0, .parser = { NULL } }, /* epoll_create1 */
- { .slow = 0, .parser = { NULL } }, /* dup3 */
- { .slow = 0, .parser = { NULL } }, /* pipe2 */
- { .slow = 0, .parser = { NULL } }, /* inotify_init1 */
- { .slow = 0, .parser = { NULL } }, /* preadv */
- { .slow = 0, .parser = { NULL } }, /* pwritev */
- { .slow = 0, .parser = { NULL } }, /* rt_tgsigqueueinfo */
- { .slow = 0, .parser = { NULL } }, /* perf_event_open */
- { .slow = 0, .parser = { NULL } }, /* recvmmsg */
- { .slow = 0, .parser = { NULL } },
- { .slow = 1, .parser = { NULL } }, /* checkpoint */
- { .slow = 1, .parser = { NULL } }, /* restore */
- { .slow = 1, .parser = { NULL } }, /* sandbox_create */
- { .slow = 0, .parser = { NULL } }, /* sandbox_attach */
- { .slow = 0, .parser = { NULL } }, /* sandbox_current */
- { .slow = 1, .parser = { NULL } }, /* msgpersist */
- { .slow = 1, .parser = { NULL } }, /* benchmark_ipc */
- { .slow = 1, .parser = { NULL } }, /* send_rpc */
- { .slow = 1, .parser = { NULL } }, /* recv_rpc */
- };
- static inline int is_pointer (const char * type)
- {
- return type[strlen(type) - 1] == '*' || !memcmp(type, "long", 5);
- }
- #define PRINTF(fmt, ...) \
- do { \
- debug_printf((fmt), __VA_ARGS__); \
- } while (0)
- #define PUTS(str) \
- do { \
- debug_puts((str)); \
- } while (0)
- #define PUTCH(ch) \
- do { \
- debug_putch((ch)); \
- } while (0)
- #define VPRINTF(fmt, ap) \
- do { \
- debug_vprintf((fmt), (ap)); \
- } while (0)
- static inline void parse_string_arg (va_list * ap)
- {
- VPRINTF("\"%s\"", ap);
- }
- static inline void parse_pointer_arg (va_list * ap)
- {
- VPRINTF("%p", ap);
- }
- static inline void parse_integer_arg (va_list * ap)
- {
- VPRINTF("%d", ap);
- }
- static inline void parse_syscall_args (va_list * ap)
- {
- const char * arg_type = va_arg(ap, const char *);
- if (memcmp(arg_type, "const char *", 13) == 0)
- parse_string_arg(ap);
- else if (is_pointer(arg_type))
- parse_pointer_arg(ap);
- else
- parse_integer_arg(ap);
- }
- static inline void skip_syscall_args (va_list * ap)
- {
- const char * arg_type = va_arg (ap, const char *);
- if (memcmp(arg_type, "const char *", 13) == 0)
- va_arg(ap, const char *);
- else if (is_pointer(arg_type))
- va_arg(ap, void *);
- else
- va_arg(ap, int);
- }
- void sysparser_printf (const char * fmt, ...)
- {
- va_list ap;
- va_start(ap, fmt);
- VPRINTF(fmt, &ap);
- va_end(ap);
- }
- void parse_syscall_before (int sysno, const char * name, int nr, ...)
- {
- if (!debug_handle)
- return;
- struct parser_table * parser = &syscall_parser_table[sysno];
- if (!parser->slow && !parser->stop)
- return;
- va_list ap;
- va_start(ap, nr);
- PRINTF("---- shim_%s(", name);
- for (int i = 0 ; i < nr ; i++) {
- if (parser->stop && parser->stop == i)
- goto dotdotdot;
- if (i)
- PUTCH(',');
- if (parser->parser[i]) {
- const char * type = va_arg(ap, const char *);
- (*parser->parser[i])(type, &ap);
- } else
- parse_syscall_args(&ap);
- }
- PUTCH(')');
- dotdotdot:
- PRINTF(" ...\n", name);
- va_end(ap);
- }
- void parse_syscall_after (int sysno, const char * name, int nr, ...)
- {
- if (!debug_handle)
- return;
- struct parser_table * parser = &syscall_parser_table[sysno];
- va_list ap;
- va_start(ap, nr);
- const char * ret_type = va_arg(ap, const char *);
- if (parser->slow || parser->stop)
- PRINTF("---- return from shim_%s(...", name);
- else
- PRINTF("---- shim_%s(", name);
- unsigned long ret_ptr;
- int ret_val;
- if (is_pointer(ret_type))
- ret_ptr = (unsigned long) va_arg(ap, void *);
- else
- ret_val = va_arg(ap, int);
- if (!parser->slow || parser->stop)
- for (int i = 0 ; i < nr ; i++) {
- if (parser->stop && i < parser->stop) {
- skip_syscall_args(&ap);
- continue;
- }
- if (i)
- PUTCH(',');
- if (parser->parser[i]) {
- const char * type = va_arg(ap, const char *);
- (*parser->parser[i])(type, &ap);
- } else
- parse_syscall_args(&ap);
- }
- if (is_pointer(ret_type)) {
- if (ret_ptr < -4095L)
- PRINTF(") = %p\n", ret_ptr);
- else
- PRINTF(") = %ld\n", (long) ret_ptr);
- } else {
- if (ret_val >= 0)
- PRINTF(") = %d\n", ret_val);
- else
- PRINTF(") = %d\n", ret_val);
- }
- va_end (ap);
- }
- static void parse_open_flags (const char * type, va_list * ap)
- {
- int flags = va_arg(*ap, int);
- if (flags & O_WRONLY) {
- PUTS("O_WRONLY");
- flags &= ~O_WRONLY;
- } else if (flags & O_RDWR) {
- PUTS("O_RDWR");
- flags &= ~O_RDWR;
- } else
- PUTS("O_RDONLY");
- if (flags & O_APPEND) {
- PUTS("|O_APPEND");
- flags &= ~O_APPEND;
- }
- if (flags & O_CREAT) {
- PUTS("|O_CREAT");
- flags &= ~O_CREAT;
- }
- if (flags & O_TRUNC) {
- PUTS("|O_TRUNC");
- flags &= ~O_TRUNC;
- }
- if (flags & O_EXCL) {
- PUTS("|O_EXCL");
- flags &= ~O_EXCL;
- }
- if (flags)
- PRINTF("|%o", flags);
- }
- static void parse_open_mode (const char * type, va_list * ap)
- {
- VPRINTF("%04o", ap);
- }
- static void parse_access_mode (const char * type, va_list * ap)
- {
- int mode = va_arg(*ap, int);
- PUTS("F_OK");
- if (mode) {
- if (mode & R_OK)
- PUTS("|R_OK");
- if (mode & W_OK)
- PUTS("|W_OK");
- if (mode & X_OK)
- PUTS("|X_OK");
- }
- }
- static void parse_clone_flags (const char * type, va_list * ap)
- {
- int flags = va_arg(*ap, int);
- #define FLG(n) { "CLONE_" #n, CLONE_##n, }
- const struct {
- const char * name; int flag;
- } all_flags[] = {
- FLG(VM), FLG(FS), FLG(FILES), FLG(SIGHAND), FLG(PTRACE), FLG(VFORK),
- FLG(PARENT), FLG(THREAD), FLG(NEWNS), FLG(SYSVSEM), FLG(SETTLS),
- FLG(PARENT_SETTID), FLG(CHILD_CLEARTID), FLG(DETACHED), FLG(UNTRACED),
- FLG(CHILD_SETTID), FLG(NEWUTS), FLG(NEWIPC), FLG(NEWUSER),
- FLG(NEWPID), FLG(NEWNET), FLG(IO),
- };
- #undef FLG
- bool printed = false;
- for (int i = 0 ; i < sizeof(all_flags) / sizeof(all_flags[0]) ; i++)
- if (flags & all_flags[i].flag) {
- if (printed)
- PUTCH('|');
- else
- printed = true;
- PUTS(all_flags[i].name);
- flags &= ~all_flags[i].flag;
- }
- if (flags)
- PRINTF("|0x%x", flags);
- }
- static void parse_mmap_prot (const char * type, va_list * ap)
- {
- int prot = va_arg(*ap, int);
- int nflags = 0;
- if (prot == PROT_NONE) {
- PUTS("PROT_NONE");
- return;
- }
- if (prot & PROT_READ) {
- if (nflags++)
- PUTS("|");
- PUTS("PROT_READ");
- }
- if (prot & PROT_WRITE) {
- if (nflags++)
- PUTS("|");
- PUTS("PROT_WRITE");
- }
- if (prot & PROT_EXEC) {
- if (nflags++)
- PUTS("|");
- PUTS("PROT_EXEC");
- }
- }
- static void parse_mmap_flags (const char * type, va_list * ap)
- {
- int flags = va_arg(*ap, int);
- if (flags & MAP_SHARED) {
- PUTS("MAP_SHARED");
- flags &= ~MAP_SHARED;
- }
- if (flags & MAP_PRIVATE) {
- PUTS("MAP_PRIVATE");
- flags &= ~MAP_PRIVATE;
- }
- if (flags & MAP_ANONYMOUS) {
- PUTS("|MAP_ANON");
- flags &= ~MAP_ANONYMOUS;
- }
- if (flags & MAP_FILE) {
- PUTS("|MAP_FILE");
- flags &= ~MAP_FILE;
- }
- if (flags & MAP_FIXED) {
- PUTS("|MAP_FIXED");
- flags &= ~MAP_FIXED;
- }
- #ifdef CONFIG_MMAP_ALLOW_UNINITIALIZED
- if (flags & MAP_UNINITIALIZED) {
- PUTS("|MAP_UNINITIALIZED");
- flags &= ~MAP_UNINITIALIZED;
- }
- #endif
- if (flags)
- PRINTF("|0x%x", flags);
- }
- static void parse_exec_args (const char * type, va_list * ap)
- {
- const char ** args = va_arg(*ap, const char **);
- PUTS("[");
- for (; *args ; args++) {
- PUTS(*args);
- PUTS(",");
- }
- PUTS("]");
- }
- static void parse_exec_envp (const char * type, va_list * ap)
- {
- const char ** envp = va_arg(*ap, const char **);
- if (!envp) {
- PUTS("NULL");
- return;
- }
- int cnt = 0;
- PUTS("[");
- for (; *envp ; envp++)
- if (cnt++ < 2) {
- PUTS(*envp);
- PUTS(",");
- }
- if (cnt > 2)
- PRINTF("(%d more)", cnt);
- PUTS("]");
- }
- static void parse_pipe_fds (const char * type, va_list * ap)
- {
- int * fds = va_arg(*ap, int *);
- PRINTF("[%d, %d]", fds[0], fds[1]);
- }
- #define S(sig) #sig
- const char *const siglist[NUM_KNOWN_SIGS + 1] =
- { NULL,
- S(SIGHUP),
- S(SIGINT),
- S(SIGQUIT),
- S(SIGILL),
- S(SIGTRAP),
- S(SIGABRT),
- S(SIGBUS),
- S(SIGFPE),
- S(SIGKILL),
- S(SIGUSR1),
- S(SIGSEGV),
- S(SIGUSR2),
- S(SIGPIPE),
- S(SIGALRM),
- S(SIGTERM),
- S(SIGSTKFLT),
- S(SIGCHLD),
- S(SIGCONT),
- S(SIGSTOP),
- S(SIGTSTP),
- S(SIGTTIN),
- S(SIGTTOU), };
- static void parse_signum (const char * type, va_list * ap)
- {
- unsigned int signum = va_arg(*ap, unsigned int);
- if (signum > 0 && signum <= NUM_KNOWN_SIGS)
- PUTS(signal_name(signum));
- }
- static void parse_sigmask (const char * type, va_list * ap)
- {
- __sigset_t * sigset = va_arg(*ap, __sigset_t *);
- if (!sigset) {
- PUTS("NULL");
- return;
- }
- PUTS("[");
- for (int signum = 1 ; signum <= sizeof(sigset) * 8 ; signum++)
- if (__sigismember(sigset, signum)) {
- PUTS(signal_name(signum));
- PUTS(",");
- }
- PUTS("]");
- }
- static void parse_sigprocmask_how (const char * type, va_list * ap)
- {
- int how = va_arg(*ap, int);
- switch (how) {
- case SIG_BLOCK:
- PUTS("BLOCK");
- break;
- case SIG_UNBLOCK:
- PUTS("UNBLOCK");
- break;
- case SIG_SETMASK:
- PUTS("SETMASK");
- break;
- default:
- PUTS("<unknown>");
- break;
- }
- }
- static void parse_timespec (const char * type, va_list * ap)
- {
- const struct timespec * tv = va_arg(*ap, const struct timespec *);
- if (!tv) {
- PUTS("NULL");
- return;
- }
- PRINTF("[%ld,%lld]", tv->tv_sec, tv->tv_nsec);
- }
- static void parse_sockaddr (const char * type, va_list *ap)
- {
- const struct sockaddr *addr = va_arg(*ap, const struct sockaddr *);
- if (!addr) {
- PUTS("NULL");
- return;
- }
- switch (addr->sa_family) {
- case AF_INET: {
- struct sockaddr_in * a = (void *) addr;
- unsigned char * ip = (void *) &a->sin_addr.s_addr;
- PRINTF("{family=INET,ip=%u.%u.%u.%u,port=htons(%u)}",
- ip[0], ip[1], ip[2], ip[3], __ntohs(a->sin_port));
- break;
- }
- case AF_INET6: {
- struct sockaddr_in6 * a = (void *) addr;
- unsigned short * ip = (void *) &a->sin6_addr.s6_addr;
- PRINTF("{family=INET,ip=[%x:%x:%x:%x:%x:%x:%x:%x],"
- "port=htons(%u)}",
- ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6],
- ip[7], __ntohs(a->sin6_port));
- break;
- }
- case AF_UNIX: {
- struct sockaddr_un * a = (void *) addr;
- PRINTF("{family=UNIX,path=%s}", a->sun_path);
- break;
- }
- default:
- PUTS("UNKNOWN");
- break;
- }
- }
- static void parse_futexop (const char * type, va_list * ap)
- {
- int op = va_arg(*ap, int);
- #ifdef FUTEX_PRIVATE_FLAG
- if (op & FUTEX_PRIVATE_FLAG) {
- PUTS("FUTEX_PRIVATE|");
- op &= ~FUTEX_PRIVATE_FLAG;
- }
- #endif
- #ifdef FUTEX_CLOCK_REALTIME
- if (op & FUTEX_CLOCK_REALTIME) {
- PUTS("FUTEX_CLOCK_REALTIME|");
- op &= ~FUTEX_CLOCK_REALTIME;
- }
- #endif
- op &= FUTEX_CMD_MASK;
- switch (op) {
- case FUTEX_WAIT:
- PUTS("FUTEX_WAIT");
- break;
- case FUTEX_WAKE:
- PUTS("FUTEX_WAKE");
- break;
- case FUTEX_FD:
- PUTS("FUTEX_FD");
- break;
- case FUTEX_REQUEUE:
- PUTS("FUTEX_REQUEUE");
- break;
- case FUTEX_CMP_REQUEUE:
- PUTS("FUTEX_CMP_REQUEUE");
- break;
- case FUTEX_WAKE_OP:
- PUTS("FUTEX_WAKE_OP");
- break;
- default:
- PRINTF("OP %d", op);
- break;
- }
- }
- static void parse_ioctlop (const char * type, va_list * ap)
- {
- int op = va_arg(*ap, int);
- if (op >= TCGETS && op <= TIOCVHANGUP) {
- const char * opnames[] = {
- "TCGETS", /* 0x5401 */ "TCSETS", /* 0x5402 */
- "TCSETSW", /* 0x5403 */ "TCSETSF", /* 0x5404 */
- "TCGETA", /* 0x5405 */ "TCSETA", /* 0x5406 */
- "TCSETAW", /* 0x5407 */ "TCSETAF", /* 0x5408 */
- "TCSBRK", /* 0x5409 */ "TCXONC", /* 0x540A */
- "TCFLSH", /* 0x540B */ "TIOCEXCL", /* 0x540C */
- "TIOCNXCL", /* 0x540D */ "TIOCSCTTY", /* 0x540E */
- "TIOCGPGRP", /* 0x540F */ "TIOCSPGRP", /* 0x5410 */
- "TIOCOUTQ", /* 0x5411 */ "TIOCSTI", /* 0x5412 */
- "TIOCGWINSZ", /* 0x5413 */ "TIOCSWINSZ", /* 0x5414 */
- "TIOCMGET", /* 0x5415 */ "TIOCMBIS", /* 0x5416 */
- "TIOCMBIC", /* 0x5417 */ "TIOCMSET", /* 0x5418 */
- "TIOCGSOFTCAR", /* 0x5419 */ "TIOCSSOFTCAR", /* 0x541A */
- "FIONREAD", /* 0x541B */ "TIOCLINUX", /* 0x541C */
- "TIOCCONS", /* 0x541D */ "TIOCGSERIAL", /* 0x541E */
- "TIOCSSERIAL", /* 0x541F */ "TIOCPKT", /* 0x5420 */
- "FIONBIO", /* 0x5421 */ "TIOCNOTTY", /* 0x5422 */
- "TIOCSETD", /* 0x5423 */ "TIOCGETD", /* 0x5424 */
- "TCSBRKP", /* 0x5425 */ "",
- "TIOCSBRK", /* 0x5427 */ "TIOCCBRK", /* 0x5428 */
- "TIOCGSID", /* 0x5429 */ "TCGETS2", /* 0x542A */
- "TCSETS2", /* 0x542B */ "TCSETSW2", /* 0x542C */
- "TCSETSF2", /* 0x542D */ "TIOCGRS485", /* 0x542E */
- "TIOCSRS485", /* 0x542F */ "TIOCGPTN" /* 0x5430 */
- "TIOCSPTLCK", /* 0x5431 */ "TCGETX", /* 0x5432 */
- "TCSETX", /* 0x5433 */ "TCSETXF", /* 0x5434 */
- "TCSETXW", /* 0x5435 */ "TIOCSIG", /* 0x5436 */
- "TIOCVHANGUP", /* 0x5437 */
- };
- PUTS(opnames[op - TCGETS]);
- return;
- }
- PRINTF("OP 0x%04u", op);
- }
- static void parse_seek (const char * type, va_list * ap)
- {
- int seek = va_arg(*ap, int);
- switch(seek) {
- case SEEK_CUR:
- PUTS("SEEK_CUR");
- break;
- case SEEK_SET:
- PUTS("SEEK_SET");
- break;
- case SEEK_END:
- PUTS("SEEK_END");
- break;
- default:
- PRINTF("%d", seek);
- break;
- }
- }
- static void parse_at_fdcwd (const char * type, va_list * ap)
- {
- int fd = va_arg(*ap, int);
- switch(fd) {
- case AT_FDCWD:
- PUTS("AT_FDCWD");
- break;
- default:
- PRINTF("%d", fd);
- break;
- }
- }
- static void parse_wait_option (const char * type, va_list * ap)
- {
- int option = va_arg(*ap, int);
- if (option & WNOHANG)
- PUTS("WNOHANG");
- }
|