diff --git a/proj/server/src/intercept.py b/proj/server/src/intercept.py index 09647c4..f2c13d6 100755 --- a/proj/server/src/intercept.py +++ b/proj/server/src/intercept.py @@ -1,16 +1,18 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -from typing import Optional, TypedDict +from typing import Optional, TypedDict, NotRequired from socketserver import UnixStreamServer, StreamRequestHandler, ThreadingMixIn import argparse import os import re -type Pointer[T] = tuple[int, T] -type Flags = tuple[int, list[str]] +type Pointer = int +type PointerTo[T] = tuple[Pointer, T] +type Flags = tuple[Pointer, 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]}) class ThreadedUnixStreamServer(ThreadingMixIn, UnixStreamServer): @@ -201,30 +203,30 @@ class Handler(StreamRequestHandler): def before_malloc(self, size: int) -> str: raise NotImplementedError() def after_malloc(self, size: int, - ret_value: int, errno: str = None) -> None: + ret_value: Pointer, errno: str = None) -> None: raise NotImplementedError() def before_calloc(self, nmemb: int, size: int) -> str: raise NotImplementedError() def after_calloc(self, nmemb: int, size: int, - ret_value: int, errno: str = None) -> None: + ret_value: Pointer, errno: str = None) -> None: raise NotImplementedError() - def before_realloc(self, ptr: int, size: int) -> str: + def before_realloc(self, ptr: Pointer, size: int) -> str: raise NotImplementedError() - def after_realloc(self, ptr: int, size: int, - ret_value: int, errno: str = None) -> None: + def after_realloc(self, ptr: Pointer, size: int, + ret_value: Pointer, errno: str = None) -> None: raise NotImplementedError() - def before_reallocarray(self, ptr: int, nmemb: int, size: int) -> str: + def before_reallocarray(self, ptr: Pointer, nmemb: int, size: int) -> str: raise NotImplementedError() - def after_reallocarray(self, ptr: int, nmemb: int, size: int, - ret_value: int, errno: str = None) -> None: + def after_reallocarray(self, ptr: Pointer, nmemb: int, size: int, + ret_value: Pointer, errno: str = None) -> None: raise NotImplementedError() - def before_free(self, ptr: int) -> str: + def before_free(self, ptr: Pointer) -> str: raise NotImplementedError() - def after_free(self, ptr: int) -> None: + def after_free(self, ptr: Pointer) -> None: raise NotImplementedError() - def before_getopt(self, argc: int, argv: Pointer[list[Pointer[bytes]]], optstring: Pointer[bytes]) -> str: + def before_getopt(self, argc: int, argv: PointerTo[list[PointerTo[bytes]]], optstring: PointerTo[bytes]) -> str: raise NotImplementedError() - def after_getopt(self, argc: int, argv: Pointer[list[Pointer[bytes]]], optstring: Pointer[bytes], + def after_getopt(self, argc: int, argv: PointerTo[list[PointerTo[bytes]]], optstring: PointerTo[bytes], ret_value: int) -> None: raise NotImplementedError() def before_close(self, fildes: int) -> str: @@ -232,6 +234,11 @@ 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: + raise NotImplementedError() + def after_sigaction(self, sig: int, 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: raise NotImplementedError() def after_sem_init(self, sem: int, pshared: int, value: int, @@ -240,48 +247,58 @@ class Handler(StreamRequestHandler): def before_sem_open(self, name: str, oflag: Flags, mode: Optional[int], value: Optional[int]) -> str: raise NotImplementedError() def after_sem_open(self, name: str, oflag: Flags, mode: Optional[int], value: Optional[int], + ret_value: Pointer, errno: str = None) -> None: + raise NotImplementedError() + def before_sem_post(self, sem: Pointer) -> str: + raise NotImplementedError() + def after_sem_post(self, sem: Pointer, ret_value: int, errno: str = None) -> None: raise NotImplementedError() - def before_sem_post(self, sem: int) -> str: + def before_sem_wait(self, sem: Pointer) -> str: raise NotImplementedError() - def after_sem_post(self, sem: int, + def after_sem_wait(self, sem: Pointer, ret_value: int, errno: str = None) -> None: raise NotImplementedError() - def before_sem_wait(self, sem: int) -> str: + def before_sem_trywait(self, sem: Pointer) -> str: raise NotImplementedError() - def after_sem_wait(self, sem: int, - ret_value: int, errno: str = None) -> None: - raise NotImplementedError() - def before_sem_trywait(self, sem: int) -> str: - raise NotImplementedError() - def after_sem_trywait(self, sem: int, + def after_sem_trywait(self, sem: Pointer, ret_value: int, errno: str = None) -> None: raise NotImplementedError() - def before_sem_timedwait(self, sem: int, abs_timeout: Pointer[StructTimeSpec]) -> str: + def before_sem_timedwait(self, sem: Pointer, abs_timeout: PointerTo[StructTimeSpec]) -> str: raise NotImplementedError() - def after_sem_timedwait(self, sem: int, abs_timeout: Pointer[StructTimeSpec], + def after_sem_timedwait(self, sem: Pointer, abs_timeout: PointerTo[StructTimeSpec], ret_value: int, errno: str = None) -> None: raise NotImplementedError() - def before_sem_getvalue(self, sem: int, value_ptr: int) -> str: + def before_sem_getvalue(self, sem: Pointer, value_ptr: Pointer) -> str: raise NotImplementedError() - def after_sem_getvalue(self, sem:int, value_ptr: int, + def after_sem_getvalue(self, sem: Pointer, value_ptr: Pointer, ret_value: int, errno: str = None, value: int = None) -> None: raise NotImplementedError() - def before_sem_close(self, sem: int) -> str: + def before_sem_close(self, sem: Pointer) -> str: raise NotImplementedError() - def after_sem_close(self, sem: int, + def after_sem_close(self, sem: Pointer, ret_value: int, errno: str = None) -> None: raise NotImplementedError() - def before_sem_unlink(self, name: Pointer[bytes]) -> str: + def before_sem_unlink(self, name: PointerTo[bytes]) -> str: raise NotImplementedError() - def after_sem_unlink(self, name: Pointer[bytes], + def after_sem_unlink(self, name: PointerTo[bytes], ret_value: int, errno: str = None) -> None: raise NotImplementedError() - def before_sem_destroy(self, sem: int) -> str: + def before_sem_destroy(self, sem: Pointer) -> str: raise NotImplementedError() - def after_sem_destroy(self, sem: int, + def after_sem_destroy(self, sem: Pointer, ret_value: int, errno: str = None) -> None: raise NotImplementedError() + def before_shm_open(self, name: PointerTo[bytes], oflag: Flags, mode: int) -> str: + raise NotImplementedError() + def after_shm_open(self, name: PointerTo[bytes], oflag: Flags, mode: int, + ret_value: int, errno: str = None) -> None: + raise NotImplementedError() + def before_shm_unlink(self, name: PointerTo[bytes]) -> str: + raise NotImplementedError() + def after_shm_unlink(self, name: PointerTo[bytes], + ret_value: int, errno: str = None) -> None: + raise NotImplementedError() class MemoryAllocationTester(Handler): diff --git a/proj/test1/Makefile b/proj/test1/Makefile index 35f88a7..2eaac70 100644 --- a/proj/test1/Makefile +++ b/proj/test1/Makefile @@ -26,7 +26,8 @@ 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=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 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 b44e8be..67fd37b 100644 --- a/proj/test1/src/intercept.c +++ b/proj/test1/src/intercept.c @@ -40,6 +40,8 @@ static int (*__real_sem_getvalue)(sem_t *restrict, int *restrict); static int (*__real_sem_close)(sem_t *); 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 *); #define load(name) \ if (((__real_ ## name) = dlsym(RTLD_NEXT, #name)) == NULL) { \ fprintf(stderr, "intercept: unable to load symbol '%s': %s", #name, strerror(errno)); \ @@ -66,9 +68,13 @@ extern int __real_sem_getvalue(sem_t *restrict, int *restrict); extern int __real_sem_close(sem_t *); 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 *); #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_modify_int(name, type_1, var_1) if (strncmp(buf, "modify ", 7) == 0) { \ @@ -199,6 +205,21 @@ extern int __real_sem_destroy(sem_t *); msg("return %i; errno %s", -1, strerrorname_np(errno)); \ return -1; } +#define if_error_7_int_errno(name, err1, err2, err3, err4, err5, err6, err7) if (strncmp(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, #err6) == 0) { errno = err7; \ + } else { \ + errno = 0; \ + fprintf(stderr, "intercept: " #name ": invalid error code in fail command: '%s'\n", buf + 5); \ + } \ + msg("return %i; errno %s", -1, strerrorname_np(errno)); \ + return -1; } + #define if_error_8_ptr_errno(name, err1, err2, err3, err4, err5, err6, err7, err8) if (strncmp(buf, "fail ", 5) == 0) { \ if (strcmp(buf + 5, #err1) == 0) { errno = err1; \ } else if (strcmp(buf + 5, #err2) == 0) { errno = err2; \ @@ -456,6 +477,8 @@ static void init(void) { load(sem_close); load(sem_unlink); load(sem_destroy); + load(shm_open); + load(shm_unlink); #endif atexit(fin); const char *val = getenv("INTERCEPT"); @@ -506,7 +529,7 @@ static void init(void) { void *sym(malloc)(size_t size) { init(); - msg("malloc(%li): %p", size, __builtin_return_address(0)); + msg("malloc(%li): %p", size, ret_addr); if (mode >= 4) { char buf[BUFFER_SIZE]; rcv(buf, sizeof(buf)); @@ -522,7 +545,7 @@ void *sym(malloc)(size_t size) { void *sym(calloc)(size_t nmemb, size_t size) { init(); - msg("calloc(%li, %li): %p", nmemb, size, __builtin_return_address(0)); + msg("calloc(%li, %li): %p", nmemb, size, ret_addr); if (mode >= 4) { char buf[BUFFER_SIZE]; rcv(buf, sizeof(buf)); @@ -538,7 +561,7 @@ void *sym(calloc)(size_t nmemb, size_t size) { void *sym(realloc)(void *ptr, size_t size) { init(); - msg("realloc(%p, %li): %p", ptr, size, __builtin_return_address(0)); + msg("realloc(%p, %li): %p", ptr, size, ret_addr); if (mode >= 4) { char buf[BUFFER_SIZE]; rcv(buf, sizeof(buf)); @@ -554,7 +577,7 @@ void *sym(realloc)(void *ptr, size_t size) { void *sym(reallocarray)(void *ptr, size_t nmemb, size_t size) { init(); - msg("reallocarray(%p, %li): %p", ptr, size, __builtin_return_address(0)); + msg("reallocarray(%p, %li): %p", ptr, size, ret_addr); if (mode >= 4) { char buf[BUFFER_SIZE]; rcv(buf, sizeof(buf)); @@ -570,7 +593,7 @@ void *sym(reallocarray)(void *ptr, size_t nmemb, size_t size) { void sym(free)(void *ptr) { init(); - msg("free(%p): %p", ptr, __builtin_return_address(0)); + msg("free(%p): %p", ptr, ret_addr); if (mode >= 4) { char buf[BUFFER_SIZE]; rcv(buf, sizeof(buf)); @@ -584,7 +607,7 @@ void sym(free)(void *ptr) { int sym(getopt)(const int argc, char *const argv[], const char *shortopts) { init(); - msg("getopt(%i, %as, %es): %p", argc, argv, argc, shortopts, __builtin_return_address(0)); + msg("getopt(%i, %as, %es): %p", argc, argv, argc, shortopts, ret_addr); if (mode >= 4) { char buf[BUFFER_SIZE]; rcv(buf, sizeof(buf)); @@ -602,7 +625,7 @@ int sym(getopt)(const int argc, char *const argv[], const char *shortopts) { void sym(exit)(int status) { init(); - msg("exit(%i): %p", status, __builtin_return_address(0)); + msg("exit(%i): %p", status, ret_addr); if (mode >= 4) { char buf[BUFFER_SIZE]; rcv(buf, sizeof(buf)); @@ -614,7 +637,7 @@ void sym(exit)(int status) { int sym(close)(int fildes) { init(); - msg("close(%i): %p", fildes, __builtin_return_address(0)); + msg("close(%i): %p", fildes, ret_addr); if (mode >= 4) { char buf[BUFFER_SIZE]; rcv(buf, sizeof(buf)); @@ -685,9 +708,9 @@ int sym(sigaction)(int sig, const struct sigaction *restrict act, struct sigacti 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, __builtin_return_address(0)); + 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, __builtin_return_address(0)); + msg("sigaction(%i:%s, %p:{}, %p): %p", sig, sigstr, act, oact, ret_addr); } if (mode >= 4) { char buf[BUFFER_SIZE]; @@ -730,7 +753,7 @@ int sym(sigaction)(int sig, const struct sigaction *restrict act, struct sigacti int sym(sem_init)(sem_t *sem, int pshared, unsigned int value) { init(); - msg("sem_init(%p, %i, %u): %p", sem, pshared, value, __builtin_return_address(0)); + msg("sem_init(%p, %i, %u): %p", sem, pshared, value, ret_addr); if (mode >= 4) { char buf[BUFFER_SIZE]; rcv(buf, sizeof(buf)); @@ -759,9 +782,9 @@ sem_t *sym(sem_open)(const char *name, int oflag, ...) { mode_arg = va_arg(args, mode_t); value = va_arg(args, unsigned int); va_end(args); - msg("sem_open(%es, 0%o:%s, 0%03o, %u): %p", name, oflag, ostr, mode_arg, value, __builtin_return_address(0)); + msg("sem_open(%es, 0%o:%s, 0%03o, %u): %p", name, oflag, ostr, mode_arg, value, ret_addr); } else { - msg("sem_open(%es, 0%o:|%s): %p", name, oflag, ostr, __builtin_return_address(0)); + msg("sem_open(%es, 0%o:|%s): %p", name, oflag, ostr, ret_addr); } char overwrite[BUFFER_SIZE]; @@ -831,7 +854,7 @@ sem_t *sym(sem_open)(const char *name, int oflag, ...) { int sym(sem_post)(sem_t *sem) { init(); - msg("sem_post(%p): %p", sem, __builtin_return_address(0)); + msg("sem_post(%p): %p", sem, ret_addr); if (mode >= 4) { char buf[BUFFER_SIZE]; rcv(buf, sizeof(buf)); @@ -847,7 +870,7 @@ int sym(sem_post)(sem_t *sem) { int sym(sem_wait)(sem_t *sem) { init(); - msg("sem_wait(%p): %p", sem, __builtin_return_address(0)); + msg("sem_wait(%p): %p", sem, ret_addr); if (mode >= 4) { char buf[BUFFER_SIZE]; rcv(buf, sizeof(buf)); @@ -863,7 +886,7 @@ int sym(sem_wait)(sem_t *sem) { int sym(sem_trywait)(sem_t *sem) { init(); - msg("sem_trywait(%p): %p", sem, __builtin_return_address(0)); + msg("sem_trywait(%p): %p", sem, ret_addr); if (mode >= 4) { char buf[BUFFER_SIZE]; rcv(buf, sizeof(buf)); @@ -879,7 +902,7 @@ int sym(sem_trywait)(sem_t *sem) { int sym(sem_timedwait)(sem_t *restrict sem, const struct timespec *restrict abs_timeout) { init(); - msg("sem_timedwait(%p, %p:{tv_sec: %li, tv_nsec: %li}): %p", sem, abs_timeout, abs_timeout->tv_sec, abs_timeout->tv_nsec, __builtin_return_address(0)); + msg("sem_timedwait(%p, %p:{tv_sec: %li, tv_nsec: %li}): %p", sem, abs_timeout, abs_timeout->tv_sec, abs_timeout->tv_nsec, ret_addr); struct timespec overwrite; if (mode >= 4) { char buf[BUFFER_SIZE]; @@ -924,7 +947,7 @@ int sym(sem_timedwait)(sem_t *restrict sem, const struct timespec *restrict abs_ int sym(sem_getvalue)(sem_t *restrict sem, int *restrict value) { init(); - msg("sem_getvalue(%p, %p): %p", sem, value, __builtin_return_address(0)); + msg("sem_getvalue(%p, %p): %p", sem, value, ret_addr); if (mode >= 4) { char buf[BUFFER_SIZE]; rcv(buf, sizeof(buf)); @@ -944,7 +967,7 @@ int sym(sem_getvalue)(sem_t *restrict sem, int *restrict value) { int sym(sem_close)(sem_t *sem) { init(); - msg("sem_close(%p): %p", sem, __builtin_return_address(0)); + msg("sem_close(%p): %p", sem, ret_addr); if (mode >= 4) { char buf[BUFFER_SIZE]; rcv(buf, sizeof(buf)); @@ -960,7 +983,7 @@ int sym(sem_close)(sem_t *sem) { int sym(sem_unlink)(const char *name) { init(); - msg("sem_unlink(%es): %p", name, __builtin_return_address(0)); + msg("sem_unlink(%es): %p", name, ret_addr); char overwrite[BUFFER_SIZE]; if (mode >= 4) { char buf[BUFFER_SIZE]; @@ -991,7 +1014,7 @@ int sym(sem_unlink)(const char *name) { int sym(sem_destroy)(sem_t *sem) { init(); - msg("sem_destroy(%p): %p", sem, __builtin_return_address(0)); + msg("sem_destroy(%p): %p", sem, ret_addr); if (mode >= 4) { char buf[BUFFER_SIZE]; rcv(buf, sizeof(buf)); @@ -1004,3 +1027,110 @@ int sym(sem_destroy)(sem_t *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(); + char ostr[64] = "|"; + if (oflag & O_RDONLY) strcat(ostr, "O_RDONLY|"); + if (oflag & O_RDWR) strcat(ostr, "O_RDWR|"); + if (oflag & O_CREAT) strcat(ostr, "O_CREAT|"); + if (oflag & O_EXCL) strcat(ostr, "O_EXCL|"); + 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); + char overwrite[BUFFER_SIZE]; + if (mode >= 4) { + char buf[BUFFER_SIZE]; + rcv(buf, sizeof(buf)); + if (strncmp(buf, "modify ", 7) == 0) { + // modify ,, + char *val_1 = NULL, *end_ptr_1 = NULL, *end_ptr_2 = NULL, *end_ptr_3 = NULL; + long val_2 = 0, val_3 = 0; + if (buf[7] == '"') { + // modify "",... + val_1 = strtostr(buf + 7, &end_ptr_1, overwrite); + if (val_1 == NULL) end_ptr_1 = NULL; + } else { + // modify ,... + val_1 = (char *)strtol(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 != 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: shm_open: invalid args in modify command: '%s'\n", buf + 7); \ + } + } else if_return_int_errno(shm_open) + else if_error_7_int_errno(shm_open, EACCES, EEXIST, EINVAL, EMFILE, ENAMETOOLONG, ENFILE, ENOENT) + else if_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(); + msg("shm_unlink(%es): %p", name, ret_addr); + char overwrite[BUFFER_SIZE]; + if (mode >= 4) { + char buf[BUFFER_SIZE]; + rcv(buf, sizeof(buf)); + if (strncmp(buf, "modify ", 7) == 0) { + char *end_ptr = NULL, *val = NULL; + if (buf[7] == '"') { + // modify "" + val = strtostr(buf + 7, &end_ptr, overwrite); + if (val == NULL) end_ptr = NULL; + } else { + // modify + val = (char *)strtol(buf + 7, &end_ptr, 0); + } + 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); \ + } + } else if_return_int_errno(shm_unlink) + else if_error_3_int_errno(shm_unlink, EACCES, ENAMETOOLONG, ENOENT) + else if_invalid(shm_unlink) + } + const int ret = __real_shm_unlink(name); + msg("return %i; errno %s", ret, strerrorname_np(errno)); + return ret; +}