From 4bbf70b9f367afab929cb6c2f214475ee09b2403 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 26 Mar 2018 16:46:52 +0200 Subject: initial checkin of unix domain socket tracer --- libc_overrides.c | 220 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 220 insertions(+) create mode 100644 libc_overrides.c (limited to 'libc_overrides.c') diff --git a/libc_overrides.c b/libc_overrides.c new file mode 100644 index 0000000..d0d2c6a --- /dev/null +++ b/libc_overrides.c @@ -0,0 +1,220 @@ +/* + * (C) 2018 by Harald Welte + * based on modified code from tcpsnitch + * (C) 2016 by Gregory Vander Schueren + */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sock_events.h" +#include "utils.h" + +#define EXPORT __attribute__((visibility("default"))) +#define LIBC_VERSION (__GLIBC__ * 100 + __GLIBC_MINOR__) + +#define arg2 a +#define arg3 arg2, b +#define arg4 arg3, c +#define arg5 arg4, d +#define arg6 arg5, e + +#define override(FUNCTION, RETURN_TYPE, ARGS_COUNT, ...) \ + typedef RETURN_TYPE (*FUNCTION##_type)(int fd, __VA_ARGS__); \ + FUNCTION##_type orig_##FUNCTION; \ + \ + EXPORT RETURN_TYPE FUNCTION(int fd, __VA_ARGS__) { \ + if (!orig_##FUNCTION) \ + orig_##FUNCTION = \ + (FUNCTION##_type)dlsym(RTLD_NEXT, #FUNCTION); \ + RETURN_TYPE ret = orig_##FUNCTION(fd, arg##ARGS_COUNT); \ + int err = errno; \ + if (is_unix_socket(fd)) \ + sock_ev_##FUNCTION(fd, ret, err, arg##ARGS_COUNT); \ + errno = err; \ + return ret; \ + } + +#define override_1arg(FUNCTION, RETURN_TYPE) \ + typedef RETURN_TYPE (*FUNCTION##_type)(int fd); \ + FUNCTION##_type orig_##FUNCTION; \ + \ + EXPORT RETURN_TYPE FUNCTION(int fd) { \ + if (!orig_##FUNCTION) \ + orig_##FUNCTION = \ + (FUNCTION##_type)dlsym(RTLD_NEXT, #FUNCTION); \ + RETURN_TYPE ret = orig_##FUNCTION(fd); \ + int err = errno; \ + if (is_unix_socket(fd)) sock_ev_##FUNCTION(fd, ret, err); \ + errno = err; \ + return ret; \ + } + +/* + Use "standard" font here to generate ASCII arts: + http://patorjk.com/software/taag/#p=display&f=Standard +*/ + +/* + ____ ___ ____ _ _______ _____ _ ____ ___ + / ___| / _ \ / ___| |/ / ____|_ _| / \ | _ \_ _| + \___ \| | | | | | ' /| _| | | / _ \ | |_) | | + ___) | |_| | |___| . \| |___ | | / ___ \| __/| | + |____/ \___/ \____|_|\_\_____| |_| /_/ \_\_| |___| + + sys/socket.h - Internet Protocol family + + functions: socket(), bind(), connect(), listen(), accept(), + accept4(), send(), recv(), sendto(), recvfrom(), sendmsg(), + recvmsg(), sendmmsg(), recvmmsg(), + +*/ + +typedef int (*socket_type)(int domain, int type, int protocol); +socket_type orig_socket; + +EXPORT int socket(int domain, int type, int protocol) { + if (!orig_socket) orig_socket = (socket_type)dlsym(RTLD_NEXT, "socket"); + int fd = orig_socket(domain, type, protocol); + sock_ev_socket(fd, domain, type, protocol); + return fd; +} + +typedef int (*connect_type)(int fd, const struct sockaddr *addr, socklen_t len); +connect_type orig_connect; + +EXPORT int connect(int fd, const struct sockaddr *addr, socklen_t len) { + if (!orig_connect) + orig_connect = (connect_type)dlsym(RTLD_NEXT, "connect"); + + int ret = orig_connect(fd, addr, len); + int err = errno; + if (is_unix_socket(fd)) sock_ev_connect(fd, ret, err, addr, len); + + errno = err; + return ret; +} + +override(bind, int, 3, const struct sockaddr *a, socklen_t b); +override(listen, int, 2, int a); +override(accept, int, 3, struct sockaddr *a, socklen_t *b); +override(accept4, int, 4, struct sockaddr *a, socklen_t *b, int c); + +#if defined(__ANDROID__) && __ANDROID_API__ <= 19 +override(send, ssize_t, 4, const void *a, size_t b, unsigned int c); +override(recv, ssize_t, 4, void *a, size_t b, unsigned int c); +#else +override(send, ssize_t, 4, const void *a, size_t b, int c); +override(recv, ssize_t, 4, void *a, size_t b, int c); +#endif + +override(sendto, ssize_t, 6, const void *a, size_t b, int c, + const struct sockaddr *d, socklen_t e); +#if defined(__ANDROID__) && __ANDROID_API__ <= 19 +override(recvfrom, ssize_t, 6, void *a, size_t b, unsigned int c, + const struct sockaddr *d, socklen_t *e); +#elif defined(__ANDROID__) +override(recvfrom, ssize_t, 6, void *a, size_t b, int c, + const struct sockaddr *d, socklen_t *e); +#else +override(recvfrom, ssize_t, 6, void *a, size_t b, int c, struct sockaddr *d, + socklen_t *e); +#endif + +#if defined(__ANDROID__) && __ANDROID_API__ <= 19 +override(sendmsg, ssize_t, 3, const struct msghdr *a, unsigned int b); +override(recvmsg, ssize_t, 3, struct msghdr *a, unsigned int b); +#else +override(sendmsg, ssize_t, 3, const struct msghdr *a, int b); +override(recvmsg, ssize_t, 3, struct msghdr *a, int b); +#endif + +#if defined(__ANDROID__) && __ANDROID_API__ >= 21 +override(sendmmsg, int, 4, const struct mmsghdr *a, unsigned int b, int c); +override(recvmmsg, int, 5, struct mmsghdr *a, unsigned int b, int c, + const struct timespec *d); +#elif LIBC_VERSION > 219 // Absolutely not sure this is the right boundary! +override(sendmmsg, int, 4, struct mmsghdr *a, unsigned int b, int c); +override(recvmmsg, int, 5, struct mmsghdr *a, unsigned int b, int c, + struct timespec *d); +#else +override(sendmmsg, int, 4, struct mmsghdr *a, unsigned int b, int c); +override(recvmmsg, int, 5, struct mmsghdr *a, unsigned int b, int c, + const struct timespec *d); +#endif + +/* + _ _ _ _ ___ ____ _____ ____ _ ____ ___ + | | | | \ | |_ _/ ___|_ _| _ \ / \ | _ \_ _| + | | | | \| || |\___ \ | | | | | | / _ \ | |_) | | + | |_| | |\ || | ___) || | | |_| | / ___ \| __/| | + \___/|_| \_|___|____/ |_| |____/ /_/ \_\_| |___| + + unistd.h - standard symbolic constants and types + + functions: write(), read(), close(), fork(), dup(), dup2(), dup3() + +*/ + +override(write, ssize_t, 3, const void *a, size_t b); +override(read, ssize_t, 3, void *a, size_t b); + +typedef int (*close_type)(int fd); +close_type orig_close; + +EXPORT int close(int fd) { + if (!orig_close) orig_close = (close_type)dlsym(RTLD_NEXT, "close"); + + bool is_unix = is_unix_socket(fd); + int ret = orig_close(fd); + int err = errno; + if (is_unix) sock_ev_close(fd, ret, err); + + errno = err; + return ret; +} + +override_1arg(dup, int); +override(dup2, int, 2, int a); +override(dup3, int, 3, int a, int b); + +/* + _ _ _ _____ _ ____ ___ + | | | |_ _/ _ \ / \ | _ \_ _| + | | | || | | | | / _ \ | |_) | | + | |_| || | |_| | / ___ \| __/| | + \___/|___\___/ /_/ \_\_| |___| + + sys/uio.h - definitions for vector I/O operations + + functions: writev(), readv() + +*/ + +override(writev, ssize_t, 3, const struct iovec *a, int b); +override(readv, ssize_t, 3, const struct iovec *a, int b); + +/* + ____ _____ _ _ ____ _____ ___ _ _____ _ ____ ___ + / ___|| ____| \ | | _ \| ___|_ _| | | ____| / \ | _ \_ _| + \___ \| _| | \| | | | | |_ | || | | _| / _ \ | |_) | | + ___) | |___| |\ | |_| | _| | || |___| |___ / ___ \| __/| | + |____/|_____|_| \_|____/|_| |___|_____|_____| /_/ \_\_| |___| + + sendfile.h - transfer data between file descriptors + + functions: sendfile() +*/ + +override(sendfile, ssize_t, 4, int a, off_t *b, size_t c); -- cgit v1.2.3