#define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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 #define func_def(ret, name) static ret (*__real_ ## name) #else #define sym(name) __wrap_ ## name #define func_def(ret, name) extern ret __real_ ## name #endif func_def(void *, malloc)(size_t); func_def(void *, calloc)(size_t, size_t); func_def(void *, realloc)(void *, size_t); func_def(void *, reallocarray)(void *, size_t, size_t); func_def(void, free)(void *); func_def(int, getopt)(int, char *const [], const char *); func_def(void, exit)(int); func_def(ssize_t, read)(int, void *, size_t); func_def(ssize_t, pread)(int, void *, size_t, off_t); func_def(ssize_t, write)(int, const void *, size_t); func_def(ssize_t, pwrite)(int, const void *, size_t, off_t); func_def(int, close)(int); func_def(int, sigaction)(int, const struct sigaction *, struct sigaction *); func_def(int, sem_init)(sem_t *, int, unsigned int); func_def(sem_t *, sem_open)(const char *, int, ...); func_def(int, sem_post)(sem_t *); func_def(int, sem_wait)(sem_t *); func_def(int, sem_trywait)(sem_t *); func_def(int, sem_timedwait)(sem_t *restrict, const struct timespec *restrict); func_def(int, sem_getvalue)(sem_t *restrict, int *restrict); func_def(int, sem_close)(sem_t *); func_def(int, sem_unlink)(const char *); func_def(int, sem_destroy)(sem_t *); func_def(int, shm_open)(const char *, int, mode_t); func_def(int, shm_unlink)(const char *); func_def(void *, mmap)(void *, size_t, int, int, int, off_t); func_def(int, munmap)(void *, size_t); func_def(int, ftruncate)(int, off_t); func_def(pid_t, fork)(void); func_def(pid_t, wait)(int *); func_def(pid_t, waitpid)(pid_t, int *, int); func_def(int, execl)(const char *, const char *, ...); func_def(int, execlp)(const char *, const char *, ...); func_def(int, execle)(const char *, const char *, ...); func_def(int, execv)(const char *, char *const[]); func_def(int, execvp)(const char *, char *const[]); func_def(int, execvpe)(const char *, char *const[], char *const[]); func_def(int, execve)(const char *, char *const[], char *const[]); func_def(int, fexecve)(int, char *const[], char *const[]); func_def(int, pipe)(int[2]); func_def(int, dup)(int); func_def(int, dup2)(int, int); func_def(int, dup3)(int, int, int); func_def(int, socket)(int, int, int); func_def(int, bind)(int, const struct sockaddr *, socklen_t); func_def(int, listen)(int, int); func_def(int, accept)(int, struct sockaddr *, socklen_t *); func_def(int, connect)(int, const struct sockaddr *, socklen_t); func_def(int, getaddrinfo)(const char *, const char *, const struct addrinfo *, struct addrinfo **); func_def(void, freeaddrinfo)(struct addrinfo *); func_def(ssize_t, send)(int, const void *, size_t, int); func_def(ssize_t, sendto)(int, const void *, size_t, int, const struct sockaddr *, socklen_t); func_def(ssize_t, sendmsg)(int, const struct msghdr *, int); func_def(ssize_t, recv)(int, void *, size_t, int); func_def(ssize_t, recvfrom)(int, void *, size_t, int, struct sockaddr *, socklen_t *); func_def(ssize_t, recvmsg)(int, struct msghdr *, int); #define func_idx_malloc 0 #define func_idx_calloc 1 #define func_idx_realloc 2 #define func_idx_reallocarray 3 #define func_idx_free 4 #define func_idx_getopt 5 #define func_idx_exit 6 #define func_idx_read 7 #define func_idx_pread 8 #define func_idx_write 9 #define func_idx_pwrite 10 #define func_idx_close 11 #define func_idx_sigaction 12 #define func_idx_sem_init 13 #define func_idx_sem_open 14 #define func_idx_sem_post 15 #define func_idx_sem_wait 16 #define func_idx_sem_trywait 17 #define func_idx_sem_timedwait 18 #define func_idx_sem_getvalue 19 #define func_idx_sem_close 20 #define func_idx_sem_unlink 21 #define func_idx_sem_destroy 22 #define func_idx_shm_open 23 #define func_idx_shm_unlink 24 #define func_idx_mmap 25 #define func_idx_munmap 26 #define func_idx_ftruncate 27 #define func_idx_fork 28 #define func_idx_wait 29 #define func_idx_waitpid 30 #define func_idx_execl 31 #define func_idx_execlp 32 #define func_idx_execle 33 #define func_idx_execv 34 #define func_idx_execvp 35 #define func_idx_execvpe 36 #define func_idx_execve 37 #define func_idx_fexecve 38 #define func_idx_pipe 39 #define func_idx_dup 40 #define func_idx_dup2 41 #define func_idx_dup3 42 #define func_idx_socket 43 #define func_idx_bind 44 #define func_idx_listen 45 #define func_idx_accept 46 #define func_idx_connect 47 #define func_idx_getaddrinfo 48 #define func_idx_freeaddrinfo 49 #define func_idx_send 50 #define func_idx_sendto 51 #define func_idx_sendmsg 52 #define func_idx_recv 53 #define func_idx_recvfrom 54 #define func_idx_recvmsg 55 #define FUNCTIONS \ X(malloc) \ X(calloc) \ X(realloc) \ X(reallocarray) \ X(free) \ X(getopt) \ X(exit) \ X(read) \ X(pread) \ X(write) \ X(pwrite) \ X(close) \ X(sigaction) \ X(sem_init) \ X(sem_open) \ X(sem_post) \ X(sem_wait) \ X(sem_trywait) \ X(sem_timedwait) \ X(sem_getvalue) \ X(sem_close) \ X(sem_unlink) \ X(sem_destroy) \ X(shm_open) \ X(shm_unlink) \ X(mmap) \ X(munmap) \ X(ftruncate) \ X(fork) \ X(wait) \ X(waitpid) \ X(execl) \ X(execlp) \ X(execle) \ X(execv) \ X(execvp) \ X(execvpe) \ X(execve) \ X(fexecve) \ X(pipe) \ X(dup) \ X(dup2) \ X(dup3) \ X(socket) \ X(bind) \ X(listen) \ X(accept) \ X(connect) \ X(getaddrinfo) \ X(freeaddrinfo) \ X(send) \ X(sendto) \ X(sendmsg) \ X(recv) \ X(recvfrom) \ X(recvmsg) #define case_const(name) case name: return #name #define flag_str(flags, name, buf) if (flags & name) strcat(buf, #name "|") #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) { \ char *end_ptr = NULL; \ long val = strtol(msg_buf + 7, &end_ptr, 0); \ if (end_ptr != NULL && end_ptr[0] == 0 && end_ptr != msg_buf + 7) { \ var_1 = (type_1)val; \ } else { \ fprintf(stderr, "intercept: %s: invalid args in modify command: '%s'\n", #name, msg_buf + 7); \ } } #define if_modify_int_int(name, type_1, var_1, type_2, var_2) if (strncmp(msg_buf, "modify ", 7) == 0) { \ char *end_ptr_1 = NULL, *end_ptr_2 = NULL; \ long val_1 = strtol(msg_buf + 7, &end_ptr_1, 0); \ long val_2 = 0; \ if (end_ptr_1 != NULL) val_2 = strtol(end_ptr_1 + 1, &end_ptr_2, 0); \ if (end_ptr_1 != NULL && end_ptr_1[0] == ',' && end_ptr_1 != msg_buf + 7 && \ end_ptr_2 != NULL && end_ptr_2[0] == 0 && end_ptr_2 != end_ptr_1 + 1) \ { \ var_1 = (type_1)val_1; \ var_2 = (type_2)val_2; \ } else { \ fprintf(stderr, "intercept: %s: invalid args in modify command: '%s'\n", #name, msg_buf + 7); \ } } #define if_modify_int_int_int(name, type_1, var_1, type_2, var_2, type_3, var_3) if (strncmp(msg_buf, "modify ", 7) == 0) { \ char *end_ptr_1 = NULL, *end_ptr_2 = NULL, *end_ptr_3; \ long val_1 = strtol(msg_buf + 7, &end_ptr_1, 0); \ long val_2 = 0, val_3 = 0; \ if (end_ptr_1 != NULL) val_2 = strtol(end_ptr_1 + 1, &end_ptr_2, 0); \ if (end_ptr_2 != NULL) val_3 = strtol(end_ptr_2 + 1, &end_ptr_3, 0); \ if (end_ptr_1 != NULL && end_ptr_1[0] == ',' && end_ptr_1 != msg_buf + 7 && \ end_ptr_2 != NULL && end_ptr_2[0] == ',' && end_ptr_2 != end_ptr_1 + 1 && \ end_ptr_3 != NULL && end_ptr_3[0] == 0 && end_ptr_3 != end_ptr_2 + 1) \ { \ var_1 = (type_1)val_1; \ var_2 = (type_2)val_2; \ var_3 = (type_3)val_3; \ } else { \ 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_int(name) if (strncmp(msg_buf, "return ", 7) == 0) { \ char *end_ptr = NULL; \ long val = strtol(msg_buf + 7, &end_ptr, 0); \ if (end_ptr != NULL && end_ptr[0] == 0 && end_ptr != msg_buf + 7) { \ msg("return %i", val); \ return val; \ } else { \ fprintf(stderr, "intercept: %s: invalid args in return command: '%s'\n", #name, msg_buf + 7); \ } } #define if_return_int_errno(name) if (strncmp(msg_buf, "return ", 7) == 0) { \ char *end_ptr = NULL; \ long val = strtol(msg_buf + 7, &end_ptr, 0); \ if (end_ptr != NULL && end_ptr[0] == 0 && end_ptr != msg_buf + 7) { \ msg("return %i; errno %s", val, strerrorname_np(errno)); \ return val; \ } else { \ fprintf(stderr, "intercept: %s: invalid args in return command: '%s'\n", #name, msg_buf + 7); \ } } #define if_return_int_errno_int(name, type_1, var_1, name_1) if (strncmp(msg_buf, "return ", 7) == 0) { \ char *end_ptr_1 = NULL, *end_ptr_2 = NULL; \ long val_1 = strtol(msg_buf + 7, &end_ptr_1, 0); \ long val_2 = 0; \ if (end_ptr_1 != NULL) val_2 = strtol(end_ptr_1 + 1, &end_ptr_2, 0); \ if (end_ptr_1 != NULL && end_ptr_1[0] == ',' && end_ptr_1 != msg_buf + 7 && \ end_ptr_2 != NULL && end_ptr_2[0] == 0 && end_ptr_2 != end_ptr_1 + 1) \ { \ var_1 = (type_1)val_2; \ msg("return %i; errno %s; %s=%i", val_1, strerrorname_np(errno), name_1, var_1); \ return val_1; \ } else { \ fprintf(stderr, "intercept: %s: invalid args in return command: '%s'\n", #name, msg_buf + 7); \ } } #define if_return_ptr_errno(name) if (strncmp(msg_buf, "return ", 7) == 0) { \ char *end_ptr = NULL; \ long val = strtol(msg_buf + 7, &end_ptr, 0); \ if (end_ptr != NULL && end_ptr[0] == 0 && end_ptr != msg_buf + 7) { \ msg("return %p; errno %s", val, strerrorname_np(errno)); \ return (void *)val; \ } else { \ fprintf(stderr, "intercept: %s: invalid args in return command: '%s'\n", #name, msg_buf + 7); \ } } #define if_error(err) if (strcmp(msg_buf + 5, #err) == 0) { errno = err; } static void 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 const char *getdomainstr(int domain) { switch (domain) { case_const(AF_UNSPEC); case_const(AF_UNIX); case_const(AF_INET); case_const(AF_INET6); default: return "?"; } } static const char *getsocktype(int type) { switch (type) { case_const(SOCK_STREAM); case_const(SOCK_DGRAM); case_const(SOCK_RAW); case_const(SOCK_RDM); case_const(SOCK_SEQPACKET); case_const(SOCK_DCCP); case_const(SOCK_PACKET); default: return "?"; } } static char *strtostr(char *ptr, char **end_ptr, char *buf) { if (ptr[0] != '"') return NULL; int i = 0, esc = 0, hex = 0; for (*end_ptr = ptr + 1; *end_ptr[0] != 0; (*end_ptr)++) { char ch = *end_ptr[0]; if (esc) { if (esc == 2) { if (ch >= '0' && ch <= '9') { hex = (ch - '0') << 4; } else if (ch >= 'A' && ch <= 'F') { hex = (ch - 'A' + 10) << 4; } else if (ch >= 'a' && ch <= 'f') { hex = (ch - 'a' + 10) << 4; } else { return NULL; } esc = 3; continue; } else if (esc == 3) { if (ch >= '0' && ch <= '9') { hex |= (ch - '0'); } else if (ch >= 'A' && ch <= 'F') { hex |= (ch - 'A' + 10); } else if (ch >= 'a' && ch <= 'f') { hex |= (ch - 'a' + 10); } else { return NULL; } buf[i++] = (char)hex; esc = 0; continue; } switch (ch) { case 'a': ch = '\a'; break; case 'b': ch = '\b'; break; case 't': ch = '\t'; break; case 'n': ch = '\n'; break; case 'v': ch = '\v'; break; case 'f': ch = '\f'; break; case 'r': ch = '\r'; break; case '0': ch = 0; break; case 'x': esc = 2; continue; case '"': case '\\': break; default: return NULL; } buf[i++] = ch; esc = 0; } else if (ch == '\\') { esc = 1; } else if (ch == '"') { (*end_ptr)++; return buf; } else { buf[i++] = ch; } } return NULL; } static int mode = 0; static int intercept = 0; static uint8_t func_flags[256]; static size_t msg_bytes(char *buf, size_t maxlen, size_t len, const char *str, int flags) { size_t offset = flags & 1 ? snprintf(buf, maxlen, "\"") : snprintf(buf, maxlen, "%p:\"", str); for (int i = 0; i < len && offset <= maxlen - 2; i++) { char ch = str[i]; if (ch == '\\' || ch == '"') { buf[offset++] = '\\'; buf[offset++] = ch; } else if (ch == '\t') { buf[offset++] = '\\'; buf[offset++] = 't'; } else if (ch == '\n') { buf[offset++] = '\\'; buf[offset++] = 'n'; } else if (ch == '\r') { buf[offset++] = '\\'; buf[offset++] = 'r'; } else if ((ch >= 0 && ch < 0x20) || ch == 0x7F) { offset += snprintf(buf + offset, maxlen - offset, "\\x%02x", ch); } else { buf[offset++] = ch; } } if (offset <= maxlen - 2) { buf[offset++] = '"'; buf[offset] = 0; } return offset; } static size_t msg_str(char *buf, size_t maxlen, const char *str, int flags) { return msg_bytes(buf, maxlen, strlen(str), str, flags); } 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++) { if (i > 0) { buf[offset++] = ','; buf[offset++] = ' '; } offset += msg_str(buf + offset, maxlen - offset, array[i], 0); } if (offset <= maxlen - 2) { buf[offset++] = ']'; buf[offset] = 0; } return offset; } static void msg(const char *fmt, ...) { if (!intercept || mode == -1) return; char buf[8192], sub_fmt[16]; int sub_fmt_p = 0; va_list args; va_start(args, fmt); struct timespec spec; clock_gettime(CLOCK_REALTIME, &spec); size_t offset = snprintf(buf, sizeof(buf), "%li.%09li %i ", spec.tv_sec, spec.tv_nsec, getpid()); for (char ch, state = 0; (ch = *fmt) != 0 && offset < sizeof(buf); fmt++) { if (state == '%') { if (ch == '%') { buf[offset++] = ch; state = 0; continue; } else if (ch == 'e') { state = 'e'; continue; } else if (ch == 'q') { state = 'q'; continue; } else if (ch == 'a') { state = 'a'; continue; } else { sub_fmt_p = 0; state = '_'; sub_fmt[sub_fmt_p++] = '%'; sub_fmt[sub_fmt_p] = 0; } } if (state == '_') { sub_fmt[sub_fmt_p++] = ch; sub_fmt[sub_fmt_p] = 0; if (ch == 's' || ch == 'i' || ch == 'd' || ch == 'o' || ch == 'u' || ch == 'x' || ch == 'X' || ch == 'f' || ch == 'p') { state = 0; offset += snprintf(buf + offset, sizeof(buf) - offset, sub_fmt, va_arg(args, long int)); } } else if (state == 'e') { if (ch == 's') { // escaped string offset += msg_str(buf + offset, sizeof(buf) - offset, va_arg(args, const char *), 0); } 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 *), 0); } state = 0; } else if (state == 'q') { if (ch == 'a') { // address, struct sockaddr const int len = va_arg(args, int); const struct sockaddr *addr = va_arg(args, struct sockaddr *); if (addr->sa_family == AF_UNIX) { // 0x0:{sa_family: 1:AF_UNIX, sun_path: "/path/"} const struct sockaddr_un *un = (const struct sockaddr_un *)addr; offset += snprintf(buf + offset, sizeof(buf) - offset, "%p:{sa_family: %i:AF_UNIX, sun_Path: ", (void *)un, AF_UNIX); offset += msg_str(buf + offset, sizeof(buf) - offset, un->sun_path, 1); offset += snprintf(buf + offset, sizeof(buf) - offset, "}"); } else if (addr->sa_family == AF_INET && len == sizeof(struct sockaddr_in)) { // 0x0:{sa_family: 2:AF_INET, sin_addr: "192.168.0.1", sin_port: 80} const struct sockaddr_in *in = (const struct sockaddr_in *)addr; char addr_buf[INET_ADDRSTRLEN]; offset += snprintf(buf + offset, sizeof(buf) - offset, "%p:{sa_family: %i:AF_INET, sin_addr: \"%s\", sin_port: %i}", (void *)in, AF_INET, inet_ntop(AF_INET, &in->sin_addr, addr_buf, sizeof(addr_buf)), ntohs(in->sin_port)); } else if (addr->sa_family == AF_INET6 && len == sizeof(struct sockaddr_in6)) { // 0x0:{sa_family: 10:AF_INET6, sin6_addr: "::1", sin6_port: 80, sin6_scope_id: 0} const struct sockaddr_in6 *in6 = (const struct sockaddr_in6 *)addr; char addr_buf[INET6_ADDRSTRLEN]; offset += snprintf(buf + offset, sizeof(buf) - offset, "%p:{sa_family: %i:AF_INET6, sin6_addr: \"%s\", sin6_port: %i, sin6_scope_id: %i}", (void *)in6, AF_INET6, inet_ntop(AF_INET6, &in6->sin6_addr, addr_buf, sizeof(addr_buf)), ntohs(in6->sin6_port), in6->sin6_scope_id); } else { // 0x0:{sa_family: 7:?, sa_data: "\x01\x02\x03\x04"} offset += snprintf(buf + offset, sizeof(buf) - offset, "%p:{sa_family: %i:%s, sa_data: ", (void *)addr, addr->sa_family, getdomainstr(addr->sa_family)); offset += msg_bytes(buf + offset, sizeof(buf) - offset, len - sizeof(addr->sa_family), addr->sa_data, 1); offset += snprintf(buf + offset, sizeof(buf) - offset, "}"); } } else if (ch == 'm') { // struct msghdr // TODO format struct msghdr const struct msghdr *msg = va_arg(args, struct msghdr *); offset += snprintf(buf + offset, sizeof(buf) - offset, "%p:{}", (void *)msg); } else if (ch == 't') { // struct timespec const struct timespec *tv = va_arg(args, struct timespec *); offset += snprintf(buf + offset, sizeof(buf) - offset, "%p:{tv_sec: %li, tv_nsec: %li}", (void *)tv, tv->tv_sec, tv->tv_nsec); } else if (ch == 'i') { // struct addrinfo // TODO format struct addrinfo const struct addrinfo *ai = va_arg(args, struct addrinfo *); offset += snprintf(buf + offset, sizeof(buf) - offset, "%p:{}", (void *)ai); } else { // error va_end(args); return; } state = 0; } else if (state == 'a') { if (ch == 's') { // string array 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 va_end(args); return; } state = 0; } else if (ch == '%') { state = '%'; } else { buf[offset++] = ch; } } if (offset <= sizeof(buf) - 2) { buf[offset++] = '\n'; buf[offset] = 0; } const size_t size = offset >= sizeof(buf) ? sizeof(buf) - 1 : offset; ssize_t ret; for (size_t written = 0; written < size; written += ret) { if ((ret = __real_write(intercept, buf, size)) == -1) { if (errno == EINTR) { ret = 0; continue; } va_end(args); return; } } va_end(args); } 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 = __real_read(intercept, buf, size)) == -1) { if (errno == EINTR) { ret = 0; continue; } buf[0] = 0; return; } } buf[num - 1] = 0; } static void fin(void) { if (intercept && mode > 2) __real_close(intercept); if (mode > 0) fprintf(stderr, "intercept: stopped\n"); mode = 0, intercept = 0; } static void init(void) { if (mode) return; mode = -1; #ifdef INTERCEPT_PRELOAD #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpedantic" #define X(name) load(name); FUNCTIONS #undef X #pragma GCC diagnostic pop #endif atexit(fin); const char *val = getenv("INTERCEPT"); if (val && strcmp(val, "stdout") == 0) { fprintf(stderr, "intercept: intercepting function/system calls and logging to stdout\n"); intercept = STDOUT_FILENO; mode = 1; } else if (val && strcmp(val, "stderr") == 0) { 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) { if ((intercept = open(val + 5, O_CREAT | O_TRUNC | O_WRONLY, 0644)) == -1) { 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) { if ((intercept = __real_socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { 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; } struct sockaddr_un addr = {.sun_family = AF_UNIX}; strncpy(addr.sun_path, val + 5, sizeof(addr.sun_path)); if (__real_connect(intercept, (struct sockaddr *)&addr, sizeof(addr)) == -1) { 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)); __real_close(intercept); errno = 0; mode = -1; return; } 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) { // TODO socket/tcp mode mode = 5; } else { fprintf(stderr, "intercept: not logging or manipulating function/system calls\n"); } char *fncts = getenv("INTERCEPT_FUNCTIONS"); if (fncts) { memset(func_flags, 0, sizeof(func_flags)); const char *func_names_ordered[] = { #define X(name) #name, FUNCTIONS #undef X }; char *func_names[256] = {fncts, NULL}; const size_t len = strlen(fncts); for (int i = 0, p = 0; i < len; i++) { const char ch = fncts[i]; if (ch == ',' || ch == ';' || ch == ':' || ch == 0) { fncts[i] = 0; func_names[++p] = fncts + i + 1; } } for (int i = 0; func_names[i] != NULL; i++) { const char *name1 = func_names[i]; const int wildcard = name1[strlen(name1) - 1] == '*'; for (int j = 0; j < sizeof(func_names_ordered) / sizeof(char *); j++) { const char *name2 = func_names_ordered[j]; if (strcmp(name1, name2) == 0 || (wildcard && strncmp(name1, name2, strlen(name1) - 1) == 0)) func_flags[j] |= 1; } } } else { memset(func_flags, 1, sizeof(func_flags)); } } void *sym(malloc)(size_t size) { init(); if (!func_flags[func_idx_malloc]) return __real_malloc(size); msg("malloc(%li): %p", size, ret_addr); if (mode >= 4) { char msg_buf[BUFFER_SIZE]; rcv(msg_buf, sizeof(msg_buf)); if_modify_int(malloc, size_t, size) else if_return_ptr_errno(malloc) else if_fail_ptr_errno(malloc) else if_invalid(malloc) } void *ret = __real_malloc(size); msg("return %p; errno %s", ret, strerrorname_np(errno)); return ret; } void *sym(calloc)(size_t nmemb, size_t size) { init(); if (!func_flags[func_idx_calloc]) return __real_calloc(nmemb, size); msg("calloc(%li, %li): %p", nmemb, size, ret_addr); if (mode >= 4) { char msg_buf[BUFFER_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_fail_ptr_errno(calloc) else if_invalid(calloc) } void *ret = __real_calloc(nmemb, size); msg("return %p; errno %s", ret, strerrorname_np(errno)); return ret; } void *sym(realloc)(void *ptr, size_t size) { init(); if (!func_flags[func_idx_realloc]) return __real_realloc(ptr, size); msg("realloc(%p, %li): %p", ptr, size, ret_addr); if (mode >= 4) { char msg_buf[BUFFER_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_fail_ptr_errno(realloc) else if_invalid(realloc) } void *ret = __real_realloc(ptr, size); msg("return %p; errno %s", ret, strerrorname_np(errno)); return ret; } void *sym(reallocarray)(void *ptr, size_t nmemb, size_t size) { init(); if (!func_flags[func_idx_reallocarray]) return __real_reallocarray(ptr, nmemb, size); msg("reallocarray(%p, %li): %p", ptr, size, ret_addr); if (mode >= 4) { char msg_buf[BUFFER_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_fail_ptr_errno(reallocarray) else if_invalid(reallocarray) } void *ret = __real_reallocarray(ptr, nmemb, size); msg("return %p; errno %s", ret, strerrorname_np(errno)); return ret; } void sym(free)(void *ptr) { init(); if (!func_flags[func_idx_free]) { __real_free(ptr); return; } msg("free(%p): %p", ptr, ret_addr); if (mode >= 4) { char msg_buf[BUFFER_SIZE]; rcv(msg_buf, sizeof(msg_buf)); if_modify_int(free, void *, ptr) else if_return else if_invalid(free) } __real_free(ptr); msg("return"); } int sym(getopt)(const int argc, char *const argv[], const char *shortopts) { init(); if (!func_flags[func_idx_getopt]) return __real_getopt(argc, argv, shortopts); 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)); if (strncmp(msg_buf, "modify ", 7) == 0) { // modify ,, // TODO getopt modify fprintf(stderr, "intercept: %s: modify command not implemented\n", "getopt"); } else if_return_int(getopt) else if_invalid(getopt) } const int ret = __real_getopt(argc, argv, shortopts); msg("return %i", ret); return ret; } void sym(exit)(int status) { init(); if (!func_flags[func_idx_exit]) __real_exit(status); msg("exit(%i): %p", status, ret_addr); if (mode >= 4) { char msg_buf[BUFFER_SIZE]; rcv(msg_buf, sizeof(msg_buf)); if_modify_int("exit", int, status) else if_invalid(getopt) } __real_exit(status); } ssize_t sym(read)(int fildes, void *buf, size_t nbyte) { init(); if (!func_flags[func_idx_read]) return __real_read(fildes, buf, nbyte); 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(); if (!func_flags[func_idx_pread]) return __real_pread(fildes, buf, nbyte, offset); 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(); if (!func_flags[func_idx_write]) return __real_write(fildes, buf, nbyte); msg("write(%i, %eb, %i): %p", fildes, 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(); if (!func_flags[func_idx_pwrite]) return __real_pwrite(fildes, buf, nbyte, offset); msg("pwrite(%i, %eb, %i, %i): %p", fildes, 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(); if (!func_flags[func_idx_close]) return __real_close(fildes); msg("close(%i): %p", fildes, ret_addr); if (mode >= 4) { char msg_buf[BUFFER_SIZE]; rcv(msg_buf, sizeof(msg_buf)); if_modify_int(close, int, fildes) else if_return_int_errno(close) else if_fail_int_errno(close) else if_invalid(close) } const int ret = __real_close(fildes); msg("return %i; errno %s", ret, strerrorname_np(errno)); return ret; } static const char *getsigstr(int sig) { switch (sig) { case_const(SIGINT); case_const(SIGILL); case_const(SIGABRT); case_const(SIGFPE); case_const(SIGSEGV); case_const(SIGTERM); case_const(SIGHUP); case_const(SIGQUIT); case_const(SIGTRAP); case_const(SIGKILL); case_const(SIGPIPE); case_const(SIGALRM); case_const(SIGSTKFLT); case_const(SIGPWR); case_const(SIGBUS); case_const(SIGSYS); case_const(SIGURG); case_const(SIGSTOP); case_const(SIGTSTP); case_const(SIGCONT); case_const(SIGCHLD); case_const(SIGTTIN); case_const(SIGTTOU); case_const(SIGPOLL); case_const(SIGXFSZ); case_const(SIGXCPU); case_const(SIGVTALRM); case_const(SIGPROF); case_const(SIGUSR1); case_const(SIGUSR2); case_const(SIGWINCH); default: return "?"; } } int sym(sigaction)(int sig, const struct sigaction *restrict act, struct sigaction *restrict oact) { init(); if (!func_flags[func_idx_sigaction]) return __real_sigaction(sig, act, oact); const char *sigstr = getsigstr(sig); if (act != NULL) { char *name = "sa_handler"; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpedantic" void *ptr = (void *)act->sa_handler; if (act->sa_flags & SA_SIGINFO) { name = "sa_sigaction"; ptr = (void *)act->sa_sigaction; } #pragma GCC diagnostic pop char flgstr[64] = "|"; flag_str(act->sa_flags, SA_NOCLDSTOP, flgstr); flag_str(act->sa_flags, SA_NOCLDWAIT, flgstr); flag_str(act->sa_flags, SA_SIGINFO, flgstr); if (act->sa_flags & ~(SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO)) strcat(flgstr, "?|"); char maskstr[512] = ""; for (int i = 0; i < 64; i++) { if (sigismember(&act->sa_mask, i) != 1) continue; if (maskstr[0] != 0) strcat(maskstr, ","); strcat(maskstr, getsigstr(i)); } msg("sigaction(%i:%s, %p:{sa_flags: 0x%x:%s, %s: %p, sa_mask: [%s]}, %p): %p", sig, sigstr, act, act->sa_flags, flgstr, name, ptr, maskstr, oact, ret_addr); } else { msg("sigaction(%i:%s, %p:{}, %p): %p", sig, sigstr, act, oact, ret_addr); } if (mode >= 4) { char msg_buf[BUFFER_SIZE]; rcv(msg_buf, sizeof(msg_buf)); if (strncmp(msg_buf, "modify ", 7) == 0) { // TODO sigaction modify fprintf(stderr, "intercept: %s: modify command not implemented\n", "sigaction"); } else if (strncmp(msg_buf, "return ", 7) == 0) { // TODO sigaction return fprintf(stderr, "intercept: %s: return command not implemented\n", "sigaction"); } else if_fail_int_errno(sigaction) else if_invalid(sigaction) } const int ret = __real_sigaction(sig, act, oact); if (oact != NULL) { char *name = "sa_handler"; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpedantic" void *ptr = (void *)oact->sa_handler; if (oact->sa_flags & SA_SIGINFO) { name = "sa_sigaction"; ptr = (void *)oact->sa_sigaction; } #pragma GCC diagnostic pop char flgstr[64] = "|"; flag_str(oact->sa_flags, SA_NOCLDSTOP, flgstr); flag_str(oact->sa_flags, SA_NOCLDWAIT, flgstr); flag_str(oact->sa_flags, SA_SIGINFO, flgstr); if (oact->sa_flags & ~(SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO)) strcat(flgstr, "?|"); char maskstr[512] = ""; for (int i = 0; i < 64; i++) { if (sigismember(&oact->sa_mask, i) != 1) continue; if (maskstr[0] != 0) strcat(maskstr, ","); strcat(maskstr, getsigstr(i)); } msg("return %i; errno %s; oact={sa_flags: 0x%x:%s, %s: %p, sa-mask: [%s]}", ret, strerrorname_np(errno), oact->sa_flags, flgstr, name, ptr, maskstr); } else { msg("return %i; errno %s", ret, strerrorname_np(errno)); } return ret; } int sym(sem_init)(sem_t *sem, int pshared, unsigned int value) { init(); if (!func_flags[func_idx_sem_init]) return __real_sem_init(sem, pshared, value); msg("sem_init(%p, %i, %u): %p", sem, pshared, value, ret_addr); if (mode >= 4) { char msg_buf[BUFFER_SIZE]; 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_fail_int_errno(sem_init) else if_invalid(sem_init) } const int ret = __real_sem_init(sem, pshared, value); msg("return %i; errno %s", ret, strerrorname_np(errno)); return ret; } sem_t *sym(sem_open)(const char *name, int oflag, ...) { init(); char ostr[32] = "|"; flag_str(oflag, O_CREAT, ostr); flag_str(oflag, O_EXCL, ostr); if (oflag & ~(O_CREAT | O_EXCL)) strcat(ostr, "?|"); mode_t mode_arg = 0; unsigned int value = 0; if (oflag & O_CREAT) { va_list args; va_start(args, oflag); mode_arg = va_arg(args, mode_t); value = va_arg(args, unsigned int); va_end(args); if (!func_flags[func_idx_sem_open]) return __real_sem_open(name, oflag, mode_arg, value); msg("sem_open(%es, 0%o:%s, 0%03o, %u): %p", name, oflag, ostr, mode_arg, value, ret_addr); } else { if (!func_flags[func_idx_sem_open]) return __real_sem_open(name, oflag); msg("sem_open(%es, 0%o:|%s): %p", name, oflag, ostr, ret_addr); } char overwrite[BUFFER_SIZE]; if (mode >= 4) { char msg_buf[BUFFER_SIZE]; rcv(msg_buf, sizeof(msg_buf)); if (strncmp(msg_buf, "modify ", 7) == 0) { // modify , // modify ,,, char *val_1 = NULL, *end_ptr_1 = NULL, *end_ptr_2 = NULL, *end_ptr_3 = NULL, *end_ptr_4 = NULL; long val_2 = 0, val_3 = 0, val_4 = 0; if (msg_buf[7] == '"') { // modify "",... val_1 = strtostr(msg_buf + 7, &end_ptr_1, overwrite); if (val_1 == NULL) end_ptr_1 = NULL; } else { // modify ,... val_1 = (char *)strtol(msg_buf + 7, &end_ptr_1, 0); } if (end_ptr_1 != NULL && end_ptr_1[0] != 0) { if (end_ptr_1[1] == '|') { val_2 = 0; end_ptr_2 = end_ptr_1 + 1; if (strncmp(end_ptr_2, "O_CREAT|", 8) == 0) { val_2 |= O_CREAT; end_ptr_2 += 8; } if (strncmp(end_ptr_2, "O_EXCL|", 7) == 0) { val_2 |= O_EXCL; end_ptr_2 += 7; } } else { val_2 = strtol(end_ptr_1 + 1, &end_ptr_2, 0); } } if (end_ptr_2 != NULL && end_ptr_2[0] != 0) val_3 = strtol(end_ptr_2 + 1, &end_ptr_3, 0); if (end_ptr_3 != NULL && end_ptr_3[0] != 0) val_4 = strtol(end_ptr_3 + 1, &end_ptr_4, 0); if (end_ptr_1 != NULL && end_ptr_1[0] == ',' && end_ptr_1 != msg_buf + 7 && end_ptr_2 != NULL && (end_ptr_2[0] == 0 || end_ptr_2[0] == ',') && end_ptr_2 != end_ptr_1 + 1 && (end_ptr_2[0] == 0 || (end_ptr_3 != NULL && end_ptr_3[0] == ',' && end_ptr_3 != end_ptr_2 + 1 && end_ptr_4 != NULL && end_ptr_4[0] == 0 && end_ptr_4 != end_ptr_3 + 1))) { name = val_1; oflag = (int)val_2; if (end_ptr_2[0] != 0) { mode_arg = val_3; value = val_4; } } else { 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_fail_ptr_errno(sem_open) else if_invalid(sem_open) } sem_t *ret; if (oflag & O_CREAT) { ret = __real_sem_open(name, oflag, mode_arg, value); } else { ret = __real_sem_open(name, oflag); } msg("return %p; errno %s", ret, strerrorname_np(errno)); return ret; } int sym(sem_post)(sem_t *sem) { init(); if (!func_flags[func_idx_sem_post]) return __real_sem_post(sem); msg("sem_post(%p): %p", sem, ret_addr); if (mode >= 4) { char msg_buf[BUFFER_SIZE]; rcv(msg_buf, sizeof(msg_buf)); if_modify_int(sem_post, sem_t *, sem) else if_return_int_errno(sem_post) else if_fail_int_errno(sem_post) else if_invalid(sem_post) } const int ret = __real_sem_post(sem); msg("return %i; errno %s", ret, strerrorname_np(errno)); return ret; } int sym(sem_wait)(sem_t *sem) { init(); if (!func_flags[func_idx_sem_wait]) return __real_sem_wait(sem); msg("sem_wait(%p): %p", sem, ret_addr); if (mode >= 4) { char msg_buf[BUFFER_SIZE]; rcv(msg_buf, sizeof(msg_buf)); if_modify_int(sem_wait, sem_t *, sem) else if_return_int_errno(sem_wait) else if_fail_int_errno(sem_wait) else if_invalid(sem_wait) } const int ret = __real_sem_wait(sem); msg("return %i; errno %s", ret, strerrorname_np(errno)); return ret; } int sym(sem_trywait)(sem_t *sem) { init(); if (!func_flags[func_idx_sem_trywait]) return __real_sem_trywait(sem); msg("sem_trywait(%p): %p", sem, ret_addr); if (mode >= 4) { char msg_buf[BUFFER_SIZE]; rcv(msg_buf, sizeof(msg_buf)); if_modify_int(sem_trywait, sem_t *, sem) else if_return_int_errno(sem_trywait) else if_fail_int_errno(sem_trywait) else if_invalid(sem_trywait) } const int ret = __real_sem_trywait(sem); msg("return %i; errno %s", ret, strerrorname_np(errno)); return ret; } int sym(sem_timedwait)(sem_t *restrict sem, const struct timespec *restrict abs_timeout) { init(); if (!func_flags[func_idx_sem_timedwait]) return __real_sem_timedwait(sem, abs_timeout); msg("sem_timedwait(%p, %qt): %p", sem, abs_timeout, ret_addr); struct timespec overwrite; if (mode >= 4) { char msg_buf[BUFFER_SIZE]; rcv(msg_buf, sizeof(msg_buf)); if (strncmp(msg_buf, "modify ", 7) == 0) { // modfiy , // modify ,{,} char *end_ptr_1 = NULL, *end_ptr_2 = NULL, *end_ptr_3 = NULL; long val_1 = strtol(msg_buf + 7, &end_ptr_1, 0); struct timespec *val_2 = 0; if (end_ptr_1 != NULL && end_ptr_1[0] != 0) { if (end_ptr_1[1] == '{') { long sec = 0, nsec = 0; sec = strtol(end_ptr_1 + 2, &end_ptr_2, 0); if (end_ptr_2 != NULL && end_ptr_2[0] == ',') nsec = strtol(end_ptr_2 + 1, &end_ptr_3, 0); overwrite.tv_sec = sec; overwrite.tv_nsec = nsec; if (end_ptr_3 != NULL && end_ptr_3[0] == '}' && end_ptr_3[1] == 0) { val_2 = &overwrite; end_ptr_2 = end_ptr_3 + 1; } } else { val_2 = (void *)strtol(end_ptr_1 + 1, &end_ptr_2, 0); } } if (end_ptr_1 != NULL && end_ptr_1[0] == ',' && end_ptr_1 != msg_buf + 7 && end_ptr_2 != NULL && end_ptr_2[0] == 0 && end_ptr_2 != end_ptr_1 + 1) { 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); } } else if_return_int_errno(sem_timedwait) else if_fail_int_errno(sem_timedwait) else if_invalid(sem_timedwait) } const int ret = __real_sem_timedwait(sem, abs_timeout); msg("return %i; errno %s", ret, strerrorname_np(errno)); return ret; } int sym(sem_getvalue)(sem_t *restrict sem, int *restrict value) { init(); if (!func_flags[func_idx_sem_getvalue]) return __real_sem_getvalue(sem, value); msg("sem_getvalue(%p, %p): %p", sem, value, ret_addr); if (mode >= 4) { char msg_buf[BUFFER_SIZE]; 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_fail_int_errno(sem_getvalue) else if_invalid(sem_getvalue) } const int ret = __real_sem_getvalue(sem, value); if (value != NULL) { msg("return %i; errno %s; value=%i", ret, strerrorname_np(errno), *value); } else { msg("return %i; errno %s", ret, strerrorname_np(errno)); } return ret; } int sym(sem_close)(sem_t *sem) { init(); if (!func_flags[func_idx_sem_close]) return __real_sem_close(sem); msg("sem_close(%p): %p", sem, ret_addr); if (mode >= 4) { char msg_buf[BUFFER_SIZE]; rcv(msg_buf, sizeof(msg_buf)); if_modify_int(sem_close, sem_t *, sem) else if_return_int_errno(sem_close) else if_fail_int_errno(sem_close) else if_invalid(sem_close) } const int ret = __real_sem_close(sem); msg("return %i; errno %s", ret, strerrorname_np(errno)); return ret; } int sym(sem_unlink)(const char *name) { init(); if (!func_flags[func_idx_sem_unlink]) return __real_sem_unlink(name); msg("sem_unlink(%es): %p", name, ret_addr); char overwrite[BUFFER_SIZE]; if (mode >= 4) { char msg_buf[BUFFER_SIZE]; rcv(msg_buf, sizeof(msg_buf)); if (strncmp(msg_buf, "modify ", 7) == 0) { char *end_ptr = NULL, *val = NULL; if (msg_buf[7] == '"') { // modify "" val = strtostr(msg_buf + 7, &end_ptr, overwrite); if (val == NULL) end_ptr = NULL; } else { // modify val = (char *)strtol(msg_buf + 7, &end_ptr, 0); } 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); } } else if_return_int_errno(sem_unlink) else if_fail_int_errno(sem_unlink) else if_invalid(sem_unlink) } const int ret = __real_sem_unlink(name); msg("return %p; errno %s", ret, strerrorname_np(errno)); return ret; } int sym(sem_destroy)(sem_t *sem) { init(); if (!func_flags[func_idx_sem_destroy]) return __real_sem_destroy(sem); msg("sem_destroy(%p): %p", sem, ret_addr); if (mode >= 4) { char msg_buf[BUFFER_SIZE]; rcv(msg_buf, sizeof(msg_buf)); if_modify_int(sem_destroy, sem_t *, sem) else if_return_int_errno(sem_destroy) else if_fail_int_errno(sem_destroy) else if_invalid(sem_destroy) } const int ret = __real_sem_destroy(sem); msg("return %p; errno %s", ret, strerrorname_np(errno)); return ret; } int sym(shm_open)(const char *name, int oflag, mode_t mode_arg) { init(); if (!func_flags[func_idx_shm_open]) return __real_shm_open(name, oflag, mode); char ostr[64] = "|"; flag_str(oflag, O_RDONLY, ostr); flag_str(oflag, O_RDWR, ostr); flag_str(oflag, O_CREAT, ostr); flag_str(oflag, O_EXCL, ostr); flag_str(oflag, O_TRUNC, ostr); if (oflag & ~(O_RDONLY | O_RDWR | O_CREAT | O_EXCL | O_TRUNC)) strcat(ostr, "?|"); msg("shm_open(%es, 0%o:%s, 0%03o): %p", name, oflag, ostr, mode_arg, ret_addr); char overwrite[BUFFER_SIZE]; if (mode >= 4) { char msg_buf[BUFFER_SIZE]; rcv(msg_buf, sizeof(msg_buf)); if (strncmp(msg_buf, "modify ", 7) == 0) { // modify ,, char *val_1 = NULL, *end_ptr_1 = NULL, *end_ptr_2 = NULL, *end_ptr_3 = NULL; long val_2 = 0, val_3 = 0; if (msg_buf[7] == '"') { // modify "",... val_1 = strtostr(msg_buf + 7, &end_ptr_1, overwrite); if (val_1 == NULL) end_ptr_1 = NULL; } else { // modify ,... val_1 = (char *)strtol(msg_buf + 7, &end_ptr_1, 0); } if (end_ptr_1 != NULL && end_ptr_1[0] != 0) { if (end_ptr_1[1] == '|') { val_2 = 0; end_ptr_2 = end_ptr_1 + 1; if (strncmp(end_ptr_2, "O_RDONLY|", 8) == 0) { val_2 |= O_RDONLY; end_ptr_2 += 9; } if (strncmp(end_ptr_2, "O_RDWR|", 8) == 0) { val_2 |= O_RDWR; end_ptr_2 += 7; } if (strncmp(end_ptr_2, "O_CREAT|", 8) == 0) { val_2 |= O_CREAT; end_ptr_2 += 8; } if (strncmp(end_ptr_2, "O_EXCL|", 7) == 0) { val_2 |= O_EXCL; end_ptr_2 += 7; } if (strncmp(end_ptr_2, "O_TRUNC|", 7) == 0) { val_2 |= O_TRUNC; end_ptr_2 += 8; } } else { val_2 = strtol(end_ptr_1 + 1, &end_ptr_2, 0); } } if (end_ptr_2 != NULL && end_ptr_2[0] != 0) val_3 = strtol(end_ptr_2 + 1, &end_ptr_3, 0); if (end_ptr_1 != NULL && end_ptr_1[0] == ',' && end_ptr_1 != msg_buf + 7 && end_ptr_2 != NULL && end_ptr_2[0] == ',' && end_ptr_2 != end_ptr_1 + 1 && end_ptr_3 != NULL && end_ptr_3[0] == 0 && end_ptr_3 != end_ptr_2 + 1) { name = val_1; 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); } } else if_return_int_errno(shm_open) else if_fail_int_errno(shm_open) else if_invalid(shm_open) } const int ret = __real_shm_open(name, oflag, mode); msg("return %i; errno %s", ret, strerrorname_np(errno)); return ret; } int sym(shm_unlink)(const char *name) { init(); if (!func_flags[func_idx_shm_unlink]) return __real_shm_unlink(name); msg("shm_unlink(%es): %p", name, ret_addr); char overwrite[BUFFER_SIZE]; if (mode >= 4) { char msg_buf[BUFFER_SIZE]; rcv(msg_buf, sizeof(msg_buf)); if (strncmp(msg_buf, "modify ", 7) == 0) { char *end_ptr = NULL, *val = NULL; if (msg_buf[7] == '"') { // modify "" val = strtostr(msg_buf + 7, &end_ptr, overwrite); if (val == NULL) end_ptr = NULL; } else { // modify val = (char *)strtol(msg_buf + 7, &end_ptr, 0); } 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); } } else if_return_int_errno(shm_unlink) else if_fail_int_errno(shm_unlink) else if_invalid(shm_unlink) } const int ret = __real_shm_unlink(name); msg("return %i; errno %s", ret, strerrorname_np(errno)); return ret; } void *sym(mmap)(void *addr, size_t len, int prot, int flags, int fildes, off_t off) { init(); if (!func_flags[func_idx_mmap]) return __real_mmap(addr, len, prot, flags, fildes, off); char pstr[64] = "|"; if (prot == PROT_NONE) strcat(pstr, "PROT_NONE|"); flag_str(prot, PROT_READ, pstr); flag_str(prot, PROT_WRITE, pstr); flag_str(prot, PROT_EXEC, pstr); if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC)) strcat(pstr, "?|"); char fstr[64] = "|"; flag_str(prot, MAP_SHARED, fstr); flag_str(prot, MAP_PRIVATE, fstr); flag_str(prot, MAP_FIXED, fstr); flag_str(prot, MAP_ANONYMOUS, fstr); if (prot & ~(MAP_SHARED | MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS)) strcat(fstr, "?|"); msg("mmap(%p, %i, 0x%x:%s, %0x%x:%s, %i, %i): %p", addr, len, prot, pstr, flags, fstr, fildes, off, ret_addr); if (mode >= 4) { char msg_buf[BUFFER_SIZE]; rcv(msg_buf, sizeof(msg_buf)); if (strncmp(msg_buf, "modify ", 7) == 0) { // TODO mmap modify fprintf(stderr, "intercept: %s: modify command not implemented\n", "mmap"); } else if_return_ptr_errno(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)); return ret; } int sym(munmap)(void *addr, size_t len) { init(); if (!func_flags[func_idx_munmap]) return __real_munmap(addr, len); msg("munmap(%p, %i): %p", addr, len, ret_addr); if (mode >= 4) { char msg_buf[BUFFER_SIZE]; rcv(msg_buf, sizeof(msg_buf)); if_modify_int_int(munmap, void *, addr, size_t, len) else if_return_int_errno(munmap) else if_fail_int_errno(munmap) else if_invalid(munmap) } const int ret = __real_munmap(addr, len); msg("return %i; errno %s", ret, strerrorname_np(errno)); return ret; } int sym(ftruncate)(int fildes, off_t length) { init(); if (!func_flags[func_idx_ftruncate]) return __real_ftruncate(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_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(); if (!func_flags[func_idx_fork]) return __real_fork(); 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(); if (!func_flags[func_idx_wait]) return __real_wait(stat_loc); 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(); if (!func_flags[func_idx_waitpid]) return __real_waitpid(pid, stat_loc, options); char ostr[64] = "|"; flag_str(options, WCONTINUED, ostr); flag_str(options, WNOHANG, ostr); flag_str(options, WUNTRACED, ostr); 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); if (!func_flags[func_idx_execl]) return __real_execv(pathname, (char *const *)arg_vec); 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], 0); } 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); if (!func_flags[func_idx_execlp]) return __real_execvp(file, (char *const *)arg_vec); 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], 0); } 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); if (!func_flags[func_idx_execle]) return __real_execvpe(pathname, (char *const *)arg_vec, envp); 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], 0); } 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(); if (!func_flags[func_idx_execv]) return __real_execv(pathname, argv); 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(); if (!func_flags[func_idx_execvp]) return __real_execvp(file, argv); 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(); if (!func_flags[func_idx_execvpe]) return __real_execvpe(file, argv, envp); 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(); if (!func_flags[func_idx_execve]) return __real_execve(pathname, argv, envp); 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(); if (!func_flags[func_idx_fexecve]) return __real_fexecve(fd, argv, envp); 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(); if (!func_flags[func_idx_pipe]) return __real_pipe(fildes); msg("pipe(%p): %p", fildes, 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; fildes=[%i,%i]", ret, strerrorname_np(errno), fildes[0], fildes[1]); return ret; } int sym(dup)(int oldfd) { init(); if (!func_flags[func_idx_dup]) return __real_dup(oldfd); 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(); if (!func_flags[func_idx_dup2]) return __real_dup2(oldfd, newfd); 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(); if (!func_flags[func_idx_dup3]) return __real_dup3(oldfd, newfd, flags); char fstr[16] = "|"; flag_str(flags, O_CLOEXEC, fstr); 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; } int sym(socket)(int domain, int type, int protocol) { init(); if (!func_flags[func_idx_socket]) return __real_socket(domain, type, protocol); msg("socket(%i:%s, %i:%s, %i): %p", domain, getdomainstr(domain), type, getsocktype(type), protocol, ret_addr); if (mode >= 4) { char msg_buf[BUFFER_SIZE]; rcv(msg_buf, sizeof(msg_buf)); if (strncmp(msg_buf, "modify ", 7) == 0) { // TODO socket modify fprintf(stderr, "intercept: %s: modify command not implemented\n", "socket"); } else if_return_int_errno(socket) else if_fail_int_errno(socket) else if_invalid(socket) } const int ret = __real_socket(domain, type, protocol); msg("return %i; errno %s", ret, strerrorname_np(errno)); return ret; } int sym(bind)(int sockfd, const struct sockaddr *address, socklen_t address_len) { init(); if (!func_flags[func_idx_bind]) return __real_bind(sockfd, address, address_len); msg("socket(%i, %qa, %i): %p", sockfd, address_len, address, address_len, ret_addr); if (mode >= 4) { char msg_buf[BUFFER_SIZE]; rcv(msg_buf, sizeof(msg_buf)); if (strncmp(msg_buf, "modify ", 7) == 0) { // TODO bind modify fprintf(stderr, "intercept: %s: modify command not implemented\n", "bind"); } else if_return_int_errno(bind) else if_fail_int_errno(bind) else if_invalid(bind) } const int ret = __real_bind(sockfd, address, address_len); msg("return %i; errno %s", ret, strerrorname_np(errno)); return ret; } int sym(listen)(int sockfd, int backlog) { init(); if (!func_flags[func_idx_listen]) return __real_listen(sockfd, backlog); msg("listen(%i, %i): %p", sockfd, backlog, ret_addr); if (mode >= 4) { char msg_buf[BUFFER_SIZE]; rcv(msg_buf, sizeof(msg_buf)); if_modify_int_int(listen, int, sockfd, int, backlog) else if_return_int_errno(listen) else if_fail_int_errno(listen) else if_invalid(listen) } const int ret = __real_listen(sockfd, backlog); msg("return %i; errno %s", ret, strerrorname_np(errno)); return ret; } int sym(accept)(int sockfd, struct sockaddr *restrict address, socklen_t *restrict address_len) { init(); if (!func_flags[func_idx_accept]) return __real_accept(sockfd, address, address_len); msg("accept(%i, %p, %p): %p", sockfd, address, address_len, ret_addr); if (mode >= 4) { char msg_buf[BUFFER_SIZE]; rcv(msg_buf, sizeof(msg_buf)); if (strncmp(msg_buf, "modify ", 7) == 0) { // TODO accept modify fprintf(stderr, "intercept: %s: modify command not implemented\n", "accept"); } else if_return_int_errno(accept) else if_fail_int_errno(accept) else if_invalid(accept) } const int ret = __real_accept(sockfd, address, address_len); if (ret >= 0) { if (address != NULL && address_len != NULL) { msg("return %i; errno %s; address=%qa; address_len=%i", ret, strerrorname_np(errno), *address_len, address, *address_len); } else { msg("return %i; errno %s", ret, strerrorname_np(errno)); } } else { msg("return %i; errno %s", ret, strerrorname_np(errno)); } return ret; } int sym(connect)(int sockfd, const struct sockaddr *address, socklen_t address_len) { init(); if (!func_flags[func_idx_connect]) return __real_connect(sockfd, address, address_len); msg("connect(%i, %qa, %i): %p", sockfd, address_len, address, address_len, ret_addr); if (mode >= 4) { char msg_buf[BUFFER_SIZE]; rcv(msg_buf, sizeof(msg_buf)); if (strncmp(msg_buf, "modify ", 7) == 0) { // TODO connect modify fprintf(stderr, "intercept: %s: modify command not implemented\n", "connect"); } else if_return_int_errno(connect) else if_fail_int_errno(connect) else if_invalid(connect) } const int ret = __real_connect(sockfd, address, address_len); msg("return %i; errno %s", ret, strerrorname_np(errno)); return ret; } int sym(getaddrinfo)(const char *restrict node, const char *restrict service, const struct addrinfo *restrict hints, struct addrinfo **restrict res) { init(); if (!func_flags[func_idx_getaddrinfo]) return __real_getaddrinfo(node, service, hints, res); msg("getaddrinfo(%es, %es, %qi, %p): %p", node, service, hints, res, ret_addr); if (mode >= 4) { char msg_buf[BUFFER_SIZE]; rcv(msg_buf, sizeof(msg_buf)); if (strncmp(msg_buf, "modify ", 7) == 0) { // TODO getaddrinfo modify fprintf(stderr, "intercept: %s: modify command not implemented\n", "getaddrinfo"); } else if_return_int_errno(getaddrinfo) else if_fail_int_errno(getaddrinfo) else if_invalid(getaddrinfo) } const int ret = __real_getaddrinfo(node, service, hints, res); msg("return %i; errno %s", ret, strerrorname_np(errno)); return ret; } void sym(freeaddrinfo)(struct addrinfo *res) { init(); if (!func_flags[func_idx_freeaddrinfo]) { __real_freeaddrinfo(res); return; } msg("freeaddrinfo(%p): %p", res, ret_addr); if (mode >= 4) { char msg_buf[BUFFER_SIZE]; rcv(msg_buf, sizeof(msg_buf)); if_modify_int(freeaddrinfo, struct addrinfo *, res) else if_return else if_invalid(freeaddrinfo) } __real_freeaddrinfo(res); msg("return"); } ssize_t sym(send)(int sockfd, const void *buf, size_t length, int flags) { init(); if (!func_flags[func_idx_send]) return __real_send(sockfd, buf, length, flags); char fstr[256] = "|"; flag_str(flags, MSG_CONFIRM, fstr); flag_str(flags, MSG_DONTROUTE, fstr); flag_str(flags, MSG_DONTWAIT, fstr); flag_str(flags, MSG_EOR, fstr); flag_str(flags, MSG_MORE, fstr); flag_str(flags, MSG_NOSIGNAL, fstr); flag_str(flags, MSG_OOB, fstr); flag_str(flags, MSG_FASTOPEN, fstr); if (flags & ~(MSG_CONFIRM | MSG_DONTROUTE | MSG_EOR | MSG_MORE | MSG_NOSIGNAL | MSG_OOB | MSG_FASTOPEN)) strcat(fstr, "?|"); msg("send(%i, %eb, %i, 0x%x:%s): %p", sockfd, length, buf, length, flags, fstr, ret_addr); if (mode >= 4) { char msg_buf[BUFFER_SIZE]; rcv(msg_buf, sizeof(msg_buf)); if (strncmp(msg_buf, "modify ", 7) == 0) { // TODO send modify fprintf(stderr, "intercept: %s: modify command not implemented\n", "send"); } else if_return_int_errno(send) else if_fail_int_errno(send) else if_invalid(send) } const ssize_t ret = __real_send(sockfd, buf, length, flags); msg("return %i; errno %s", ret, strerrorname_np(errno)); return ret; } ssize_t sym(sendto)(int sockfd, const void *buf, size_t size, int flags, const struct sockaddr *dest_addr, socklen_t addrlen) { init(); if (!func_flags[func_idx_sendto]) return __real_sendto(sockfd, buf, size, flags, dest_addr, addrlen); char fstr[256] = "|"; flag_str(flags, MSG_CONFIRM, fstr); flag_str(flags, MSG_DONTROUTE, fstr); flag_str(flags, MSG_DONTWAIT, fstr); flag_str(flags, MSG_EOR, fstr); flag_str(flags, MSG_MORE, fstr); flag_str(flags, MSG_NOSIGNAL, fstr); flag_str(flags, MSG_OOB, fstr); flag_str(flags, MSG_FASTOPEN, fstr); if (flags & ~(MSG_CONFIRM | MSG_DONTROUTE | MSG_EOR | MSG_MORE | MSG_NOSIGNAL | MSG_OOB | MSG_FASTOPEN)) strcat(fstr, "?|"); msg("sendto(%i, %eb, %i, 0x%x:%s, %qa, %i): %p", sockfd, size, buf, size, flags, fstr, addrlen, dest_addr, addrlen, ret_addr); if (mode >= 4) { char msg_buf[BUFFER_SIZE]; rcv(msg_buf, sizeof(msg_buf)); if (strncmp(msg_buf, "modify ", 7) == 0) { // TODO sendto modify fprintf(stderr, "intercept: %s: modify command not implemented\n", "sendto"); } else if_return_int_errno(sendto) else if_fail_int_errno(sendto) else if_invalid(sendto) } const ssize_t ret = __real_sendto(sockfd, buf, size, flags, dest_addr, addrlen); msg("return %i; errno %s", ret, strerrorname_np(errno)); return ret; } ssize_t sym(sendmsg)(int sockfd, const struct msghdr *message, int flags) { init(); if (!func_flags[func_idx_sendmsg]) return __real_sendmsg(sockfd, message, flags); char fstr[256] = "|"; flag_str(flags, MSG_CONFIRM, fstr); flag_str(flags, MSG_DONTROUTE, fstr); flag_str(flags, MSG_DONTWAIT, fstr); flag_str(flags, MSG_EOR, fstr); flag_str(flags, MSG_MORE, fstr); flag_str(flags, MSG_NOSIGNAL, fstr); flag_str(flags, MSG_OOB, fstr); flag_str(flags, MSG_FASTOPEN, fstr); if (flags & ~(MSG_CONFIRM | MSG_DONTROUTE | MSG_EOR | MSG_MORE | MSG_NOSIGNAL | MSG_OOB | MSG_FASTOPEN)) strcat(fstr, "?|"); msg("sendmsg(%i, %qm, 0x%x:%s): %p", sockfd, message, flags, fstr, ret_addr); if (mode >= 4) { char msg_buf[BUFFER_SIZE]; rcv(msg_buf, sizeof(msg_buf)); if (strncmp(msg_buf, "modify ", 7) == 0) { // TODO sendmsg modify fprintf(stderr, "intercept: %s: modify command not implemented\n", "sendmsg"); } else if_return_int_errno(sendmsg) else if_fail_int_errno(sendmsg) else if_invalid(sendmsg) } const ssize_t ret = __real_sendmsg(sockfd, message, flags); msg("return %i; errno %s", ret, strerrorname_np(errno)); return ret; } ssize_t sym(recv)(int sockfd, void *buf, size_t size, int flags) { init(); if (!func_flags[func_idx_recv]) return __real_recv(sockfd, buf, size, flags); char fstr[256] = "|"; flag_str(flags, MSG_DONTWAIT, fstr); flag_str(flags, MSG_ERRQUEUE, fstr); flag_str(flags, MSG_OOB, fstr); flag_str(flags, MSG_PEEK, fstr); flag_str(flags, MSG_TRUNC, fstr); flag_str(flags, MSG_WAITALL, fstr); if (flags & ~(MSG_DONTWAIT | MSG_ERRQUEUE | MSG_OOB | MSG_PEEK | MSG_TRUNC | MSG_WAITALL)) strcat(fstr, "?|"); msg("recv(%i, %p, %i, 0x%x:%s): %p", sockfd, buf, size, flags, fstr, ret_addr); if (mode >= 4) { char msg_buf[BUFFER_SIZE]; rcv(msg_buf, sizeof(msg_buf)); if (strncmp(msg_buf, "modify ", 7) == 0) { // TODO recv modify fprintf(stderr, "intercept: %s: modify command not implemented\n", "recv"); } else if_return_int_errno(recv) else if_fail_int_errno(recv) else if_invalid(recv) } const ssize_t ret = __real_recv(sockfd, buf, size, flags); 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(recvfrom)(int sockfd, void *restrict buf, size_t size, int flags, struct sockaddr *restrict src_addr, socklen_t *restrict addrlen) { init(); if (!func_flags[func_idx_recvfrom]) return __real_recvfrom(sockfd, buf, size, flags, src_addr, addrlen); char fstr[256] = "|"; flag_str(flags, MSG_DONTWAIT, fstr); flag_str(flags, MSG_ERRQUEUE, fstr); flag_str(flags, MSG_OOB, fstr); flag_str(flags, MSG_PEEK, fstr); flag_str(flags, MSG_TRUNC, fstr); flag_str(flags, MSG_WAITALL, fstr); if (flags & ~(MSG_DONTWAIT | MSG_ERRQUEUE | MSG_OOB | MSG_PEEK | MSG_TRUNC | MSG_WAITALL)) strcat(fstr, "?|"); msg("recvfrom(%i, %p, %i, 0x%x:%s, %p, %p): %p", sockfd, buf, size, flags, fstr, addrlen, src_addr, addrlen, ret_addr); if (mode >= 4) { char msg_buf[BUFFER_SIZE]; rcv(msg_buf, sizeof(msg_buf)); if (strncmp(msg_buf, "modify ", 7) == 0) { // TODO recvfrom modify fprintf(stderr, "intercept: %s: modify command not implemented\n", "recvfrom"); } else if_return_int_errno(recvfrom) else if_fail_int_errno(recvfrom) else if_invalid(recvfrom) } const ssize_t ret = __real_recvfrom(sockfd, buf, size, flags, src_addr, addrlen); if (ret >= 0) { if (src_addr != NULL && addrlen != NULL) { msg("return %i; errno %s; buf=%eb; src_addr=%qa; addrlen=%i", ret, strerrorname_np(errno), ret, buf, *addrlen, src_addr, *addrlen); } else { 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(recvmsg)(int sockfd, struct msghdr *message, int flags) { init(); if (!func_flags[func_idx_recvmsg]) return __real_recvmsg(sockfd, message, flags); char fstr[256] = "|"; flag_str(flags, MSG_CMSG_CLOEXEC, fstr); flag_str(flags, MSG_DONTWAIT, fstr); flag_str(flags, MSG_ERRQUEUE, fstr); flag_str(flags, MSG_OOB, fstr); flag_str(flags, MSG_PEEK, fstr); flag_str(flags, MSG_TRUNC, fstr); flag_str(flags, MSG_WAITALL, fstr); if (flags & ~(MSG_CMSG_CLOEXEC | MSG_DONTWAIT | MSG_ERRQUEUE | MSG_OOB | MSG_PEEK | MSG_TRUNC | MSG_WAITALL)) strcat(fstr, "?|"); msg("recvmsg(%i, %qm, 0x%x:%s): %p", sockfd, msg, flags, fstr, ret_addr); if (mode >= 4) { char msg_buf[BUFFER_SIZE]; rcv(msg_buf, sizeof(msg_buf)); if (strncmp(msg_buf, "modify ", 7) == 0) { // TODO recvmsg modify fprintf(stderr, "intercept: %s: modify command not implemented\n", "recvmsg"); } else if_return_int_errno(recvmsg) else if_fail_int_errno(recvmsg) else if_invalid(recvmsg) } const ssize_t ret = __real_recvmsg(sockfd, message, flags); if (ret >= 0) { msg("return %i; errno %s; message=%eb", ret, strerrorname_np(errno), sizeof(*message), message); } else { msg("return %i; errno %s", ret, strerrorname_np(errno)); } return ret; }