1
0
Files
BSc-Thesis/proj/intercept/src/intercept.c

2325 lines
85 KiB
C

#define _GNU_SOURCE
#include <getopt.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/stat.h>
#include <time.h>
#include <stdarg.h>
#include <semaphore.h>
#include <signal.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <netdb.h>
#include <arpa/inet.h>
#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 <argc>,<argv>,<shortopts>
// 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 <name>,<oflag>
// modify <name>,<oflag>,<mode>,<value>
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 "<name>",...
val_1 = strtostr(msg_buf + 7, &end_ptr_1, overwrite);
if (val_1 == NULL) end_ptr_1 = NULL;
} else {
// modify <name_ptr>,...
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 <sem>,<abs_timeout_ptr>
// modify <sem>,{<tv_sec>,<tv_nsec>}
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 "<name>"
val = strtostr(msg_buf + 7, &end_ptr, overwrite);
if (val == NULL) end_ptr = NULL;
} else {
// modify <name_ptr>
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 <name>,<oflag>,<mode>
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 "<name>",...
val_1 = strtostr(msg_buf + 7, &end_ptr_1, overwrite);
if (val_1 == NULL) end_ptr_1 = NULL;
} else {
// modify <name_ptr>,...
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 "<name>"
val = strtostr(msg_buf + 7, &end_ptr, overwrite);
if (val == NULL) end_ptr = NULL;
} else {
// modify <name_ptr>
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;
}