X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fprocd.git;a=blobdiff_plain;f=trace%2Ftrace.c;h=1c1e75753fc910fad78f4aec4c7a01f3a55d6f29;hp=5189cfb11290baa18c3897a06ee51223ae2676f7;hb=67eb7e68165bfa29ab57eb82f3e40eca17662365;hpb=5e4ad0270bedf98da1d47e3e1306f7b66b6b29c7 diff --git a/trace/trace.c b/trace/trace.c index 5189cfb..1c1e757 100644 --- a/trace/trace.c +++ b/trace/trace.c @@ -25,6 +25,7 @@ #include #include #include +#include #ifndef PTRACE_EVENT_STOP /* PTRACE_EVENT_STOP is defined in linux/ptrace.h, but this header @@ -32,6 +33,7 @@ #define PTRACE_EVENT_STOP 128 #endif +#include #include #include #include @@ -65,46 +67,30 @@ enum mode { SECCOMP_TRACE, } mode = UTRACE; -#define PROC_NAME(mode) (mode == UTRACE ? "utrace" : "seccomp-trace") - -#define INFO(fmt, ...) do { \ - fprintf(stderr, "%s: "fmt, PROC_NAME(mode), ## __VA_ARGS__); \ -} while (0) - -#define ERROR(fmt, ...) do { \ - syslog(LOG_ERR, "%s: "fmt, PROC_NAME(mode), ## __VA_ARGS__); \ - fprintf(stderr, "%s: "fmt, PROC_NAME(mode), ## __VA_ARGS__); \ -} while (0) - -#define LOGERR(fmt, ...) do { \ - syslog(LOG_ERR, "%s: "fmt, PROC_NAME(mode), ## __VA_ARGS__); \ -} while (0) - struct tracee { struct uloop_process proc; int in_syscall; }; static struct tracee tracer; -static int *syscall_count; +static int syscall_count[SYSCALL_COUNT]; static int violation_count; static struct blob_buf b; -static int syscall_max; static int debug; char *json = NULL; int ptrace_restart; -static int max_syscall = ARRAY_SIZE(syscall_names); - static void set_syscall(const char *name, int val) { int i; - for (i = 0; i < max_syscall; i++) - if (syscall_names[i] && !strcmp(syscall_names[i], name)) { + for (i = 0; i < SYSCALL_COUNT; i++) { + int sc = syscall_index_to_number(i); + if (syscall_name(sc) && !strcmp(syscall_name(sc), name)) { syscall_count[i] = val; return; } + } } struct syscall { @@ -130,29 +116,29 @@ static void print_syscalls(int policy, const char *json) set_syscall("exit", 1); } - struct syscall sorted[ARRAY_SIZE(syscall_names)]; + struct syscall sorted[SYSCALL_COUNT]; - for (i = 0; i < ARRAY_SIZE(syscall_names); i++) { - sorted[i].syscall = i; + for (i = 0; i < SYSCALL_COUNT; i++) { + sorted[i].syscall = syscall_index_to_number(i); sorted[i].count = syscall_count[i]; } - qsort(sorted, ARRAY_SIZE(syscall_names), sizeof(sorted[0]), cmp_count); + qsort(sorted, SYSCALL_COUNT, sizeof(sorted[0]), cmp_count); blob_buf_init(&b, 0); c = blobmsg_open_array(&b, "whitelist"); - for (i = 0; i < ARRAY_SIZE(syscall_names); i++) { + for (i = 0; i < SYSCALL_COUNT; i++) { int sc = sorted[i].syscall; if (!sorted[i].count) break; - if (syscall_names[sc]) { + if (syscall_name(sc)) { if (debug) printf("syscall %d (%s) was called %d times\n", - sc, syscall_names[sc], sorted[i].count); - blobmsg_add_string(&b, NULL, syscall_names[sc]); + sc, syscall_name(sc), sorted[i].count); + blobmsg_add_string(&b, NULL, syscall_name(sc)); } else { - ERROR("no name found for syscall(%d)\n", sc); + ULOG_ERR("no name found for syscall(%d)\n", sc); } } blobmsg_close_array(&b, c); @@ -162,9 +148,9 @@ static void print_syscalls(int policy, const char *json) if (fp) { fprintf(fp, "%s", blobmsg_format_json_indent(b.head, true, 0)); fclose(fp); - INFO("saving syscall trace to %s\n", json); + ULOG_INFO("saving syscall trace to %s\n", json); } else { - ERROR("failed to open %s\n", json); + ULOG_ERR("failed to open %s\n", json); } } else { printf("%s\n", @@ -187,13 +173,14 @@ static void report_seccomp_vialation(pid_t pid, unsigned syscall) if (violation_count < INT_MAX) violation_count++; - if (syscall < ARRAY_SIZE(syscall_names)) { - syscall_count[syscall]++; - LOGERR("%s[%u] tried to call non-whitelisted syscall: %s (see %s)\n", - buf, pid, syscall_names[syscall], json); + int i = syscall_index(syscall); + if (i >= 0) { + syscall_count[i]++; + ULOG_ERR("%s[%u] tried to call non-whitelisted syscall: %s (see %s)\n", + buf, pid, syscall_name(syscall), json); } else { - LOGERR("%s[%u] tried to call non-whitelisted syscall: %d (see %s)\n", - buf, pid, syscall, json); + ULOG_ERR("%s[%u] tried to call non-whitelisted syscall: %d (see %s)\n", + buf, pid, syscall, json); } } @@ -209,11 +196,11 @@ static void tracer_cb(struct uloop_process *c, int ret) if (WSTOPSIG(ret) & 0x80) { if (!tracee->in_syscall) { int syscall = ptrace(PTRACE_PEEKUSER, c->pid, reg_syscall_nr); - - if (syscall < syscall_max) { - syscall_count[syscall]++; + int i = syscall_index(syscall); + if (i >= 0) { + syscall_count[i]++; if (debug) - fprintf(stderr, "%s()\n", syscall_names[syscall]); + fprintf(stderr, "%s()\n", syscall_name(syscall)); } else if (debug) { fprintf(stderr, "syscal(%d)\n", syscall); } @@ -262,6 +249,15 @@ static void tracer_cb(struct uloop_process *c, int ret) uloop_process_add(c); } +static void sigterm_handler(int signum) +{ + /* When we receive SIGTERM, we forward it to the tracee. After + * the tracee exits, trace_cb() will be called and make us + * exit too. */ + kill(tracer.proc.pid, SIGTERM); +} + + int main(int argc, char **argv, char **envp) { int status, ch, policy = EPERM; @@ -331,7 +327,7 @@ int main(int argc, char **argv, char **envp) memcpy(&_envp[newenv], envp, envc * sizeof(char *)); ret = execve(_argv[0], _argv, _envp); - ERROR("failed to exec %s: %s\n", _argv[0], strerror(errno)); + ULOG_ERR("failed to exec %s: %m\n", _argv[0]); free(_argv); free(_envp); @@ -341,14 +337,15 @@ int main(int argc, char **argv, char **envp) if (child < 0) return -1; - syscall_max = ARRAY_SIZE(syscall_names); - syscall_count = calloc(syscall_max, sizeof(int)); waitpid(child, &status, WUNTRACED); if (!WIFSTOPPED(status)) { - ERROR("failed to start %s\n", *argv); + ULOG_ERR("failed to start %s\n", *argv); return -1; } + /* Initialize uloop to catch all ptrace stops from now on. */ + uloop_init(); + int ptrace_options = PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK | PTRACE_O_TRACECLONE; switch (mode) { case UTRACE: @@ -360,13 +357,19 @@ int main(int argc, char **argv, char **envp) ptrace_restart = PTRACE_CONT; break; } - ptrace(PTRACE_SEIZE, child, 0, ptrace_options); - ptrace(ptrace_restart, child, 0, SIGCONT); + if (ptrace(PTRACE_SEIZE, child, 0, ptrace_options) == -1) { + ULOG_ERR("PTRACE_SEIZE: %m\n"); + return -1; + } + if (ptrace(ptrace_restart, child, 0, SIGCONT) == -1) { + ULOG_ERR("ptrace_restart: %m\n"); + return -1; + } - uloop_init(); tracer.proc.pid = child; tracer.proc.cb = tracer_cb; uloop_process_add(&tracer.proc); + signal(SIGTERM, sigterm_handler); /* Override uloop's SIGTERM handler */ uloop_run(); uloop_done(); @@ -375,7 +378,7 @@ int main(int argc, char **argv, char **envp) case UTRACE: if (!json) if (asprintf(&json, "/tmp/%s.%u.json", basename(*argv), child) < 0) - ERROR("failed to allocate output path: %s\n", strerror(errno)); + ULOG_ERR("failed to allocate output path: %m\n"); break; case SECCOMP_TRACE: if (!violation_count)