diff --git a/proj/intercept/intercept b/proj/intercept/intercept index cd76316..2f88813 100755 --- a/proj/intercept/intercept +++ b/proj/intercept/intercept @@ -10,6 +10,7 @@ import sys def main() -> None: parser = argparse.ArgumentParser() parser.add_argument('-F', '--functions') + parser.add_argument('-s', '--sparse', action='store_true') libs = parser.add_mutually_exclusive_group() libs.add_argument('-o', '--only-own', action='store_true') libs.add_argument('-L', '--libraries') @@ -31,6 +32,7 @@ def main() -> None: subprocess.run(extra, stdin=sys.stdin, env={ 'LD_PRELOAD': os.getcwd() + '/intercept.so', 'INTERCEPT': intercept, + 'INTERCEPT_VERBOSE': '0' if args.sparse else '1', 'INTERCEPT_FUNCTIONS': args.functions or '*', 'INTERCEPT_LIBRARIES': '*,-/lib*,-/usr/lib*' if args.only_own else args.libraries or '*', }) diff --git a/proj/intercept/src/intercept.c b/proj/intercept/src/intercept.c index b9c3679..bb45b3b 100644 --- a/proj/intercept/src/intercept.c +++ b/proj/intercept/src/intercept.c @@ -545,6 +545,7 @@ static char *strtostr(char *ptr, char **end_ptr, char *buf) { static int mode = 0; static int intercept = 0; +static int verbosity = 0; static uint8_t func_flags[256]; static uint8_t lib_flags[0x1000]; @@ -578,7 +579,7 @@ static size_t msg_bytes(char *buf, size_t maxlen, size_t len, const char *str, i } static size_t msg_str(char *buf, size_t maxlen, const char *str, int flags) { - return msg_bytes(buf, maxlen, strlen(str), str, flags); + return msg_bytes(buf, maxlen, str == NULL ? 0 : strlen(str), str, flags); } static size_t msg_array_str(char *buf, size_t maxlen, char *const array[], int n) { @@ -597,6 +598,35 @@ static size_t msg_array_str(char *buf, size_t maxlen, char *const array[], int n return offset; } +static size_t msg_sockaddr(char *buf, const size_t size, const struct sockaddr *addr, const socklen_t len) { + size_t offset = 0; + if (addr == NULL) { + offset += snprintf(buf + offset, size - offset, "%p:{}", (void *)addr); + } else 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, size - offset, "%p:{sa_family: %i:AF_UNIX, sun_Path: ", (void *)un, AF_UNIX); + offset += msg_str(buf + offset, size - offset, un->sun_path, 1); + offset += snprintf(buf + offset, size - 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, size - 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, size - 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, size - offset, "%p:{sa_family: %i:%s, sa_data: ", (void *)addr, addr->sa_family, getdomainstr(addr->sa_family)); + offset += msg_bytes(buf + offset, size - offset, len - sizeof(addr->sa_family), addr->sa_data, 1); + offset += snprintf(buf + offset, size - offset, "}"); + } + return offset; +} + static void msg(const char *fmt, ...) { if (!intercept || mode == -1) return; char buf[8192], sub_fmt[16]; @@ -640,11 +670,21 @@ static void msg(const char *fmt, ...) { } else if (state == 'e') { if (ch == 's') { // escaped string - offset += msg_str(buf + offset, sizeof(buf) - offset, va_arg(args, const char *), 0); + const char *str = va_arg(args, const char *); + if (!verbosity) { + offset += snprintf(buf + offset, sizeof(buf) - offset, "%p:\"\"", (void *)str); + } else { + offset += msg_str(buf + offset, sizeof(buf) - offset, str, 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); + const char *str = va_arg(args, const char *); + if (!verbosity) { + offset += snprintf(buf + offset, sizeof(buf) - offset, "%p:\"\"", (void *)str); + } else { + offset += msg_bytes(buf + offset, sizeof(buf) - offset, len, str, 0); + } } state = 0; } else if (state == 'q') { @@ -652,42 +692,54 @@ static void msg(const char *fmt, ...) { // 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); + if (!verbosity) { + offset += snprintf(buf + offset, sizeof(buf) - offset, "%p:{}", (void *)addr); } 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, "}"); + offset += msg_sockaddr(buf + offset, sizeof(buf) - offset, addr, len); } } 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); + if (!verbosity) { + offset += snprintf(buf + offset, sizeof(buf) - offset, "%p:{}", (void *)msg); + } else { + // TODO format 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); + if (!verbosity) { + offset += snprintf(buf + offset, sizeof(buf) - offset, "%p:{}", (void *)tv); + } else { + 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); + if (!verbosity) { + offset += snprintf(buf + offset, sizeof(buf) - offset, "%p:[]", (void *)ai); + } else { + offset += snprintf(buf + offset, sizeof(buf) - offset, "%p:[", (void *)ai); + for (; ai != NULL; ai = ai->ai_next) { + char fstr[256] = "|"; + flag_str(ai->ai_flags, AI_PASSIVE, fstr); + flag_str(ai->ai_flags, AI_CANONNAME, fstr); + flag_str(ai->ai_flags, AI_NUMERICHOST, fstr); + flag_str(ai->ai_flags, AI_V4MAPPED, fstr); + flag_str(ai->ai_flags, AI_ALL, fstr); + flag_str(ai->ai_flags, AI_ADDRCONFIG, fstr); + flag_str(ai->ai_flags, AI_CANONIDN, fstr); + flag_str(ai->ai_flags, AI_NUMERICSERV, fstr); + if (ai->ai_flags & ~(AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST | AI_V4MAPPED | AI_ALL | AI_ADDRCONFIG | AI_CANONIDN | AI_NUMERICSERV)) strcat(fstr, "?|"); + offset += snprintf(buf + offset, sizeof(buf) - offset, "{ai_flags: 0x%x:%s, ai_family: %i:%s, ai_socktype: %i:%s, ai_protocol: %i, ai_addrlen: %i, ai_addr: ", ai->ai_flags, fstr, ai->ai_family, getdomainstr(ai->ai_family), ai->ai_socktype, getsocktype(ai->ai_socktype), ai->ai_protocol, ai->ai_addrlen); + offset += msg_sockaddr(buf + offset, sizeof(buf) - offset, ai->ai_addr, ai->ai_addrlen); + offset += snprintf(buf + offset, sizeof(buf) - offset, ", ai_canonname: "); + offset += msg_str(buf + offset, sizeof(buf) - offset, ai->ai_canonname, 0); + offset += snprintf(buf + offset, sizeof(buf) - offset, ", ai_next: %p}%s", (void *)ai->ai_next, ai->ai_next ? ", " : ""); + } + offset += snprintf(buf + offset, sizeof(buf) - offset, "]"); + } } else { // error va_end(args); @@ -699,7 +751,11 @@ static void msg(const char *fmt, ...) { // 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); + if (!verbosity) { + offset += snprintf(buf + offset, sizeof(buf) - offset, "%p:[]", (void *)array); + } else { + offset += msg_array_str(buf + offset, sizeof(buf) - offset, array, len); + } } else { // error va_end(args); @@ -842,6 +898,13 @@ static void init(void) { fprintf(stderr, "intercept: not logging or manipulating function/system calls\n"); } + char *verbose = getenv("INTERCEPT_VERBOSE"); + if (!verbose || verbose[0] == 0 || strcmp(verbose, "0") == 0) { + verbosity = 0; + } else { + verbosity = 1; + } + char *fncts = getenv("INTERCEPT_FUNCTIONS"); if (!fncts) { memset(func_flags, 1, sizeof(func_flags)); @@ -1195,7 +1258,11 @@ 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)" ret_str, sig, sigstr, act, act->sa_flags, flgstr, name, ptr, maskstr, oact, ret_data); + if (!verbosity) { + msg("sigaction(%i:%s, %p:{}, %p)" ret_str, sig, sigstr, act, oact, ret_addr); + } else { + msg("sigaction(%i:%s, %p:{sa_flags: 0x%x:%s, %s: %p, sa_mask: [%s]}, %p)" ret_str, sig, sigstr, act, act->sa_flags, flgstr, name, ptr, maskstr, oact, ret_data); + } } else { msg("sigaction(%i:%s, %p:{}, %p): %p", sig, sigstr, act, oact, ret_addr); } @@ -2226,9 +2293,9 @@ int sym(getaddrinfo)(const char *restrict node, const char *restrict service, co } const int ret = __real_getaddrinfo(node, service, hints, res); if (res != NULL) { - msg("return %i; errno %s; res=%p", ret, strerrorname_np(errno), *res); + msg("return %i; errno %s; res=%qi", ret, strerrorname_np(errno), *res); } else { - msg("return %i; errno %s", ret, strerrorname_np(errno), *res); + msg("return %i; errno %s", ret, strerrorname_np(errno)); } return ret; } @@ -2262,7 +2329,7 @@ ssize_t sym(send)(int sockfd, const void *buf, size_t length, int flags) { 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, "?|"); + if (flags & ~(MSG_CONFIRM | MSG_DONTROUTE | MSG_DONTWAIT | MSG_EOR | MSG_MORE | MSG_NOSIGNAL | MSG_OOB | MSG_FASTOPEN)) strcat(fstr, "?|"); msg("send(%i, %eb, %i, 0x%x:%s)" ret_str, sockfd, length, buf, length, flags, fstr, ret_data); if (mode >= 4) { @@ -2293,7 +2360,7 @@ ssize_t sym(sendto)(int sockfd, const void *buf, size_t size, int flags, const s 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, "?|"); + if (flags & ~(MSG_CONFIRM | MSG_DONTROUTE | MSG_DONTWAIT | MSG_EOR | MSG_MORE | MSG_NOSIGNAL | MSG_OOB | MSG_FASTOPEN)) strcat(fstr, "?|"); msg("sendto(%i, %eb, %i, 0x%x:%s, %qa, %i)" ret_str, sockfd, size, buf, size, flags, fstr, addrlen, dest_addr, addrlen, ret_data); if (mode >= 4) { @@ -2324,7 +2391,7 @@ ssize_t sym(sendmsg)(int sockfd, const struct msghdr *message, int flags) { 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, "?|"); + if (flags & ~(MSG_CONFIRM | MSG_DONTROUTE | MSG_DONTWAIT | MSG_EOR | MSG_MORE | MSG_NOSIGNAL | MSG_OOB | MSG_FASTOPEN)) strcat(fstr, "?|"); msg("sendmsg(%i, %qm, 0x%x:%s)" ret_str, sockfd, message, flags, fstr, ret_data); if (mode >= 4) { diff --git a/proj/server/src/intercept/__init__.py b/proj/server/src/intercept/__init__.py index 9835259..88ed488 100644 --- a/proj/server/src/intercept/__init__.py +++ b/proj/server/src/intercept/__init__.py @@ -17,7 +17,9 @@ StructSockAddr = TypedDict('StructSockAddr', {'sa_family': Constant, 'sa_data': 'sun_path': NotRequired[bytes], 'sin_addr': NotRequired[bytes], 'sin_port': NotRequired[int], 'sin6_addr': NotRequired[bytes], 'sin6_port': NotRequired[int], 'sin6_scope_id': NotRequired[int]}) -StructAddrInfo = TypedDict('StructAddrInfo', {}) +StructAddrInfo = TypedDict('StructAddrInfo', {'ai_flags': Flags, 'ai_family': Constant, 'ai_socktype': Constant, 'ai_protocol': int, 'ai_addrlen': int, + 'ai_addr': PointerTo[StructSockAddr], + 'ai_canonname': PointerTo[bytes], 'ai_next': Pointer}) StructMsgHdr = TypedDict('StructMsgHdr', {}) @@ -481,10 +483,10 @@ class Handler(StreamRequestHandler): def after_connect(self, sockfd: int, address: PointerTo[StructSockAddr], address_len: int, ret_value: int, errno: str = None) -> None: raise NotImplementedError() - def before_getaddrinfo(self, node: PointerTo[bytes], service: PointerTo[bytes], hints: PointerTo[StructAddrInfo], res_ptr: Pointer) -> str: + def before_getaddrinfo(self, node: PointerTo[bytes], service: PointerTo[bytes], hints: PointerTo[list[StructAddrInfo]], res_ptr: Pointer) -> str: raise NotImplementedError() - def after_getaddrinfo(self, node: PointerTo[bytes], service: PointerTo[bytes], hints: PointerTo[StructAddrInfo], res_ptr: Pointer, - ret_value: int, errno: str = None, res: Pointer = None) -> None: + def after_getaddrinfo(self, node: PointerTo[bytes], service: PointerTo[bytes], hints: PointerTo[list[StructAddrInfo]], res_ptr: Pointer, + ret_value: int, errno: str = None, res: PointerTo[list[StructAddrInfo]] = None) -> None: raise NotImplementedError() def before_freeaddrinfo(self, res: Pointer) -> str: raise NotImplementedError() diff --git a/proj/server/src/test-interrupts b/proj/server/src/test-interrupts index 2d1410e..7be8d01 100755 --- a/proj/server/src/test-interrupts +++ b/proj/server/src/test-interrupts @@ -24,6 +24,7 @@ def main() -> None: subprocess.run(extra, env={ 'LD_PRELOAD': os.getcwd() + '/../../intercept/intercept.so', 'INTERCEPT': 'unix:' + socket_name, + 'INTERCEPT_VERBOSE': '1', 'INTERCEPT_FUNCTIONS': '*', 'INTERCEPT_LIBRARIES': '*,-/lib*,-/usr/lib*', }) diff --git a/proj/server/src/test-memory b/proj/server/src/test-memory index 5739fcc..893a5ad 100755 --- a/proj/server/src/test-memory +++ b/proj/server/src/test-memory @@ -24,6 +24,7 @@ def main() -> None: subprocess.run(extra, env={ 'LD_PRELOAD': os.getcwd() + '/../../intercept/intercept.so', 'INTERCEPT': 'unix:' + socket_name, + 'INTERCEPT_VERBOSE': '1', 'INTERCEPT_FUNCTIONS': ','.join(['malloc', 'calloc', 'realloc', 'reallocarray', 'free', 'getaddrinfo', 'freeaddrinfo']), 'INTERCEPT_LIBRARIES': '*,-/lib*,-/usr/lib*', }) diff --git a/proj/server/src/test-return-values b/proj/server/src/test-return-values index 025d5f4..6dfbe60 100755 --- a/proj/server/src/test-return-values +++ b/proj/server/src/test-return-values @@ -35,6 +35,7 @@ def main() -> None: subprocess.run(extra, stdin=stdin, env={ 'LD_PRELOAD': os.getcwd() + '/../../intercept/intercept.so', 'INTERCEPT': 'unix:' + socket_name, + 'INTERCEPT_VERBOSE': '1', 'INTERCEPT_FUNCTIONS': '*', 'INTERCEPT_LIBRARIES': '*,-/lib*,-/usr/lib*', })