From cf71b7b9d1dad172a89ff3c9b9aa67f4068061a7 Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Sat, 1 Mar 2025 22:54:51 +0100 Subject: [PATCH] proj: Implement mmap, munmap --- proj/server/src/intercept.py | 21 ++++-- proj/test1/Makefile | 2 +- proj/test1/src/intercept.c | 122 ++++++++++++++++++++++++++++------- 3 files changed, 114 insertions(+), 31 deletions(-) diff --git a/proj/server/src/intercept.py b/proj/server/src/intercept.py index f2c13d6..2431243 100755 --- a/proj/server/src/intercept.py +++ b/proj/server/src/intercept.py @@ -10,7 +10,8 @@ import re type Pointer = int type PointerTo[T] = tuple[Pointer, T] -type Flags = tuple[Pointer, list[str]] +type Constant = tuple[int, str] +type Flags = tuple[int, list[str]] StructTimeSpec = TypedDict('StructTimeSpec', {'tv_sec': int, 'tv_nsec': int}) StructSigAction = TypedDict('StructSigAction', {'sa_flags': Flags, 'sa_handler': NotRequired[Pointer], 'sa_sigaction': NotRequired[Pointer], 'sa_mask': list[str]}) @@ -234,14 +235,14 @@ class Handler(StreamRequestHandler): def after_close(self, fildes: int, ret_value: int, errno: str = None) -> None: raise NotImplementedError() - def before_sigaction(self, sig: int, act: PointerTo[StructSigAction], oact_ptr: Pointer) -> str: + def before_sigaction(self, sig: Constant, act: PointerTo[StructSigAction], oact_ptr: Pointer) -> str: raise NotImplementedError() - def after_sigaction(self, sig: int, act: PointerTo[StructSigAction], oact_ptr: Pointer, + def after_sigaction(self, sig: Constant, act: PointerTo[StructSigAction], oact_ptr: Pointer, ret_value: int, errno: str = None, oact: StructSigAction = None) -> None: raise NotImplementedError() - def before_sem_init(self, sem: int, pshared: int, value: int) -> str: + def before_sem_init(self, sem: Pointer, pshared: int, value: int) -> str: raise NotImplementedError() - def after_sem_init(self, sem: int, pshared: int, value: int, + def after_sem_init(self, sem: Pointer, pshared: int, value: int, ret_value: int, errno: str = None) -> None: raise NotImplementedError() def before_sem_open(self, name: str, oflag: Flags, mode: Optional[int], value: Optional[int]) -> str: @@ -299,6 +300,16 @@ class Handler(StreamRequestHandler): def after_shm_unlink(self, name: PointerTo[bytes], ret_value: int, errno: str = None) -> None: raise NotImplementedError() + def before_mmap(self, addr: Pointer, len_value: int, prot: Flags, flags: Flags, fildes: int, off: int) -> str: + raise NotImplementedError() + def after_mmap(self, addr: Pointer, len_value: int, prot: Flags, flags: Flags, fildes: int, off: int, + ret_value: Pointer, errno: str = None) -> None: + raise NotImplementedError() + def before_munmap(self, addr: Pointer, len_value: int) -> str: + raise NotImplementedError() + def after_munmap(self, addr: Pointer, len_value: int, + ret_value: int, errno: str = None) -> None: + raise NotImplementedError() class MemoryAllocationTester(Handler): diff --git a/proj/test1/Makefile b/proj/test1/Makefile index 2eaac70..16edf24 100644 --- a/proj/test1/Makefile +++ b/proj/test1/Makefile @@ -27,7 +27,7 @@ main: bin/main.o main_intercept: bin/main.o src/intercept.c $(CC) -o $@ $^ $(CFLAGS) -lc -Wl,--wrap=malloc,--wrap=free,--wrap=calloc,--wrap=realloc,--wrap=reallocarray,--wrap=getopt,--wrap=exit,--wrap=close,--wrap=sigaction,\ --wrap=sem_init,--wrap=sem_open,--wrap=sem_post,--wrap=sem_wait,--wrap=sem_trywait,--wrap=sem_timedwait,--wrap=sem_getvalue,--wrap=sem_close,--wrap=sem_unlink,--wrap=sem_destroy,\ ---wrap=shm_open,--wrap=shm_unlink +--wrap=shm_open,--wrap=shm_unlink,--wrap=mmap,--wrap=munmap clean: rm -rf main main_wrapped bin/* *.so *.ko *.o diff --git a/proj/test1/src/intercept.c b/proj/test1/src/intercept.c index 67fd37b..a5130fe 100644 --- a/proj/test1/src/intercept.c +++ b/proj/test1/src/intercept.c @@ -17,6 +17,7 @@ #include #include #include +#include #define BUFFER_SIZE 256 @@ -42,6 +43,8 @@ static int (*__real_sem_unlink)(const char *); static int (*__real_sem_destroy)(sem_t *); static int (*__real_shm_open)(const char *, int, mode_t); static int (*__real_shm_unlink)(const char *); +static void *(*__real_mmap)(void *, size_t, int, int, int, off_t); +static int (*__real_munmap)(void *, size_t); #define load(name) \ if (((__real_ ## name) = dlsym(RTLD_NEXT, #name)) == NULL) { \ fprintf(stderr, "intercept: unable to load symbol '%s': %s", #name, strerror(errno)); \ @@ -70,12 +73,14 @@ extern int __real_sem_unlink(const char *); extern int __real_sem_destroy(sem_t *); extern int __real_shm_open(const char *, int, mode_t); extern int __real_shm_unlink(const char *); +extern void *__real_mmap(void *, size_t, int, int, int, off_t); +extern int __real_munmap(void *, size_t); #define sym(name) __wrap_ ## name #endif #define ret_addr __builtin_return_address(0) -#define if_invalid(name) if (strcmp(buf, "ok") != 0) { fprintf(stderr, "intercept: " #name ": invalid command: '%s'\n", buf); } +#define if_invalid(name) if (strcmp(buf, "ok") != 0) { fprintf(stderr, "intercept: %s: invalid command: '%s'\n", #name, buf); } #define if_modify_int(name, type_1, var_1) if (strncmp(buf, "modify ", 7) == 0) { \ char *end_ptr = NULL; \ @@ -83,7 +88,7 @@ extern int __real_shm_unlink(const char *); if (end_ptr != NULL && end_ptr[0] == 0 && end_ptr != buf + 7) { \ var_1 = (type_1)val; \ } else { \ - fprintf(stderr, "intercept: " #name ": invalid args in modify command: '%s'\n", buf + 7); \ + fprintf(stderr, "intercept: %s: invalid args in modify command: '%s'\n", #name, buf + 7); \ } } #define if_modify_int_int(name, type_1, var_1, type_2, var_2) if (strncmp(buf, "modify ", 7) == 0) { \ @@ -97,7 +102,7 @@ extern int __real_shm_unlink(const char *); var_1 = (type_1)val_1; \ var_2 = (type_2)val_2; \ } else { \ - fprintf(stderr, "intercept: " #name ": invalid args in modify command: '%s'\n", buf + 7); \ + fprintf(stderr, "intercept: %s: invalid args in modify command: '%s'\n", #name, buf + 7); \ } } #define if_modify_int_int_int(name, type_1, var_1, type_2, var_2, type_3, var_3) if (strncmp(buf, "modify ", 7) == 0) { \ @@ -114,7 +119,7 @@ extern int __real_shm_unlink(const char *); var_2 = (type_2)val_2; \ var_3 = (type_3)val_3; \ } else { \ - fprintf(stderr, "intercept: " #name ": invalid args in modify command: '%s'\n", buf + 7); \ + fprintf(stderr, "intercept: %s: invalid args in modify command: '%s'\n", #name, buf + 7); \ } } #define if_return if (strcmp(buf, "return") == 0) { \ @@ -128,7 +133,7 @@ extern int __real_shm_unlink(const char *); msg("return %i", val); \ return val; \ } else { \ - fprintf(stderr, "intercept: " #name ": invalid args in return command: '%s'\n", buf + 7); \ + fprintf(stderr, "intercept: %s: invalid args in return command: '%s'\n", #name, buf + 7); \ } } #define if_return_int_errno(name) if (strncmp(buf, "return ", 7) == 0) { \ @@ -138,7 +143,7 @@ extern int __real_shm_unlink(const char *); msg("return %i; errno %s", val, strerrorname_np(errno)); \ return val; \ } else { \ - fprintf(stderr, "intercept: " #name ": invalid args in return command: '%s'\n", buf + 7); \ + fprintf(stderr, "intercept: %s: invalid args in return command: '%s'\n", #name, buf + 7); \ } } #define if_return_int_errno_int(name, type_1, var_1, name_1) if (strncmp(buf, "return ", 7) == 0) { \ @@ -150,10 +155,10 @@ extern int __real_shm_unlink(const char *); 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; " name_1 "=%i", val_1, strerrorname_np(errno), var_1); \ + msg("return %i; errno %s; %s=%i", val_1, strerrorname_np(errno), name_1, var_1); \ return val_1; \ } else { \ - fprintf(stderr, "intercept: " #name ": invalid args in return command: '%s'\n", buf + 7); \ + fprintf(stderr, "intercept: %s: invalid args in return command: '%s'\n", #name, buf + 7); \ } } #define if_return_ptr_errno(name) if (strncmp(buf, "return ", 7) == 0) { \ @@ -163,14 +168,14 @@ extern int __real_shm_unlink(const char *); msg("return %p; errno %s", val, strerrorname_np(errno)); \ return (void *)val; \ } else { \ - fprintf(stderr, "intercept: " #name ": invalid args in return command: '%s'\n", buf + 7); \ + fprintf(stderr, "intercept: %s: invalid args in return command: '%s'\n", #name, buf + 7); \ } } #define if_error_1_ptr_errno(name, err1) if (strncmp(buf, "fail ", 5) == 0) { \ if (strcmp(buf + 5, #err1) == 0) { errno = err1; \ } else { \ errno = 0; \ - fprintf(stderr, "intercept: " #name ": invalid error code in fail command: '%s'\n", buf + 5); \ + fprintf(stderr, "intercept: %s: invalid error code in fail command: '%s'\n", #name, buf + 5); \ } \ msg("return %p; errno %s", NULL, strerrorname_np(errno)); \ return NULL; } @@ -179,7 +184,7 @@ extern int __real_shm_unlink(const char *); if (strcmp(buf + 5, #err1) == 0) { errno = err1; \ } else { \ errno = 0; \ - fprintf(stderr, "intercept: " #name ": invalid error code in fail command: '%s'\n", buf + 5); \ + fprintf(stderr, "intercept: %s: invalid error code in fail command: '%s'\n", #name, buf + 5); \ } \ msg("return %i; errno %s", -1, strerrorname_np(errno)); \ return -1; } @@ -189,7 +194,7 @@ extern int __real_shm_unlink(const char *); } else if (strcmp(buf + 5, #err2) == 0) { errno = err2; \ } else { \ errno = 0; \ - fprintf(stderr, "intercept: " #name ": invalid error code in fail command: '%s'\n", buf + 5); \ + fprintf(stderr, "intercept: %s: invalid error code in fail command: '%s'\n", #name, buf + 5); \ } \ msg("return %i; errno %s", -1, strerrorname_np(errno)); \ return -1; } @@ -200,7 +205,7 @@ extern int __real_shm_unlink(const char *); } else if (strcmp(buf + 5, #err3) == 0) { errno = err3; \ } else { \ errno = 0; \ - fprintf(stderr, "intercept: " #name ": invalid error code in fail command: '%s'\n", buf + 5); \ + fprintf(stderr, "intercept: %s: invalid error code in fail command: '%s'\n", #name, buf + 5); \ } \ msg("return %i; errno %s", -1, strerrorname_np(errno)); \ return -1; } @@ -212,10 +217,10 @@ extern int __real_shm_unlink(const char *); } else if (strcmp(buf + 5, #err4) == 0) { errno = err4; \ } else if (strcmp(buf + 5, #err5) == 0) { errno = err5; \ } else if (strcmp(buf + 5, #err6) == 0) { errno = err6; \ - } else if (strcmp(buf + 5, #err6) == 0) { errno = err7; \ + } else if (strcmp(buf + 5, #err7) == 0) { errno = err7; \ } else { \ errno = 0; \ - fprintf(stderr, "intercept: " #name ": invalid error code in fail command: '%s'\n", buf + 5); \ + fprintf(stderr, "intercept: %s: invalid error code in fail command: '%s'\n", #name, buf + 5); \ } \ msg("return %i; errno %s", -1, strerrorname_np(errno)); \ return -1; } @@ -231,11 +236,29 @@ extern int __real_shm_unlink(const char *); } else if (strcmp(buf + 5, #err8) == 0) { errno = err8; \ } else { \ errno = 0; \ - fprintf(stderr, "intercept: " #name ": invalid error code in fail command: '%s'\n", buf + 5); \ + fprintf(stderr, "intercept: %s: invalid error code in fail command: '%s'\n", #name, buf + 5); \ } \ msg("return %p; errno %s", NULL, strerrorname_np(errno)); \ return NULL; } +#define if_error_10_map_errno(name, err1, err2, err3, err4, err5, err6, err7, err8, err9, err10) if (strncmp(buf, "fail ", 5) == 0) { \ + if (strcmp(buf + 5, #err1) == 0) { errno = err1; \ + } else if (strcmp(buf + 5, #err2) == 0) { errno = err2; \ + } else if (strcmp(buf + 5, #err3) == 0) { errno = err3; \ + } else if (strcmp(buf + 5, #err4) == 0) { errno = err4; \ + } else if (strcmp(buf + 5, #err5) == 0) { errno = err5; \ + } else if (strcmp(buf + 5, #err6) == 0) { errno = err6; \ + } else if (strcmp(buf + 5, #err7) == 0) { errno = err7; \ + } else if (strcmp(buf + 5, #err8) == 0) { errno = err8; \ + } else if (strcmp(buf + 5, #err9) == 0) { errno = err9; \ + } else if (strcmp(buf + 5, #err10) == 0) { errno = err10; \ + } else { \ + errno = 0; \ + fprintf(stderr, "intercept: %s: invalid error code in fail command: '%s'\n", #name, buf + 5); \ + } \ + msg("return %i; errno %s", MAP_FAILED, strerrorname_np(errno)); \ + return MAP_FAILED; } + static char *strtostr(char *ptr, char **end_ptr, char *buf) { if (ptr[0] != '"') return NULL; @@ -479,6 +502,8 @@ static void init(void) { load(sem_destroy); load(shm_open); load(shm_unlink); + load(mmap); + load(munmap); #endif atexit(fin); const char *val = getenv("INTERCEPT"); @@ -614,7 +639,7 @@ int sym(getopt)(const int argc, char *const argv[], const char *shortopts) { if (strncmp(buf, "modify ", 7) == 0) { // modify ,, // TODO getopt modify - fprintf(stderr, "intercept: getopt: modify command not implemented\n"); + fprintf(stderr, "intercept: %s: modify command not implemented\n", "getopt"); } else if_return_int(getopt) else if_invalid(getopt) } @@ -717,10 +742,10 @@ int sym(sigaction)(int sig, const struct sigaction *restrict act, struct sigacti rcv(buf, sizeof(buf)); if (strncmp(buf, "modify ", 7) == 0) { // TODO sigaction modify - fprintf(stderr, "intercept: sigaction: modify command not implemented\n"); + fprintf(stderr, "intercept: %s: modify command not implemented\n", "sigaction"); } else if (strncmp(buf, "return ", 7) == 0) { // TODO sigaction return - fprintf(stderr, "intercept: sigaction: return command not implemented\n"); + fprintf(stderr, "intercept: %s: return command not implemented\n", "sigaction"); } else if_error_1_int_errno(sigaction, EINVAL) else if_invalid(sigaction) } @@ -835,7 +860,7 @@ sem_t *sym(sem_open)(const char *name, int oflag, ...) { value = val_4; } } else { - fprintf(stderr, "intercept: sem_open: invalid args in modify command: '%s'\n", buf + 7); \ + fprintf(stderr, "intercept: %s: invalid args in modify command: '%s'\n", "sem_open", buf + 7); \ } } else if_return_ptr_errno(sem_open) else if_error_8_ptr_errno(sem_open, EACCES, EEXIST, EINVAL, EMFILE, ENAMETOOLONG, ENFILE, ENOENT, ENOMEM) @@ -934,7 +959,7 @@ int sym(sem_timedwait)(sem_t *restrict sem, const struct timespec *restrict abs_ sem = (sem_t *)val_1; abs_timeout = val_2; } else { - fprintf(stderr, "intercept: sem_timedwait: invalid args in modify command: '%s'\n", buf + 7); \ + fprintf(stderr, "intercept: %s: invalid args in modify command: '%s'\n", "sem_timedwait", buf + 7); \ } } else if_return_int_errno(sem_timedwait) else if_error_3_int_errno(sem_timedwait, EINTR, EINVAL, ETIMEDOUT) @@ -1001,7 +1026,7 @@ int sym(sem_unlink)(const char *name) { if (end_ptr != NULL && end_ptr[0] == 0 && end_ptr != buf + 7) { name = val; } else { - fprintf(stderr, "intercept: sem_unlink: invalid args in modify command: '%s'\n", buf + 7); \ + fprintf(stderr, "intercept: %s: invalid args in modify command: '%s'\n", "sem_unlink", buf + 7); \ } } else if_return_int_errno(sem_unlink) else if_error_3_int_errno(sem_unlink, EACCES, ENAMETOOLONG, ENOENT) @@ -1038,7 +1063,7 @@ int sym(shm_open)(const char *name, int oflag, mode_t mode_arg) { if (oflag & O_TRUNC) strcat(ostr, "O_TRUNC|"); if (oflag & ~(O_RDONLY | O_RDWR | O_CREAT | O_EXCL | O_TRUNC)) strcat(ostr, "?|"); - msg("shm_open(%es, 0%o:%s, 0%o): %p", name, oflag, ostr, mode_arg, ret_addr); + 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 buf[BUFFER_SIZE]; @@ -1093,7 +1118,7 @@ int sym(shm_open)(const char *name, int oflag, mode_t mode_arg) { oflag = (int)val_2; mode_arg = val_3; } else { - fprintf(stderr, "intercept: shm_open: invalid args in modify command: '%s'\n", buf + 7); \ + fprintf(stderr, "intercept: %s: invalid args in modify command: '%s'\n", "shm_open", buf + 7); \ } } else if_return_int_errno(shm_open) else if_error_7_int_errno(shm_open, EACCES, EEXIST, EINVAL, EMFILE, ENAMETOOLONG, ENFILE, ENOENT) @@ -1124,7 +1149,7 @@ int sym(shm_unlink)(const char *name) { if (end_ptr != NULL && end_ptr[0] == 0 && end_ptr != buf + 7) { name = val; } else { - fprintf(stderr, "intercept: shm_unlink: invalid args in modify command: '%s'\n", buf + 7); \ + fprintf(stderr, "intercept: %s: invalid args in modify command: '%s'\n", "shm_unlink", buf + 7); \ } } else if_return_int_errno(shm_unlink) else if_error_3_int_errno(shm_unlink, EACCES, ENAMETOOLONG, ENOENT) @@ -1134,3 +1159,50 @@ int sym(shm_unlink)(const char *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(); + char pstr[64] = "|"; + if (prot == PROT_NONE) strcat(pstr, "PROT_NONE|"); + if (prot & PROT_READ) strcat(pstr, "PROT_READ|"); + if (prot & PROT_WRITE) strcat(pstr, "PROT_WRITE|"); + if (prot & PROT_EXEC) strcat(pstr, "PROT_EXEC|"); + if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC)) strcat(pstr, "?|"); + char fstr[64] = "|"; + if (prot & MAP_SHARED) strcat(fstr, "MAP_SHARED|"); + if (prot & MAP_PRIVATE) strcat(fstr, "MAP_PRIVATE|"); + if (prot & MAP_FIXED) strcat(fstr, "MAP_FIXED|"); + if (prot & MAP_ANONYMOUS) strcat(fstr, "MAP_ANONYMOUS|"); + 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 buf[BUFFER_SIZE]; + rcv(buf, sizeof(buf)); + if (strncmp(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_error_10_map_errno(mmap, EACCES, EAGAIN, EBADF, EINVAL, EMFILE, ENODEV, ENOMEM, ENOTSUP, ENXIO, EOVERFLOW) + 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(); + msg("munmap(%p, %i): %p", addr, len, ret_addr); + if (mode >= 4) { + char buf[BUFFER_SIZE]; + rcv(buf, sizeof(buf)); + if_modify_int_int(munmap, void *, addr, size_t, len) + else if_return_int_errno(munmap) + else if_error_1_int_errno(munmap, EINVAL) + else if_invalid(munmap) + } + const int ret = __real_munmap(addr, len); + msg("return %i; errno %s", ret, strerrorname_np(errno)); + return ret; +}