From d4575728b52ede46afc56e862c1c204c5621096e Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Wed, 2 Apr 2025 10:37:49 +0200 Subject: [PATCH] proj: Implement fork/exec/pipe --- proj/intercept/Makefile | 6 +- proj/intercept/src/intercept.c | 855 +++++++++++++++++++++----- proj/server/src/intercept/__init__.py | 101 ++- proj/server/src/intercept/standard.py | 19 + 4 files changed, 824 insertions(+), 157 deletions(-) diff --git a/proj/intercept/Makefile b/proj/intercept/Makefile index 2f2dc4f..73fa0ca 100644 --- a/proj/intercept/Makefile +++ b/proj/intercept/Makefile @@ -19,10 +19,12 @@ intercept.so: bin/intercept_preload.o $(CC) -shared -o $@ $^ $(CFLAGS) -lc -ldl main_intercept: bin/main.o src/intercept.c - $(CC) -o $@ $^ $(CFLAGS) -lc -Wl,--wrap=malloc,--wrap=free,--wrap=calloc,--wrap=realloc,--wrap=reallocarray,--wrap=getopt,--wrap=exit,--wrap=close,--wrap=sigaction,\ + $(CC) -o $@ $^ $(CFLAGS) -lc -Wl,--wrap=malloc,--wrap=free,--wrap=calloc,--wrap=realloc,--wrap=reallocarray,--wrap=getopt,--wrap=exit,\ +--wrap=read,--wrap=pread,--wrap=write,--wrap=pwrite,--wrap=close,--wrap=sigaction,\ --wrap=sem_init,--wrap=sem_open,--wrap=sem_post,--wrap=sem_wait,--wrap=sem_trywait,--wrap=sem_timedwait,--wrap=sem_getvalue,--wrap=sem_close,--wrap=sem_unlink,--wrap=sem_destroy,\ --wrap=shm_open,--wrap=shm_unlink,--wrap=mmap,--wrap=munmap,\ ---wrap=ftruncate +--wrap=ftruncate,--wrap=fork,--wrap=wait,--wrap=waitpid,--wrap=pipe,--wrap=dup,--wrap=dup2,--wrap=dup3,\ +--wrap=execl,--wrap=execlp,--wrap=execle,--wrap=execv,--wrap=execvp,--wrap=execvpe,--wrap=execve,--wrap=fexecve clean: rm -rf main_intercept bin/* *.so *.ko *.o diff --git a/proj/intercept/src/intercept.c b/proj/intercept/src/intercept.c index c7d0f9c..0d7b91e 100644 --- a/proj/intercept/src/intercept.c +++ b/proj/intercept/src/intercept.c @@ -22,6 +22,12 @@ #define BUFFER_SIZE 256 #ifdef INTERCEPT_PRELOAD +#define load(name) \ + if (((__real_ ## name) = dlsym(RTLD_NEXT, #name)) == NULL) { \ + fprintf(stderr, "intercept: unable to load symbol '%s': %s", #name, strerror(errno)); \ + return; \ + } +#define sym(name) name static void *(*__real_malloc)(size_t); static void *(*__real_calloc)(size_t, size_t); static void *(*__real_realloc)(void *, size_t); @@ -29,6 +35,10 @@ static void *(*__real_reallocarray)(void *, size_t, size_t); static void (*__real_free)(void *); static int (*__real_getopt)(int, char *const [], const char *); static void (*__real_exit)(int); +static ssize_t (*__real_read)(int, void *, size_t); +static ssize_t (*__real_pread)(int, void *, size_t, off_t); +static ssize_t (*__real_write)(int, const void *, size_t); +static ssize_t (*__real_pwrite)(int, const void *, size_t, off_t); static int (*__real_close)(int); static int (*__real_sigaction)(int, const struct sigaction *, struct sigaction *); static int (*__real_sem_init)(sem_t *, int, unsigned int); @@ -46,13 +56,23 @@ static int (*__real_shm_unlink)(const char *); static void *(*__real_mmap)(void *, size_t, int, int, int, off_t); static int (*__real_munmap)(void *, size_t); static int (*__real_ftruncate)(int, off_t); -#define load(name) \ - if (((__real_ ## name) = dlsym(RTLD_NEXT, #name)) == NULL) { \ - fprintf(stderr, "intercept: unable to load symbol '%s': %s", #name, strerror(errno)); \ - return; \ - } -#define sym(name) name +static pid_t (*__real_fork)(void); +static pid_t (*__real_wait)(int *); +static pid_t (*__real_waitpid)(pid_t, int *, int); +static int (*__real_execl)(const char *, const char *, ...); +static int (*__real_execlp)(const char *, const char *, ...); +static int (*__real_execle)(const char *, const char *, ...); +static int (*__real_execv)(const char *, char *const[]); +static int (*__real_execvp)(const char *, char *const[]); +static int (*__real_execvpe)(const char *, char *const[], char *const[]); +static int (*__real_execve)(const char *, char *const[], char *const[]); +static int (*__real_fexecve)(int, char *const[], char *const[]); +static int (*__real_pipe)(int[2]); +static int (*__real_dup)(int); +static int (*__real_dup2)(int, int); +static int (*__real_dup3)(int, int, int); #else +#define sym(name) __wrap_ ## name extern void *__real_malloc(size_t); extern void *__real_calloc(size_t, size_t); extern void *__real_realloc(void *, size_t); @@ -60,6 +80,10 @@ extern void *__real_reallocarray(void *, size_t, size_t); extern void __real_free(void *); extern int __real_getopt(int, char *const [], const char *); extern void __real_exit(int); +extern ssize_t __real_read(int, void *, size_t); +extern ssize_t __real_pread(int, void *, size_t, off_t); +extern ssize_t __real_write(int, const void *, size_t); +extern ssize_t __real_pwrite(int, const void *, size_t, off_t); extern int __real_close(int); extern int __real_sigaction(int, const struct sigaction *, struct sigaction *); extern int __real_sem_init(sem_t *, int, unsigned int); @@ -77,11 +101,31 @@ extern int __real_shm_unlink(const char *); extern void *__real_mmap(void *, size_t, int, int, int, off_t); extern int __real_munmap(void *, size_t); extern int __real_ftruncate(int, off_t); -#define sym(name) __wrap_ ## name +extern pid_t __real_fork(void); +extern pid_t __real_wait(int *); +extern pid_t __real_waitpid(pid_t, int *, int); +extern int __real_execl(const char *, const char *, ...); +extern int __real_execlp(const char *, const char *, ...); +extern int __real_execle(const char *, const char *, ...); +extern int __real_execv(const char *, char *const[]); +extern int __real_execvp(const char *, char *const[]); +extern int __real_execvpe(const char *, char *const[], char *const[]); +extern int __real_execve(const char *, char *const[], char *const[]); +extern int __real_fexecve(int, char *const[], char *const[]); +extern int __real_pipe(int[2]); +extern int __real_dup(int); +extern int __real_dup2(int, int); +extern int __real_dup3(int, int, int); #endif #define ret_addr __builtin_return_address(0) +#define if_fail if (strncmp(msg_buf, "fail ", 5) == 0) + +#define if_fail_int_errno(name) if_fail { set_errno(#name, msg_buf); return -1; } + +#define if_fail_ptr_errno(name) if_fail { set_errno(#name, msg_buf); return NULL; } + #define if_invalid(name) if (strcmp(msg_buf, "ok") != 0) { fprintf(stderr, "intercept: %s: invalid command: '%s'\n", #name, msg_buf); } #define if_modify_int(name, type_1, var_1) if (strncmp(msg_buf, "modify ", 7) == 0) { \ @@ -124,9 +168,7 @@ extern int __real_ftruncate(int, off_t); fprintf(stderr, "intercept: %s: invalid args in modify command: '%s'\n", #name, msg_buf + 7); \ } } -#define if_return if (strcmp(msg_buf, "return") == 0) { \ - msg("return"); \ - return; } +#define if_return if (strcmp(msg_buf, "return") == 0) { msg("return"); return; } #define if_return_int(name) if (strncmp(msg_buf, "return ", 7) == 0) { \ char *end_ptr = NULL; \ @@ -173,107 +215,150 @@ extern int __real_ftruncate(int, off_t); fprintf(stderr, "intercept: %s: invalid args in return command: '%s'\n", #name, msg_buf + 7); \ } } -#define if_error_1_ptr_errno(name, err1) if (strncmp(msg_buf, "fail ", 5) == 0) { \ - if (strcmp(msg_buf + 5, #err1) == 0) { errno = err1; \ - } else { \ - errno = 0; \ - fprintf(stderr, "intercept: %s: invalid error code in fail command: '%s'\n", #name, msg_buf + 5); \ - } \ - msg("return %p; errno %s", NULL, strerrorname_np(errno)); \ - return NULL; } - -#define if_error_1_int_errno(name, err1) if (strncmp(msg_buf, "fail ", 5) == 0) { \ - if (strcmp(msg_buf + 5, #err1) == 0) { errno = err1; \ - } else { \ - errno = 0; \ - fprintf(stderr, "intercept: %s: invalid error code in fail command: '%s'\n", #name, msg_buf + 5); \ - } \ - msg("return %i; errno %s", -1, strerrorname_np(errno)); \ - return -1; } - -#define if_error_2_int_errno(name, err1, err2) if (strncmp(msg_buf, "fail ", 5) == 0) { \ - if (strcmp(msg_buf + 5, #err1) == 0) { errno = err1; \ - } else if (strcmp(msg_buf + 5, #err2) == 0) { errno = err2; \ - } else { \ - errno = 0; \ - fprintf(stderr, "intercept: %s: invalid error code in fail command: '%s'\n", #name, msg_buf + 5); \ - } \ - msg("return %i; errno %s", -1, strerrorname_np(errno)); \ - return -1; } - -#define if_error_3_int_errno(name, err1, err2, err3) if (strncmp(msg_buf, "fail ", 5) == 0) { \ - if (strcmp(msg_buf + 5, #err1) == 0) { errno = err1; \ - } else if (strcmp(msg_buf + 5, #err2) == 0) { errno = err2; \ - } else if (strcmp(msg_buf + 5, #err3) == 0) { errno = err3; \ - } else { \ - errno = 0; \ - fprintf(stderr, "intercept: %s: invalid error code in fail command: '%s'\n", #name, msg_buf + 5); \ - } \ - msg("return %i; errno %s", -1, strerrorname_np(errno)); \ - return -1; } - -#define if_error_5_int_errno(name, err1, err2, err3, err4, err5) if (strncmp(msg_buf, "fail ", 5) == 0) { \ - if (strcmp(msg_buf + 5, #err1) == 0) { errno = err1; \ - } else if (strcmp(msg_buf + 5, #err2) == 0) { errno = err2; \ - } else if (strcmp(msg_buf + 5, #err3) == 0) { errno = err3; \ - } else if (strcmp(msg_buf + 5, #err4) == 0) { errno = err4; \ - } else if (strcmp(msg_buf + 5, #err5) == 0) { errno = err5; \ - } else { \ - errno = 0; \ - fprintf(stderr, "intercept: %s: invalid error code in fail command: '%s'\n", #name, msg_buf + 5); \ - } \ - msg("return %i; errno %s", -1, strerrorname_np(errno)); \ - return -1; } - -#define if_error_7_int_errno(name, err1, err2, err3, err4, err5, err6, err7) if (strncmp(msg_buf, "fail ", 5) == 0) { \ - if (strcmp(msg_buf + 5, #err1) == 0) { errno = err1; \ - } else if (strcmp(msg_buf + 5, #err2) == 0) { errno = err2; \ - } else if (strcmp(msg_buf + 5, #err3) == 0) { errno = err3; \ - } else if (strcmp(msg_buf + 5, #err4) == 0) { errno = err4; \ - } else if (strcmp(msg_buf + 5, #err5) == 0) { errno = err5; \ - } else if (strcmp(msg_buf + 5, #err6) == 0) { errno = err6; \ - } else if (strcmp(msg_buf + 5, #err7) == 0) { errno = err7; \ - } else { \ - errno = 0; \ - fprintf(stderr, "intercept: %s: invalid error code in fail command: '%s'\n", #name, msg_buf + 5); \ - } \ - msg("return %i; errno %s", -1, strerrorname_np(errno)); \ - return -1; } - -#define if_error_8_ptr_errno(name, err1, err2, err3, err4, err5, err6, err7, err8) if (strncmp(msg_buf, "fail ", 5) == 0) { \ - if (strcmp(msg_buf + 5, #err1) == 0) { errno = err1; \ - } else if (strcmp(msg_buf + 5, #err2) == 0) { errno = err2; \ - } else if (strcmp(msg_buf + 5, #err3) == 0) { errno = err3; \ - } else if (strcmp(msg_buf + 5, #err4) == 0) { errno = err4; \ - } else if (strcmp(msg_buf + 5, #err5) == 0) { errno = err5; \ - } else if (strcmp(msg_buf + 5, #err6) == 0) { errno = err6; \ - } else if (strcmp(msg_buf + 5, #err6) == 0) { errno = err7; \ - } else if (strcmp(msg_buf + 5, #err8) == 0) { errno = err8; \ - } else { \ - errno = 0; \ - fprintf(stderr, "intercept: %s: invalid error code in fail command: '%s'\n", #name, msg_buf + 5); \ - } \ - msg("return %p; errno %s", NULL, strerrorname_np(errno)); \ - return NULL; } - -#define if_error_10_map_errno(name, err1, err2, err3, err4, err5, err6, err7, err8, err9, err10) if (strncmp(msg_buf, "fail ", 5) == 0) { \ - if (strcmp(msg_buf + 5, #err1) == 0) { errno = err1; \ - } else if (strcmp(msg_buf + 5, #err2) == 0) { errno = err2; \ - } else if (strcmp(msg_buf + 5, #err3) == 0) { errno = err3; \ - } else if (strcmp(msg_buf + 5, #err4) == 0) { errno = err4; \ - } else if (strcmp(msg_buf + 5, #err5) == 0) { errno = err5; \ - } else if (strcmp(msg_buf + 5, #err6) == 0) { errno = err6; \ - } else if (strcmp(msg_buf + 5, #err7) == 0) { errno = err7; \ - } else if (strcmp(msg_buf + 5, #err8) == 0) { errno = err8; \ - } else if (strcmp(msg_buf + 5, #err9) == 0) { errno = err9; \ - } else if (strcmp(msg_buf + 5, #err10) == 0) { errno = err10; \ - } else { \ - errno = 0; \ - fprintf(stderr, "intercept: %s: invalid error code in fail command: '%s'\n", #name, msg_buf + 5); \ - } \ - msg("return %i; errno %s", MAP_FAILED, strerrorname_np(errno)); \ - return MAP_FAILED; } +#define if_error(err) if (strcmp(msg_buf + 5, #err) == 0) { errno = err; } +static long set_errno(const char *name, const char *msg_buf) { + char *end_ptr = NULL; + long val = strtol(msg_buf + 5, &end_ptr, 0); + if (end_ptr != NULL && end_ptr[0] == 0 && end_ptr != msg_buf + 5) { + errno = (int)val; + } else if_error(EPERM) + else if_error(ENOENT) + else if_error(ESRCH) + else if_error(EINTR) + else if_error(EIO) + else if_error(ENXIO) + else if_error(E2BIG) + else if_error(ENOEXEC) + else if_error(EBADF) + else if_error(ECHILD) + else if_error(EAGAIN) + else if_error(ENOMEM) + else if_error(EACCES) + else if_error(EFAULT) + else if_error(ENOTBLK) + else if_error(EBUSY) + else if_error(EEXIST) + else if_error(EXDEV) + else if_error(ENODEV) + else if_error(ENOTDIR) + else if_error(EISDIR) + else if_error(EINVAL) + else if_error(ENFILE) + else if_error(EMFILE) + else if_error(ENOTTY) + else if_error(ETXTBSY) + else if_error(EFBIG) + else if_error(ENOSPC) + else if_error(ESPIPE) + else if_error(EROFS) + else if_error(EMLINK) + else if_error(EPIPE) + else if_error(EDOM) + else if_error(ERANGE) + else if_error(EDEADLK) + else if_error(ENAMETOOLONG) + else if_error(ENOLCK) + else if_error(ENOSYS) + else if_error(ENOTEMPTY) + else if_error(ELOOP) + else if_error(EWOULDBLOCK) + else if_error(ENOMSG) + else if_error(EIDRM) + else if_error(ECHRNG) + else if_error(EL2NSYNC) + else if_error(EL3HLT) + else if_error(EL3RST) + else if_error(ELNRNG) + else if_error(EUNATCH) + else if_error(ENOCSI) + else if_error(EL2HLT) + else if_error(EBADE) + else if_error(EBADR) + else if_error(EXFULL) + else if_error(ENOANO) + else if_error(EBADRQC) + else if_error(EBADSLT) + else if_error(EDEADLOCK) + else if_error(EBFONT) + else if_error(ENOSTR) + else if_error(ENODATA) + else if_error(ETIME) + else if_error(ENOSR) + else if_error(ENONET) + else if_error(ENOPKG) + else if_error(EREMOTE) + else if_error(ENOLINK) + else if_error(EADV) + else if_error(ESRMNT) + else if_error(ECOMM) + else if_error(EPROTO) + else if_error(EMULTIHOP) + else if_error(EDOTDOT) + else if_error(EBADMSG) + else if_error(EOVERFLOW) + else if_error(ENOTUNIQ) + else if_error(EBADFD) + else if_error(EREMCHG) + else if_error(ELIBACC) + else if_error(ELIBBAD) + else if_error(ELIBSCN) + else if_error(ELIBMAX) + else if_error(ELIBEXEC) + else if_error(EILSEQ) + else if_error(ERESTART) + else if_error(ESTRPIPE) + else if_error(EUSERS) + else if_error(ENOTSOCK) + else if_error(EDESTADDRREQ) + else if_error(EMSGSIZE) + else if_error(EPROTOTYPE) + else if_error(ENOPROTOOPT) + else if_error(EPROTONOSUPPORT) + else if_error(ESOCKTNOSUPPORT) + else if_error(EOPNOTSUPP) + else if_error(EPFNOSUPPORT) + else if_error(EAFNOSUPPORT) + else if_error(EADDRINUSE) + else if_error(EADDRNOTAVAIL) + else if_error(ENETDOWN) + else if_error(ENETRESET) + else if_error(ECONNABORTED) + else if_error(ECONNRESET) + else if_error(ENOBUFS) + else if_error(EISCONN) + else if_error(ENOTCONN) + else if_error(ESHUTDOWN) + else if_error(ETOOMANYREFS) + else if_error(ETIMEDOUT) + else if_error(ECONNREFUSED) + else if_error(EHOSTDOWN) + else if_error(EHOSTUNREACH) + else if_error(EALREADY) + else if_error(EINPROGRESS) + else if_error(ESTALE) + else if_error(EUCLEAN) + else if_error(ENOTNAM) + else if_error(ENAVAIL) + else if_error(EISNAM) + else if_error(EREMOTEIO) + else if_error(EDQUOT) + else if_error(ENOMEDIUM) + else if_error(EMEDIUMTYPE) + else if_error(ECANCELED) + else if_error(ENOKEY) + else if_error(EKEYEXPIRED) + else if_error(EKEYREVOKED) + else if_error(EKEYREJECTED) + else if_error(EOWNERDEAD) + else if_error(ENOTRECOVERABLE) + else if_error(ERFKILL) + else if_error(EHWPOISON) + else { + errno = 0; + fprintf(stderr, "intercept: %s: invalid error code in fail command: '%s'\n", name, msg_buf + 5); + } +} static char *strtostr(char *ptr, char **end_ptr, char *buf) { if (ptr[0] != '"') return NULL; @@ -339,9 +424,10 @@ static char *strtostr(char *ptr, char **end_ptr, char *buf) { static int mode = 0; static int intercept = 0; -static size_t msg_str(char *buf, size_t maxlen, const char *str) { +static size_t msg_bytes(char *buf, size_t maxlen, size_t len, const char *str) { size_t offset = snprintf(buf, maxlen, "%p:\"", str); - for (char ch; (ch = *str) != 0 && offset <= maxlen - 2; str++) { + for (int i = 0; i < len && offset <= maxlen - 2; i++) { + char ch = str[i]; if (ch == '\\' || ch == '"') { buf[offset++] = '\\'; buf[offset++] = ch; @@ -367,6 +453,10 @@ static size_t msg_str(char *buf, size_t maxlen, const char *str) { return offset; } +static size_t msg_str(char *buf, size_t maxlen, const char *str) { + return msg_bytes(buf, maxlen, strlen(str), str); +} + static size_t msg_array_str(char *buf, size_t maxlen, char *const array[], int n) { size_t offset = snprintf(buf, maxlen, "%p:[", (void *)array); for (int i = 0; i < n && offset <= maxlen - 2; i++) { @@ -384,7 +474,7 @@ static size_t msg_array_str(char *buf, size_t maxlen, char *const array[], int n } static void msg(const char *fmt, ...) { - if (!intercept) return; + if (!intercept || mode == -1) return; char buf[1024], sub_fmt[16]; int sub_fmt_p = 0; @@ -424,6 +514,10 @@ static void msg(const char *fmt, ...) { if (ch == 's') { // escaped string offset += msg_str(buf + offset, sizeof(buf) - offset, va_arg(args, const char *)); + } else if (ch == 'b') { + // escaped byte sequence + const int len = va_arg(args, int); + offset += msg_bytes(buf + offset, sizeof(buf) - offset, len, va_arg(args, const char *)); } else { // error va_end(args); @@ -433,8 +527,8 @@ static void msg(const char *fmt, ...) { } else if (state == 'a') { if (ch == 's') { // string array - char *const *array = va_arg(args, char *const *); const int len = va_arg(args, int); + char *const *array = va_arg(args, char *const *); offset += msg_array_str(buf + offset, sizeof(buf) - offset, array, len); } else { // error @@ -456,7 +550,7 @@ static void msg(const char *fmt, ...) { ssize_t ret; for (size_t written = 0; written < size; written += ret) { - if ((ret = write(intercept, buf, size)) == -1) { + if ((ret = __real_write(intercept, buf, size)) == -1) { if (errno == EINTR) { ret = 0; continue; @@ -473,7 +567,7 @@ static void rcv(char *buf, const int size) { if (!intercept) return; size_t num = 0; for (ssize_t ret; num == 0 || buf[num - 1] != '\n'; num += ret) { - if ((ret = read(intercept, buf, size)) == -1) { + if ((ret = __real_read(intercept, buf, size)) == -1) { if (errno == EINTR) { ret = 0; continue; @@ -495,6 +589,7 @@ static void fin(void) { static void init(void) { if (mode) return; + mode = -1; #ifdef INTERCEPT_PRELOAD load(malloc); load(calloc); @@ -503,6 +598,10 @@ static void init(void) { load(free); load(getopt); load(exit); + load(read); + load(pread); + load(write); + load(pwrite); load(close); load(sigaction); load(sem_init); @@ -520,30 +619,44 @@ static void init(void) { load(mmap); load(munmap); load(ftruncate); + load(fork); + load(wait); + load(waitpid); + load(execl); + load(execlp); + load(execle); + load(execv); + load(execvp); + load(execvpe); + load(execve); + load(fexecve); + load(pipe); + load(dup); + load(dup2); + load(dup3) #endif atexit(fin); const char *val = getenv("INTERCEPT"); if (val && strcmp(val, "stdout") == 0) { - mode = 1; fprintf(stderr, "intercept: intercepting function/system calls and logging to stdout\n"); intercept = STDOUT_FILENO; + mode = 1; } else if (val && strcmp(val, "stderr") == 0) { - mode = 2; fprintf(stderr, "intercept: intercepting function/system calls and logging to stderr\n"); intercept = STDERR_FILENO; + mode = 2; } else if (val && strncmp(val, "file:", 5) == 0) { - mode = 3; if ((intercept = open(val + 5, O_CREAT | O_TRUNC | O_WRONLY, 0644)) == -1) { - fprintf(stderr, "intercept: unable to open log file '%s': %s\nintercept: not logging or manipulating function/system calls\n", val + 5, strerror(errno)); + fprintf(stderr, "intercept: unable to open log file '%s': %s\n" "intercept: not logging or manipulating function/system calls\n", val + 5, strerror(errno)); errno = 0; mode = -1; return; } fprintf(stderr, "intercept: intercepting function/system calls and logging to file\n"); + mode = 3; } else if (val && strncmp(val, "unix:", 5) == 0) { - mode = 4; if ((intercept = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { - fprintf(stderr, "intercept: unable to open unix socket '%s': %s\nintercept: not logging or manipulating function/system calls\n", val + 5, strerror(errno)); + fprintf(stderr, "intercept: unable to open unix socket '%s': %s\n" "intercept: not logging or manipulating function/system calls\n", val + 5, strerror(errno)); errno = 0; mode = -1; return; @@ -551,7 +664,7 @@ static void init(void) { struct sockaddr_un addr = {.sun_family = AF_UNIX}; strncpy(addr.sun_path, val + 5, sizeof(addr.sun_path)); if (connect(intercept, (struct sockaddr *)&addr, sizeof(addr)) == -1) { - fprintf(stderr, "intercept: unable to connect to unix socket '%s': %s\nintercept: not logging or manipulating function/system calls\n", val + 5, strerror(errno)); + fprintf(stderr, "intercept: unable to connect to unix socket '%s': %s\n" "intercept: not logging or manipulating function/system calls\n", val + 5, strerror(errno)); close(intercept); errno = 0; mode = -1; @@ -560,12 +673,12 @@ static void init(void) { fprintf(stderr, "intercept: intercepting function/system calls and logging to unix socket\n"); char buf[256] = ""; const ssize_t ret = readlink("/proc/self/exe", buf, sizeof(buf)); + mode = 4; msg("PID:%li%s%s", getpid(), ret != -1 ? ";PATH:" : "", buf); } else if (val && strncmp(val, "tcp://", 6) == 0) { - mode = 5; // TODO socket/tcp mode + mode = 5; } else { - mode = -1; fprintf(stderr, "intercept: not logging or manipulating function/system calls\n"); } } @@ -578,7 +691,7 @@ void *sym(malloc)(size_t size) { rcv(msg_buf, sizeof(msg_buf)); if_modify_int(malloc, size_t, size) else if_return_ptr_errno(malloc) - else if_error_1_ptr_errno(malloc, ENOMEM) + else if_fail_ptr_errno(malloc) else if_invalid(malloc) } void *ret = __real_malloc(size); @@ -594,7 +707,7 @@ void *sym(calloc)(size_t nmemb, size_t size) { rcv(msg_buf, sizeof(msg_buf)); if_modify_int_int(calloc, size_t, nmemb, size_t, size) else if_return_ptr_errno(calloc) - else if_error_1_ptr_errno(calloc, ENOMEM) + else if_fail_ptr_errno(calloc) else if_invalid(calloc) } void *ret = __real_calloc(nmemb, size); @@ -610,7 +723,7 @@ void *sym(realloc)(void *ptr, size_t size) { rcv(msg_buf, sizeof(msg_buf)); if_modify_int_int(realloc, void *, ptr, size_t, size) else if_return_ptr_errno(realloc) - else if_error_1_ptr_errno(realloc, ENOMEM) + else if_fail_ptr_errno(realloc) else if_invalid(realloc) } void *ret = __real_realloc(ptr, size); @@ -626,7 +739,7 @@ void *sym(reallocarray)(void *ptr, size_t nmemb, size_t size) { rcv(msg_buf, sizeof(msg_buf)); if_modify_int_int_int(reallocarray, void *, ptr, size_t, nmemb, size_t, size) else if_return_ptr_errno(reallocarray) - else if_error_1_ptr_errno(reallocarray, ENOMEM) + else if_fail_ptr_errno(reallocarray) else if_invalid(reallocarray) } void *ret = __real_reallocarray(ptr, nmemb, size); @@ -650,7 +763,7 @@ void sym(free)(void *ptr) { int sym(getopt)(const int argc, char *const argv[], const char *shortopts) { init(); - msg("getopt(%i, %as, %es): %p", argc, argv, argc, shortopts, ret_addr); + msg("getopt(%i, %as, %es): %p", argc, argc, argv, shortopts, ret_addr); if (mode >= 4) { char msg_buf[BUFFER_SIZE]; rcv(msg_buf, sizeof(msg_buf)); @@ -678,6 +791,86 @@ void sym(exit)(int status) { __real_exit(status); } +ssize_t sym(read)(int fildes, void *buf, size_t nbyte) { + init(); + msg("read(%i, %p, %i): %p", fildes, buf, nbyte, ret_addr); + if (mode >= 4) { + char msg_buf[BUFFER_SIZE]; + rcv(msg_buf, sizeof(msg_buf)); + if (strncmp(msg_buf, "modify ", 7) == 0) { + // TODO read modify + fprintf(stderr, "intercept: %s: modify command not implemented\n", "read"); + } else if_return_int_errno(read) + else if_fail_int_errno(read) + else if_invalid(read) + } + const ssize_t ret = __real_read(fildes, buf, nbyte); + if (ret >= 0) { + msg("return %i; errno %s; buf=%eb", ret, strerrorname_np(errno), ret, buf); + } else { + msg("return %i; errno %s", ret, strerrorname_np(errno)); + } + return ret; +} + +ssize_t sym(pread)(int fildes, void *buf, size_t nbyte, off_t offset) { + init(); + msg("pread(%i, %p, %i, %i): %p", fildes, buf, nbyte, offset, ret_addr); + if (mode >= 4) { + char msg_buf[BUFFER_SIZE]; + rcv(msg_buf, sizeof(msg_buf)); + if (strncmp(msg_buf, "modify ", 7) == 0) { + // TODO pread modify + fprintf(stderr, "intercept: %s: modify command not implemented\n", "pread"); + } else if_return_int_errno(pread) + else if_fail_int_errno(pread) + else if_invalid(pread) + } + const ssize_t ret = __real_pread(fildes, buf, nbyte, offset); + if (ret >= 0) { + msg("return %i; errno %s; buf=%eb", ret, strerrorname_np(errno), ret, buf); + } else { + msg("return %i; errno %s", ret, strerrorname_np(errno)); + } + return ret; +} + +ssize_t sym(write)(int fildes, const void *buf, size_t nbyte) { + init(); + msg("write(%i, %eb, %i): %p", fildes, buf, nbyte, buf, nbyte, ret_addr); + if (mode >= 4) { + char msg_buf[BUFFER_SIZE]; + rcv(msg_buf, sizeof(msg_buf)); + if (strncmp(msg_buf, "modify ", 7) == 0) { + // TODO write modify + fprintf(stderr, "intercept: %s: modify command not implemented\n", "write"); + } else if_return_int_errno(write) + else if_fail_int_errno(write) + else if_invalid(write) + } + const ssize_t ret = __real_write(fildes, buf, nbyte); + msg("return %i; errno %s", ret, strerrorname_np(errno)); + return ret; +} + +ssize_t sym(pwrite)(int fildes, const void *buf, size_t nbyte, off_t offset) { + init(); + msg("pwrite(%i, %eb, %i, %i): %p", fildes, buf, nbyte, buf, nbyte, offset, ret_addr); + if (mode >= 4) { + char msg_buf[BUFFER_SIZE]; + rcv(msg_buf, sizeof(msg_buf)); + if (strncmp(msg_buf, "modify ", 7) == 0) { + // TODO pwrite modify + fprintf(stderr, "intercept: %s: modify command not implemented\n", "pwrite"); + } else if_return_int_errno(pwrite) + else if_fail_int_errno(pwrite) + else if_invalid(pwrite) + } + const ssize_t ret = __real_pwrite(fildes, buf, nbyte, offset); + msg("return %i; errno %s", ret, strerrorname_np(errno)); + return ret; +} + int sym(close)(int fildes) { init(); msg("close(%i): %p", fildes, ret_addr); @@ -686,7 +879,7 @@ int sym(close)(int fildes) { rcv(msg_buf, sizeof(msg_buf)); if_modify_int(close, int, fildes) else if_return_int_errno(close) - else if_error_3_int_errno(close, EBADF, EINTR, EIO) + else if_fail_int_errno(close) else if_invalid(close) } const int ret = __real_close(fildes); @@ -764,7 +957,7 @@ int sym(sigaction)(int sig, const struct sigaction *restrict act, struct sigacti } else if (strncmp(msg_buf, "return ", 7) == 0) { // TODO sigaction return fprintf(stderr, "intercept: %s: return command not implemented\n", "sigaction"); - } else if_error_1_int_errno(sigaction, EINVAL) + } else if_fail_int_errno(sigaction) else if_invalid(sigaction) } const int ret = __real_sigaction(sig, act, oact); @@ -802,7 +995,7 @@ int sym(sem_init)(sem_t *sem, int pshared, unsigned int value) { rcv(msg_buf, sizeof(msg_buf)); if_modify_int_int_int(sem_init, sem_t *, sem, int, pshared, unsigned int, value) else if_return_int_errno(sem_init) - else if_error_2_int_errno(sem_init, EINVAL, ENOSYS) + else if_fail_int_errno(sem_init) else if_invalid(sem_init) } const int ret = __real_sem_init(sem, pshared, value); @@ -878,10 +1071,10 @@ sem_t *sym(sem_open)(const char *name, int oflag, ...) { value = val_4; } } else { - fprintf(stderr, "intercept: %s: invalid args in modify command: '%s'\n", "sem_open", msg_buf + 7); \ + fprintf(stderr, "intercept: %s: invalid args in modify command: '%s'\n", "sem_open", msg_buf + 7); } } else if_return_ptr_errno(sem_open) - else if_error_8_ptr_errno(sem_open, EACCES, EEXIST, EINVAL, EMFILE, ENAMETOOLONG, ENFILE, ENOENT, ENOMEM) + else if_fail_ptr_errno(sem_open) else if_invalid(sem_open) } @@ -903,7 +1096,7 @@ int sym(sem_post)(sem_t *sem) { rcv(msg_buf, sizeof(msg_buf)); if_modify_int(sem_post, sem_t *, sem) else if_return_int_errno(sem_post) - else if_error_2_int_errno(sem_post, EINVAL, EOVERFLOW) + else if_fail_int_errno(sem_post) else if_invalid(sem_post) } const int ret = __real_sem_post(sem); @@ -919,7 +1112,7 @@ int sym(sem_wait)(sem_t *sem) { rcv(msg_buf, sizeof(msg_buf)); if_modify_int(sem_wait, sem_t *, sem) else if_return_int_errno(sem_wait) - else if_error_2_int_errno(sem_wait, EINTR, EINVAL) + else if_fail_int_errno(sem_wait) else if_invalid(sem_wait) } const int ret = __real_sem_wait(sem); @@ -935,7 +1128,7 @@ int sym(sem_trywait)(sem_t *sem) { rcv(msg_buf, sizeof(msg_buf)); if_modify_int(sem_trywait, sem_t *, sem) else if_return_int_errno(sem_trywait) - else if_error_3_int_errno(sem_trywait, EAGAIN, EINTR, EINVAL) + else if_fail_int_errno(sem_trywait) else if_invalid(sem_trywait) } const int ret = __real_sem_trywait(sem); @@ -977,10 +1170,10 @@ int sym(sem_timedwait)(sem_t *restrict sem, const struct timespec *restrict abs_ sem = (sem_t *)val_1; abs_timeout = val_2; } else { - fprintf(stderr, "intercept: %s: invalid args in modify command: '%s'\n", "sem_timedwait", msg_buf + 7); \ + fprintf(stderr, "intercept: %s: invalid args in modify command: '%s'\n", "sem_timedwait", msg_buf + 7); } } else if_return_int_errno(sem_timedwait) - else if_error_3_int_errno(sem_timedwait, EINTR, EINVAL, ETIMEDOUT) + else if_fail_int_errno(sem_timedwait) else if_invalid(sem_timedwait) } const int ret = __real_sem_timedwait(sem, abs_timeout); @@ -996,7 +1189,7 @@ int sym(sem_getvalue)(sem_t *restrict sem, int *restrict value) { rcv(msg_buf, sizeof(msg_buf)); if_modify_int_int(sem_getvalue, sem_t *, sem, int *, value) else if_return_int_errno_int(sem_getvalue, int, *value, "value") - else if_error_1_int_errno(sem_getvalue, EINVAL) + else if_fail_int_errno(sem_getvalue) else if_invalid(sem_getvalue) } const int ret = __real_sem_getvalue(sem, value); @@ -1016,7 +1209,7 @@ int sym(sem_close)(sem_t *sem) { rcv(msg_buf, sizeof(msg_buf)); if_modify_int(sem_close, sem_t *, sem) else if_return_int_errno(sem_close) - else if_error_1_int_errno(sem_close, EINVAL) + else if_fail_int_errno(sem_close) else if_invalid(sem_close) } const int ret = __real_sem_close(sem); @@ -1044,10 +1237,10 @@ int sym(sem_unlink)(const char *name) { if (end_ptr != NULL && end_ptr[0] == 0 && end_ptr != msg_buf + 7) { name = val; } else { - fprintf(stderr, "intercept: %s: invalid args in modify command: '%s'\n", "sem_unlink", msg_buf + 7); \ + fprintf(stderr, "intercept: %s: invalid args in modify command: '%s'\n", "sem_unlink", msg_buf + 7); } } else if_return_int_errno(sem_unlink) - else if_error_3_int_errno(sem_unlink, EACCES, ENAMETOOLONG, ENOENT) + else if_fail_int_errno(sem_unlink) else if_invalid(sem_unlink) } const int ret = __real_sem_unlink(name); @@ -1063,7 +1256,7 @@ int sym(sem_destroy)(sem_t *sem) { rcv(msg_buf, sizeof(msg_buf)); if_modify_int(sem_destroy, sem_t *, sem) else if_return_int_errno(sem_destroy) - else if_error_1_int_errno(sem_destroy, EINVAL) + else if_fail_int_errno(sem_destroy) else if_invalid(sem_destroy) } const int ret = __real_sem_destroy(sem); @@ -1136,10 +1329,10 @@ int sym(shm_open)(const char *name, int oflag, mode_t mode_arg) { oflag = (int)val_2; mode_arg = val_3; } else { - fprintf(stderr, "intercept: %s: invalid args in modify command: '%s'\n", "shm_open", msg_buf + 7); \ + fprintf(stderr, "intercept: %s: invalid args in modify command: '%s'\n", "shm_open", msg_buf + 7); } } else if_return_int_errno(shm_open) - else if_error_7_int_errno(shm_open, EACCES, EEXIST, EINVAL, EMFILE, ENAMETOOLONG, ENFILE, ENOENT) + else if_fail_int_errno(shm_open) else if_invalid(shm_open) } const int ret = __real_shm_open(name, oflag, mode); @@ -1167,10 +1360,10 @@ int sym(shm_unlink)(const char *name) { if (end_ptr != NULL && end_ptr[0] == 0 && end_ptr != msg_buf + 7) { name = val; } else { - fprintf(stderr, "intercept: %s: invalid args in modify command: '%s'\n", "shm_unlink", msg_buf + 7); \ + fprintf(stderr, "intercept: %s: invalid args in modify command: '%s'\n", "shm_unlink", msg_buf + 7); } } else if_return_int_errno(shm_unlink) - else if_error_3_int_errno(shm_unlink, EACCES, ENAMETOOLONG, ENOENT) + else if_fail_int_errno(shm_unlink) else if_invalid(shm_unlink) } const int ret = __real_shm_unlink(name); @@ -1201,8 +1394,10 @@ void *sym(mmap)(void *addr, size_t len, int prot, int flags, int fildes, off_t o // TODO mmap modify fprintf(stderr, "intercept: %s: modify command not implemented\n", "mmap"); } else if_return_ptr_errno(mmap) - else if_error_10_map_errno(mmap, EACCES, EAGAIN, EBADF, EINVAL, EMFILE, ENODEV, ENOMEM, ENOTSUP, ENXIO, EOVERFLOW) - else if_invalid(mmap) + else if_fail { + set_errno("mmap", msg_buf); + return MAP_FAILED; + } else if_invalid(mmap) } void *ret = __real_mmap(addr, len, prot, flags, fildes, off); msg("return %p; errno %s", ret, strerrorname_np(errno)); @@ -1217,7 +1412,7 @@ int sym(munmap)(void *addr, size_t len) { rcv(msg_buf, sizeof(msg_buf)); if_modify_int_int(munmap, void *, addr, size_t, len) else if_return_int_errno(munmap) - else if_error_1_int_errno(munmap, EINVAL) + else if_fail_int_errno(munmap) else if_invalid(munmap) } const int ret = __real_munmap(addr, len); @@ -1227,16 +1422,368 @@ int sym(munmap)(void *addr, size_t len) { int sym(ftruncate)(int fildes, off_t length) { init(); - msg("ftruncate(%i, %i): %p", fildes, length); + msg("ftruncate(%i, %i): %p", fildes, length, ret_addr); if (mode >= 4) { char msg_buf[BUFFER_SIZE]; rcv(msg_buf, sizeof(msg_buf)); if_modify_int_int(ftruncate, int, fildes, off_t, length) else if_return_int_errno(ftruncate) - else if_error_5_int_errno(ftruncate, EINTR, EINVAL, EFBIG, EIO, EBADF) + else if_fail_int_errno(ftruncate) else if_invalid(ftruncate) } const int ret = __real_ftruncate(fildes, length); msg("return %i; errno %s", ret, strerrorname_np(errno)); return ret; } + +pid_t sym(fork)(void) { + init(); + msg("fork(): %p", ret_addr); + if (mode >= 4) { + char msg_buf[BUFFER_SIZE]; + rcv(msg_buf, sizeof(msg_buf)); + if_return_int_errno(fork) + else if_fail_int_errno(fork) + else if_invalid(fork) + } + const pid_t ret = __real_fork(); + msg("return %i; errno %s", ret, strerrorname_np(errno)); + return ret; +} + +pid_t sym(wait)(int *stat_loc) { + init(); + msg("wait(%p): %p", stat_loc, ret_addr); + if (mode >= 4) { + char msg_buf[BUFFER_SIZE]; + rcv(msg_buf, sizeof(msg_buf)); + if_modify_int(wait, int *, stat_loc) + else if_return_int_errno_int(wait, int, *stat_loc, "stat_loc") + else if_fail_int_errno(wait) + else if_invalid(wait) + } + const pid_t ret = __real_wait(stat_loc); + if (stat_loc != NULL) { + msg("return %i; errno %s; stat=%i", ret, *stat_loc, strerrorname_np(errno)); + } else { + msg("return %i; errno %s", ret, strerrorname_np(errno)); + } + return ret; +} + +pid_t sym(waitpid)(pid_t pid, int *stat_loc, int options) { + init(); + char ostr[64] = "|"; + if (options & WCONTINUED) strcat(ostr, "WCONTINUED|"); + if (options & WNOHANG) strcat(ostr, "WNOHANG|"); + if (options & WUNTRACED) strcat(ostr, "WUNTRACED|"); + if (options & ~(WCONTINUED | WNOHANG | WUNTRACED)) strcat(ostr, "?|"); + + msg("waitpid(%i, %p, 0x%x:%s): %p", pid, stat_loc, options, ostr, ret_addr); + if (mode >= 4) { + char msg_buf[BUFFER_SIZE]; + rcv(msg_buf, sizeof(msg_buf)); + // TODO waitpid modify options + if_modify_int_int_int(waitpid, pid_t, pid, int *, stat_loc, int, options) + else if_return_int_errno_int(waitpid, int, *stat_loc, "stat_loc") + else if_fail_int_errno(waitpid) + else if_invalid(waitpid) + } + const pid_t ret = __real_waitpid(pid, stat_loc, options); + if (stat_loc != NULL) { + msg("return %i; errno %s; stat=%i", ret, *stat_loc, strerrorname_np(errno)); + } else { + msg("return %i; errno %s", ret, strerrorname_np(errno)); + } + return ret; +} + +int sym(execl)(const char *pathname, const char *arg, ...) { + init(); + va_list args; + va_start(args, arg); + const char *arg_vec[64]; + arg_vec[0] = arg; + for (int i = 1; i < 64 && arg_vec[i - 1] != NULL; i++) { + arg_vec[i] = va_arg(args, const char *); + } + va_end(args); + char arg_buf[4096] = "", *arg_buf_ptr = arg_buf; + for (int i = 1; i < 64; i++) { + arg_buf_ptr[0] = ','; + arg_buf_ptr[1] = ' '; + arg_buf_ptr[2] = 0; + arg_buf_ptr += 2; + if (arg_vec[i] == NULL) { + strcat(arg_buf_ptr, "NULL"); + break; + } + arg_buf_ptr += msg_str(arg_buf, sizeof(arg_buf) - (arg_buf_ptr - arg_buf), arg_vec[i]); + } + + msg("execl(%es, %es%s): %p", pathname, arg, arg_buf, ret_addr); + if (mode >= 4) { + char msg_buf[BUFFER_SIZE]; + rcv(msg_buf, sizeof(msg_buf)); + if (strncmp(msg_buf, "modify ", 7) == 0) { + // TODO execl modify + fprintf(stderr, "intercept: %s: modify command not implemented\n", "execl"); + } else if_return_int_errno(execl) + else if_fail_int_errno(execl) + else if_invalid(execl) + } + const int ret = __real_execv(pathname, (char *const *)arg_vec); + msg("return %i; errno %s", ret, strerrorname_np(errno)); + return ret; +} + +int sym(execlp)(const char *file, const char *arg, ...) { + init(); + va_list args; + va_start(args, arg); + const char *arg_vec[64]; + arg_vec[0] = arg; + for (int i = 1; i < 64 && arg_vec[i - 1] != NULL; i++) { + arg_vec[i] = va_arg(args, const char *); + } + va_end(args); + char arg_buf[4096] = "", *arg_buf_ptr = arg_buf; + for (int i = 1; i < 64; i++) { + arg_buf_ptr[0] = ','; + arg_buf_ptr[1] = ' '; + arg_buf_ptr[2] = 0; + arg_buf_ptr += 2; + if (arg_vec[i] == NULL) { + strcat(arg_buf_ptr, "NULL"); + break; + } + arg_buf_ptr += msg_str(arg_buf, sizeof(arg_buf) - (arg_buf_ptr - arg_buf), arg_vec[i]); + } + + msg("execlp(%es, %es%s): %p", file, arg, arg_buf, ret_addr); + if (mode >= 4) { + char msg_buf[BUFFER_SIZE]; + rcv(msg_buf, sizeof(msg_buf)); + if (strncmp(msg_buf, "modify ", 7) == 0) { + // TODO execlp modify + fprintf(stderr, "intercept: %s: modify command not implemented\n", "execlp"); + } else if_return_int_errno(execlp) + else if_fail_int_errno(execlp) + else if_invalid(execlp) + } + const int ret = __real_execvp(file, (char *const *)arg_vec); + msg("return %i; errno %s", ret, strerrorname_np(errno)); + return ret; +} + +int sym(execle)(const char *pathname, const char *arg, ...) { + init(); + va_list args; + va_start(args, arg); + const char *arg_vec[64]; + char *const *envp = NULL; + arg_vec[0] = arg; + for (int i = 1; i < 64; i++) { + arg_vec[i] = va_arg(args, const char *); + if (arg_vec[i] == NULL) { + envp = va_arg(args, char *const *); + break; + } + } + va_end(args); + char arg_buf[4096] = "", *arg_buf_ptr = arg_buf; + for (int i = 1; i < 64; i++) { + arg_buf_ptr[0] = ','; + arg_buf_ptr[1] = ' '; + arg_buf_ptr[2] = 0; + arg_buf_ptr += 2; + if (arg_vec[i] == NULL) { + strcat(arg_buf_ptr, "NULL"); + break; + } + arg_buf_ptr += msg_str(arg_buf, sizeof(arg_buf) - (arg_buf_ptr - arg_buf), arg_vec[i]); + } + + int len = 0; for (len = 0; envp[len] != NULL; len++) {} + msg("execle(%es, %es%s, %as): %p", pathname, arg, arg_buf, len, envp, ret_addr); + if (mode >= 4) { + char msg_buf[BUFFER_SIZE]; + rcv(msg_buf, sizeof(msg_buf)); + if (strncmp(msg_buf, "modify ", 7) == 0) { + // TODO execle modify + fprintf(stderr, "intercept: %s: modify command not implemented\n", "execle"); + } else if_return_int_errno(execle) + else if_fail_int_errno(execle) + else if_invalid(execle) + } + const int ret = __real_execvpe(pathname, (char *const *)arg_vec, envp); + msg("return %i; errno %s", ret, strerrorname_np(errno)); + return ret; +} + +int sym(execv)(const char *pathname, char *const argv[]) { + init(); + int len = 0; for (len = 0; argv[len] != NULL; len++) {} + msg("execv(%es, %as): %p", pathname, len, argv, ret_addr); + if (mode >= 4) { + char msg_buf[BUFFER_SIZE]; + rcv(msg_buf, sizeof(msg_buf)); + if (strncmp(msg_buf, "modify ", 7) == 0) { + // TODO execv modify + fprintf(stderr, "intercept: %s: modify command not implemented\n", "execv"); + } else if_return_int_errno(execv) + else if_fail_int_errno(execv) + else if_invalid(execv) + } + const int ret = __real_execv(pathname, argv); + msg("return %i; errno %s", ret, strerrorname_np(errno)); + return ret; +} + +int sym(execvp)(const char *file, char *const argv[]) { + init(); + int len = 0; for (len = 0; argv[len] != NULL; len++) {} + msg("execvp(%es, %as): %p", file, len, argv, ret_addr); + if (mode >= 4) { + char msg_buf[BUFFER_SIZE]; + rcv(msg_buf, sizeof(msg_buf)); + if (strncmp(msg_buf, "modify ", 7) == 0) { + // TODO execvp modify + fprintf(stderr, "intercept: %s: modify command not implemented\n", "execvp"); + } else if_return_int_errno(execvp) + else if_fail_int_errno(execvp) + else if_invalid(execvp) + } + const int ret = __real_execvp(file, argv); + msg("return %i; errno %s", ret, strerrorname_np(errno)); + return ret; +} + +int sym(execvpe)(const char *file, char *const argv[], char *const envp[]) { + init(); + int len1 = 0; for (len1 = 0; argv[len1] != NULL; len1++) {} + int len2 = 0; for (len2 = 0; envp[len2] != NULL; len2++) {} + msg("execvpe(%es, %as, %as): %p", file, len1, argv, len2, envp, ret_addr); + if (mode >= 4) { + char msg_buf[BUFFER_SIZE]; + rcv(msg_buf, sizeof(msg_buf)); + if (strncmp(msg_buf, "modify ", 7) == 0) { + // TODO execvpe modify + fprintf(stderr, "intercept: %s: modify command not implemented\n", "execvpe"); + } else if_return_int_errno(execvpe) + else if_fail_int_errno(execvpe) + else if_invalid(execvpe) + } + const int ret = __real_execvpe(file, argv, envp); + msg("return %i; errno %s", ret, strerrorname_np(errno)); + return ret; +} + +int sym(execve)(const char *pathname, char *const argv[], char *const envp[]) { + init(); + int len1 = 0; for (len1 = 0; argv[len1] != NULL; len1++) {} + int len2 = 0; for (len2 = 0; envp[len2] != NULL; len2++) {} + msg("execve(%es, %as, %as): %p", pathname, len1, argv, len2, envp, ret_addr); + if (mode >= 4) { + char msg_buf[BUFFER_SIZE]; + rcv(msg_buf, sizeof(msg_buf)); + if (strncmp(msg_buf, "modify ", 7) == 0) { + // TODO execve modify + fprintf(stderr, "intercept: %s: modify command not implemented\n", "execve"); + } else if_return_int_errno(execve) + else if_fail_int_errno(execve) + else if_invalid(execve) + } + const int ret = __real_execve(pathname, argv, envp); + msg("return %i; errno %s", ret, strerrorname_np(errno)); + return ret; +} + +int sym(fexecve)(int fd, char *const argv[], char *const envp[]) { + init(); + int len1 = 0; for (len1 = 0; argv[len1] != NULL; len1++) {} + int len2 = 0; for (len2 = 0; envp[len2] != NULL; len2++) {} + msg("fexecve(%i, %as, %as): %p", fd, len1, argv, len2, envp, ret_addr); + if (mode >= 4) { + char msg_buf[BUFFER_SIZE]; + rcv(msg_buf, sizeof(msg_buf)); + if (strncmp(msg_buf, "modify ", 7) == 0) { + // TODO fexecve modify + fprintf(stderr, "intercept: %s: modify command not implemented\n", "fexecve"); + } else if_return_int_errno(fexecve) + else if_fail_int_errno(fexecve) + else if_invalid(fexecve) + } + const int ret = __real_fexecve(fd, argv, envp); + msg("return %i; errno %s", ret, strerrorname_np(errno)); + return ret; +} + +int sym(pipe)(int fildes[2]) { + init(); + msg("pipe(%p:[%i,%i]): %p", fildes, fildes[0], fildes[1], ret_addr); + if (mode >= 4) { + char msg_buf[BUFFER_SIZE]; + rcv(msg_buf, sizeof(msg_buf)); + if (strncmp(msg_buf, "modify ", 7) == 0) { + // TODO pipe modify + fprintf(stderr, "intercept: %s: modify command not implemented\n", "pipe"); + } else if_return_int_errno(pipe) + else if_fail_int_errno(pipe) + else if_invalid(pipe) + } + const int ret = __real_pipe(fildes); + msg("return %i; errno %s", ret, strerrorname_np(errno)); + return ret; +} + +int sym(dup)(int oldfd) { + init(); + msg("dup(%i): %p", oldfd, ret_addr); + if (mode >= 4) { + char msg_buf[BUFFER_SIZE]; + rcv(msg_buf, sizeof(msg_buf)); + if_modify_int(dup, int, oldfd) + else if_return_int_errno(dup) + else if_fail_int_errno(dup) + else if_invalid(dup) + } + const int ret = __real_dup(oldfd); + msg("return %i; errno %s", ret, strerrorname_np(errno)); + return ret; +} + +int sym(dup2)(int oldfd, int newfd) { + init(); + msg("dup2(%i, %i): %p", oldfd, newfd, ret_addr); + if (mode >= 4) { + char msg_buf[BUFFER_SIZE]; + rcv(msg_buf, sizeof(msg_buf)); + if_modify_int_int(dup2, int, oldfd, int, newfd) + else if_return_int_errno(dup2) + else if_fail_int_errno(dup2) + else if_invalid(dup2) + } + const int ret = __real_dup2(oldfd, newfd); + msg("return %i; errno %s", ret, strerrorname_np(errno)); + return ret; +} + +int sym(dup3)(int oldfd, int newfd, int flags) { + init(); + char fstr[16] = "|"; + if (flags & O_CLOEXEC) strcat(fstr, "O_CLOEXEC|"); + if (flags & ~(O_CLOEXEC)) strcat(fstr, "?|"); + msg("dup3(%i, %i, 0%o:%s): %p", oldfd, newfd, flags, fstr, ret_addr); + if (mode >= 4) { + char msg_buf[BUFFER_SIZE]; + rcv(msg_buf, sizeof(msg_buf)); + if_modify_int_int_int(dup3, int, oldfd, int, newfd, int, flags) + else if_return_int_errno(dup3) + else if_fail_int_errno(dup3) + else if_invalid(dup3) + } + const int ret = __real_dup3(oldfd, newfd, flags); + msg("return %i; errno %s", ret, strerrorname_np(errno)); + return ret; +} diff --git a/proj/server/src/intercept/__init__.py b/proj/server/src/intercept/__init__.py index 73b8dfb..0806150 100644 --- a/proj/server/src/intercept/__init__.py +++ b/proj/server/src/intercept/__init__.py @@ -90,7 +90,7 @@ class Handler(StreamRequestHandler): def parse_arg(argument: str) -> tuple[any, int]: if argument == '': return None, 0 - m = re.match(r'^\s*\(nil\)\s*(,|$)', argument) + m = re.match(r'^\s*(\(nil\)|NULL|null|nullptr)\s*(,|$)', argument) if m: return 0, len(m.group(0)) m = re.match(r'^\s*(.*?)([,:]|$)', argument) @@ -232,6 +232,30 @@ class Handler(StreamRequestHandler): def after_getopt(self, argc: int, argv: PointerTo[list[PointerTo[bytes]]], optstring: PointerTo[bytes], ret_value: int) -> None: raise NotImplementedError() + def before_exit(self, status: int) -> str: + raise NotImplementedError() + def after_exit(self, status: int) -> None: + raise NotImplementedError() + def before_read(self, fildes: int, buf_ptr: Pointer, nbyte: int) -> str: + raise NotImplementedError() + def after_read(self, fildes: int, buf_ptr: Pointer, nbyte: int, + ret_value: int, errno: str = None, buf: PointerTo[bytes] = None) -> None: + raise NotImplementedError() + def before_pread(self, fildes: int, buf_ptr: Pointer, nbyte: int, offset: int) -> str: + raise NotImplementedError() + def after_pread(self, fildes: int, buf_ptr: Pointer, nbyte: int, offset: int, + ret_value: int, errno: str = None, buf: PointerTo[bytes] = None) -> None: + raise NotImplementedError() + def before_write(self, fildes: int, buf: PointerTo[bytes], nbyte: int) -> str: + raise NotImplementedError() + def after_write(self, fildes: int, buf: PointerTo[bytes], nbyte: int, + ret_value: int, errno: str = None) -> None: + raise NotImplementedError() + def before_pwrite(self, fildes: int, buf: PointerTo[bytes], nbyte: int, offste: int) -> str: + raise NotImplementedError() + def after_pwrite(self, fildes: int, buf: PointerTo[bytes], nbyte: int, offste: int, + ret_value: int, errno: str = None) -> None: + raise NotImplementedError() def before_close(self, fildes: int) -> str: raise NotImplementedError() def after_close(self, fildes: int, @@ -317,6 +341,81 @@ class Handler(StreamRequestHandler): def after_ftruncate(self, fildes: int, length: int, ret_value: int, errno: str = None) -> None: raise NotImplementedError() + def before_fork(self) -> str: + raise NotImplementedError() + def after_fork(self, + ret_value: int, errno: str = None) -> None: + raise NotImplementedError() + def before_wait(self, stat_loc: Pointer) -> str: + raise NotImplementedError() + def after_wait(self, stat_loc: Pointer, + ret_value: int, errno: str = None, stat: int = None) -> None: + raise NotImplementedError() + def before_waitpid(self, pid: int, stat_loc: Pointer, options: Flags) -> str: + raise NotImplementedError() + def after_waitpid(self, pid: int, stat_loc: Pointer, options: Flags, + ret_value: int, errno: str = None, stat: int = None) -> None: + raise NotImplementedError() + def before_execl(self, pathname: PointerTo[bytes], *args: list[PointerTo[bytes]]) -> str: + raise NotImplementedError() + def after_execl(self, pathname: PointerTo[bytes], *args: list[PointerTo[bytes]], + ret_value: int, errno: str = None) -> None: + raise NotImplementedError() + def before_execlp(self, file: PointerTo[bytes], *args: list[PointerTo[bytes]]) -> str: + raise NotImplementedError() + def after_execlp(self, file: PointerTo[bytes], *args: list[PointerTo[bytes]], + ret_value: int, errno: str = None) -> None: + raise NotImplementedError() + def before_execle(self, pathname: PointerTo[bytes], *args: list[PointerTo[bytes]], envp: PointerTo[list[PointerTo[bytes]]]) -> str: + raise NotImplementedError() + def after_execle(self, pathname: PointerTo[bytes], *args: list[PointerTo[bytes]], envp: PointerTo[list[PointerTo[bytes]]], + ret_value: int, errno: str = None) -> None: + raise NotImplementedError() + def before_execv(self, pathname: PointerTo[bytes], argv: PointerTo[list[PointerTo[bytes]]]) -> str: + raise NotImplementedError() + def after_execv(self, pathname: PointerTo[bytes], argv: PointerTo[list[PointerTo[bytes]]], + ret_value: int, errno: str = None) -> None: + raise NotImplementedError() + def before_execvp(self, file: PointerTo[bytes], argv: PointerTo[list[PointerTo[bytes]]]) -> str: + raise NotImplementedError() + def after_execvp(self, file: PointerTo[bytes], argv: PointerTo[list[PointerTo[bytes]]], + ret_value: int, errno: str = None) -> None: + raise NotImplementedError() + def before_execvpe(self, file: PointerTo[bytes], argv: PointerTo[list[PointerTo[bytes]]], envp: PointerTo[list[PointerTo[bytes]]]) -> str: + raise NotImplementedError() + def after_execvpe(self, file: PointerTo[bytes], argv: PointerTo[list[PointerTo[bytes]]], envp: PointerTo[list[PointerTo[bytes]]], + ret_value: int, errno: str = None) -> None: + raise NotImplementedError() + def before_execve(self, pathname: PointerTo[bytes], argv: PointerTo[list[PointerTo[bytes]]], envp: PointerTo[list[PointerTo[bytes]]]) -> str: + raise NotImplementedError() + def after_execve(self, pathname: PointerTo[bytes], argv: PointerTo[list[PointerTo[bytes]]], envp: PointerTo[list[PointerTo[bytes]]], + ret_value: int, errno: str = None) -> None: + raise NotImplementedError() + def before_fexecve(self, fd: int, argv: PointerTo[list[PointerTo[bytes]]], envp: PointerTo[list[PointerTo[bytes]]]) -> str: + raise NotImplementedError() + def after_fexecve(self, fd: int, argv: PointerTo[list[PointerTo[bytes]]], envp: PointerTo[list[PointerTo[bytes]]], + ret_value: int, errno: str = None) -> None: + raise NotImplementedError() + def before_pipe(self, fildes: PointerTo[list[int]]) -> str: + raise NotImplementedError() + def after_pipe(self, fildes: PointerTo[list[int]], + ret_value: int, errno: str = None) -> None: + raise NotImplementedError() + def before_dup(self, oldfd: int) -> str: + raise NotImplementedError() + def after_dup(self, oldfd: int, + ret_value: int, errno: str = None) -> None: + raise NotImplementedError() + def before_dup2(self, oldfd: int, newfd: int) -> str: + raise NotImplementedError() + def after_dup2(self, oldfd: int, newfd: int, + ret_value: int, errno: str = None) -> None: + raise NotImplementedError() + def before_dup3(self, oldfd: int, newfd: int, flags: Flags) -> str: + raise NotImplementedError() + def after_dup3(self, oldfd: int, newfd: int, flags: Flags, + ret_value: int, errno: str = None) -> None: + raise NotImplementedError() def intercept(socket: str, handler: type[Handler]) -> None: diff --git a/proj/server/src/intercept/standard.py b/proj/server/src/intercept/standard.py index 7cb3a8a..769f1ad 100644 --- a/proj/server/src/intercept/standard.py +++ b/proj/server/src/intercept/standard.py @@ -9,6 +9,10 @@ FUNCTION_ERRORS: dict[str, list[str]] = { 'calloc': ['ENOMEM'], 'realloc': ['ENOMEM'], 'reallocarray': ['ENOMEM'], + 'read': [], + 'pread': [], + 'write': [], + 'pwrite': [], 'close': ['EBADF'], # EINTR, EIO 'sigaction': ['EINVAL'], 'sem_init': ['EINVAL', 'ENOSYS'], @@ -26,6 +30,21 @@ FUNCTION_ERRORS: dict[str, list[str]] = { 'mmap': ['EACCES', 'EBADF', 'EINVAL', 'EMFILE', 'ENODEV', 'ENOMEM', 'ENOTSUP', 'ENXIO', 'EOVERFLOW'], # EAGAIN 'munmap': ['EINVAL'], 'ftruncate': ['EINTR', 'EINVAL', 'EFBIG', 'EIO', 'EBADF'], + 'fork': ['EAGAIN', 'ENOMEM', 'ENOSYS'], + 'wait': ['ECHILD', 'EINTR'], + 'waitpid': ['ECHILD', 'EINTR', 'EINVAL'], + 'execl': ['ECHILD', 'EINTR'], + 'execlp': ['ECHILD', 'EINTR'], + 'execle': ['ECHILD', 'EINTR'], + 'execv': ['ECHILD', 'EINTR'], + 'execvp': ['ECHILD', 'EINTR'], + 'execvpe': ['ECHILD', 'EINTR'], + 'execve': ['ECHILD', 'EINTR'], + 'fexecve': ['ECHILD', 'EINTR'], + 'pipe': ['EMFILE', 'ENFILE'], + 'dup': ['EBADF', 'EMFILE'], # ENOMEM + 'dup2': ['EBADF', 'EBUSY', 'EINTR', 'EMFILE'], # ENOMEM + 'dup3': ['EBADF', 'EBUSY', 'EINTR', 'EINVAL', 'EMFILE'], # ENOMEM } SKIP_ERRORS: list[str] = ['EINTR']