diff options
Diffstat (limited to 'trace')
-rw-r--r-- | trace/preload.c | 80 | ||||
-rw-r--r-- | trace/trace.c | 225 |
2 files changed, 0 insertions, 305 deletions
diff --git a/trace/preload.c b/trace/preload.c deleted file mode 100644 index 99dd906..0000000 --- a/trace/preload.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2015 John Crispin <blogic@openwrt.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2.1 - * as published by the Free Software Foundation - * - * This program 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. - */ - -#define _GNU_SOURCE -#include <sys/ptrace.h> -#include <sys/types.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <dlfcn.h> - -#include "../preload.h" - -#define ERROR(fmt, ...) do { \ - fprintf(stderr,"perload-jail: "fmt, ## __VA_ARGS__); \ - } while (0) - -static main_t __main__; - -static int __preload_main__(int argc, char **argv, char **envp) -{ - unsetenv("LD_PRELOAD"); - ptrace(PTRACE_TRACEME); - kill(getpid(), SIGSTOP); - - return (*__main__)(argc, argv, envp); -} - -int __libc_start_main(main_t main, - int argc, - char **argv, - ElfW(auxv_t) *auxvec, - __typeof (main) init, - void (*fini) (void), - void (*rtld_fini) (void), - void *stack_end) -{ - start_main_t __start_main__; - - __start_main__ = dlsym(RTLD_NEXT, "__libc_start_main"); - if (!__start_main__) - ERROR("failed to find __libc_start_main %s\n", dlerror()); - - __main__ = main; - - return (*__start_main__)(__preload_main__, argc, argv, auxvec, - init, fini, rtld_fini, stack_end); -} - -void __uClibc_main(main_t main, - int argc, - char **argv, - void (*app_init)(void), - void (*app_fini)(void), - void (*rtld_fini)(void), - void *stack_end attribute_unused) -{ - uClibc_main __start_main__; - - __start_main__ = dlsym(RTLD_NEXT, "__uClibc_main"); - if (!__start_main__) - ERROR("failed to find __uClibc_main %s\n", dlerror()); - - __main__ = main; - - return (*__start_main__)(__preload_main__, argc, argv, - app_init, app_fini, rtld_fini, stack_end); -} diff --git a/trace/trace.c b/trace/trace.c deleted file mode 100644 index b0005b8..0000000 --- a/trace/trace.c +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright (C) 2015 John Crispin <blogic@openwrt.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2.1 - * as published by the Free Software Foundation - * - * This program 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. - */ - -#define _GNU_SOURCE -#include <stddef.h> -#include <sys/ptrace.h> -#include <sys/types.h> -#include <sys/user.h> -#include <sys/wait.h> -#include <unistd.h> -#include <stdlib.h> -#include <stdio.h> -#include <errno.h> -#include <string.h> -#include <syslog.h> - -#include <libubox/uloop.h> -#include <libubox/blobmsg.h> -#include <libubox/blobmsg_json.h> - -#include "../syscall-names.h" - -#define _offsetof(a, b) __builtin_offsetof(a,b) -#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) - -#ifdef __amd64__ -#define reg_syscall_nr _offsetof(struct user, regs.orig_rax) -#elif defined(__i386__) -#define reg_syscall_nr _offsetof(struct user, regs.orig_eax) -#elif defined(__mips) -# ifndef EF_REG2 -# define EF_REG2 8 -# endif -#define reg_syscall_nr (EF_REG2 / 4) -#elif defined(__arm__) -#define reg_syscall_nr _offsetof(struct user, regs.uregs[7]) -#else -#error tracing is not supported on this architecture -#endif - -#define INFO(fmt, ...) do { \ - fprintf(stderr, "utrace: "fmt, ## __VA_ARGS__); \ -} while (0) - -#define ERROR(fmt, ...) do { \ - syslog(LOG_ERR, "utrace: "fmt, ## __VA_ARGS__); \ - fprintf(stderr, "utrace: "fmt, ## __VA_ARGS__); \ -} while (0) - -static struct uloop_process tracer; -static int *syscall_count; -static struct blob_buf b; -static int syscall_max; -static int in_syscall; -static int debug; - -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)) { - syscall_count[i] = val; - return; - } -} - -static void print_syscalls(int policy, const char *json) -{ - void *c; - int i; - - set_syscall("rt_sigaction", 1); - set_syscall("sigreturn", 1); - set_syscall("rt_sigreturn", 1); - set_syscall("exit_group", 1); - set_syscall("exit", 1); - - blob_buf_init(&b, 0); - c = blobmsg_open_array(&b, "whitelist"); - - for (i = 0; i < ARRAY_SIZE(syscall_names); i++) { - if (!syscall_count[i]) - continue; - if (syscall_names[i]) { - if (debug) - printf("syscall %d (%s) was called %d times\n", - i, syscall_names[i], syscall_count[i]); - blobmsg_add_string(&b, NULL, syscall_names[i]); - } else { - ERROR("no name found for syscall(%d)\n", i); - } - } - blobmsg_close_array(&b, c); - blobmsg_add_u32(&b, "policy", policy); - if (json) { - FILE *fp = fopen(json, "w"); - if (fp) { - fprintf(fp, "%s", blobmsg_format_json_indent(b.head, true, 0)); - fclose(fp); - INFO("saving syscall trace to %s\n", json); - } else { - ERROR("failed to open %s\n", json); - } - } else { - printf("%s\n", - blobmsg_format_json_indent(b.head, true, 0)); - } - -} - -static void tracer_cb(struct uloop_process *c, int ret) -{ - if (WIFSTOPPED(ret) && WSTOPSIG(ret) & 0x80) { - if (!in_syscall) { - int syscall = ptrace(PTRACE_PEEKUSER, c->pid, reg_syscall_nr); - - if (syscall < syscall_max) { - syscall_count[syscall]++; - if (debug) - fprintf(stderr, "%s()\n", syscall_names[syscall]); - } else if (debug) { - fprintf(stderr, "syscal(%d)\n", syscall); - } - } - in_syscall = !in_syscall; - } else if (WIFEXITED(ret)) { - uloop_end(); - return; - } - ptrace(PTRACE_SYSCALL, c->pid, 0, 0); - uloop_process_add(&tracer); -} - -int main(int argc, char **argv, char **envp) -{ - char *json = NULL; - int status, ch, policy = EPERM; - pid_t child; - - while ((ch = getopt(argc, argv, "f:p:")) != -1) { - switch (ch) { - case 'f': - json = optarg; - break; - case 'p': - policy = atoi(optarg); - break; - } - } - - argc -= optind; - argv += optind; - - if (!argc) - return -1; - - if (getenv("TRACE_DEBUG")) - debug = 1; - unsetenv("TRACE_DEBUG"); - - child = fork(); - - if (child == 0) { - char **_argv = calloc(argc + 1, sizeof(char *)); - char **_envp; - char preload[] = "LD_PRELOAD=/lib/libpreload-trace.so"; - int envc = 1; - int ret; - - memcpy(_argv, argv, argc * sizeof(char *)); - - while (envp[envc++]) - ; - - _envp = calloc(envc, sizeof(char *)); - memcpy(&_envp[1], _envp, envc * sizeof(char *)); - *envp = preload; - - ret = execve(_argv[0], _argv, envp); - ERROR("failed to exec %s: %s\n", _argv[0], strerror(errno)); - return ret; - } - - if (child < 0) - return -1; - - syscall_max = ARRAY_SIZE(syscall_names); - syscall_count = calloc(syscall_max, sizeof(int)); - waitpid(child, &status, 0); - if (!WIFSTOPPED(status)) { - ERROR("failed to start %s\n", *argv); - return -1; - } - - ptrace(PTRACE_SETOPTIONS, child, 0, PTRACE_O_TRACESYSGOOD); - ptrace(PTRACE_SYSCALL, child, 0, 0); - - uloop_init(); - tracer.pid = child; - tracer.cb = tracer_cb; - uloop_process_add(&tracer); - uloop_run(); - uloop_done(); - - if (!json) - if (asprintf(&json, "/tmp/%s.%u.json", basename(*argv), child) < 0) - ERROR("failed to allocate output path: %s\n", strerror(errno)); - - print_syscalls(policy, json); - - return 0; -} |