2325 lines
85 KiB
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;
|
|
}
|