From 642b9e483b99e483bd5b3bdb44e14391226ee920 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Wed, 31 Oct 2018 19:05:37 +0700 Subject: utils.c: drop 'const' qualifier from udtrace_sstate_by_fd() --- utils.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils.c b/utils.c index 4b653f2..ad008e7 100644 --- a/utils.c +++ b/utils.c @@ -133,7 +133,7 @@ void udtrace_fd_set_path(int fd, const char *path) } } -const struct sock_state *udtrace_sstate_by_fd(int fd) +struct sock_state *udtrace_sstate_by_fd(int fd) { int i; for (i = 0; i < ARRAY_SIZE(unix_fds); i++) { @@ -154,7 +154,7 @@ bool is_unix_socket(int fd) void udtrace_data(int fd, bool is_out, const char *fn, const uint8_t *data, unsigned int len) { - const struct sock_state *ss = udtrace_sstate_by_fd(fd); + struct sock_state *ss = udtrace_sstate_by_fd(fd); if (!data || !len || !ss) return; ss->dissector(fd, is_out, fn, data, len); -- cgit v1.2.3 From 6424fba52d31b51a7875114c9a8906266810e56e Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Wed, 31 Oct 2018 19:06:30 +0700 Subject: utils.c: use udtrace_sstate_by_fd() --- utils.c | 55 +++++++++++++++++++++++++++++++------------------------ utils.h | 3 +++ 2 files changed, 34 insertions(+), 24 deletions(-) diff --git a/utils.c b/utils.c index ad008e7..bf9b935 100644 --- a/utils.c +++ b/utils.c @@ -80,30 +80,34 @@ __attribute__ ((constructor)) static void udtrace_init(void) /* add a file descriptor from the list of to-be-traced ones */ void udtrace_add_fd(int fd) { - int i; - for (i = 0; i < ARRAY_SIZE(unix_fds); i++) { - if (unix_fds[i].fd == -1) { - LOG("Adding FD %d\n", fd); - unix_fds[i].fd = fd; - return; - } + struct sock_state *ss; + + /* Find an unused state in unix_fds */ + ss = udtrace_sstate_by_fd(-1); + if (!ss) { + LOG("Couldn't add UNIX FD %d (no space in unix_fds)\n", fd); + return; } - LOG("Couldn't add UNIX FD %d (no space in unix_fds)\n", fd); + + LOG("Adding FD %d\n", fd); + ss->fd = fd; } /* delete a file descriptor from the list of to-be-traced ones */ void udtrace_del_fd(int fd) { - int i; - for (i = 0; i < ARRAY_SIZE(unix_fds); i++) { - if (unix_fds[i].fd == fd) { - LOG("Removing FD %d\n", fd); - free((void *) unix_fds[i].path); - unix_fds[i] = (struct sock_state) { -1, NULL, NULL }; - return; - } + struct sock_state *ss; + + /* Find the corresponding state in unix_fds */ + ss = udtrace_sstate_by_fd(fd); + if (!ss) { + LOG("Couldn't delete UNIX FD %d (no such FD in unix_fds)\n", fd); + return; } - LOG("Couldn't delete UNIX FD %d (no such FD)\n", fd); + + LOG("Removing FD %d\n", fd); + free((void *) ss->path); + *ss = (struct sock_state) { -1, NULL, NULL }; } static void udtrace_resolve_dissector(struct sock_state *ss) @@ -123,14 +127,17 @@ static void udtrace_resolve_dissector(struct sock_state *ss) /* set the path of a given fd */ void udtrace_fd_set_path(int fd, const char *path) { - int i; - for (i = 0; i < ARRAY_SIZE(unix_fds); i++) { - if (unix_fds[i].fd == fd) { - unix_fds[i].path = strdup(path); - udtrace_resolve_dissector(&unix_fds[i]); - return; - } + struct sock_state *ss; + + /* Find the corresponding state in unix_fds */ + ss = udtrace_sstate_by_fd(fd); + if (!ss) { + LOG("Couldn't set path for UNIX FD %d (no such FD in unix_fds)\n", fd); + return; } + + ss->path = strdup(path); + udtrace_resolve_dissector(ss); } struct sock_state *udtrace_sstate_by_fd(int fd) diff --git a/utils.h b/utils.h index f1f52f4..8ac4859 100644 --- a/utils.h +++ b/utils.h @@ -6,6 +6,9 @@ #define LOG(fmt, args ...) \ fprintf(stderr, ">>> UDTRACE: " fmt, ## args) +/* find the state corresponding to a given file descriptor */ +struct sock_state *udtrace_sstate_by_fd(int fd); + /* add a file descriptor from the list of to-be-traced ones */ void udtrace_add_fd(int fd); -- cgit v1.2.3 From 0578d751b1ea0ac10ad2b033f9b73c922f120fdb Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Wed, 31 Oct 2018 19:14:20 +0700 Subject: utils.h: share 'sock_state' struct from 'utils.c' --- utils.c | 8 -------- utils.h | 9 +++++++++ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/utils.c b/utils.c index bf9b935..f188205 100644 --- a/utils.c +++ b/utils.c @@ -47,19 +47,11 @@ static char *hexdump(const unsigned char *buf, int len, char *delim) return hexd_buff; } -typedef void (*udtrace_dissector)(int fd, bool is_out, const char *fn, const uint8_t *data, unsigned int len); - static void default_dissector(int fd, bool is_out, const char *fn, const uint8_t *data, unsigned int len) { fprintf(stderr, "%d %s %c %s\n", fd, fn, is_out ? 'W' : 'R', hexdump(data, len, "")); } -struct sock_state { - int fd; - const char *path; - udtrace_dissector dissector; -}; - static struct sock_state unix_fds[MAX_UNIX_FDS]; __attribute__ ((constructor)) static void udtrace_init(void) diff --git a/utils.h b/utils.h index 8ac4859..8145c9b 100644 --- a/utils.h +++ b/utils.h @@ -6,6 +6,15 @@ #define LOG(fmt, args ...) \ fprintf(stderr, ">>> UDTRACE: " fmt, ## args) +typedef void (*udtrace_dissector)(int fd, bool is_out, const char *fn, + const uint8_t *data, unsigned int len); + +struct sock_state { + int fd; + const char *path; + udtrace_dissector dissector; +}; + /* find the state corresponding to a given file descriptor */ struct sock_state *udtrace_sstate_by_fd(int fd); -- cgit v1.2.3 From 04ac4751701a28b7bec0c812a98d8a7ca1008a69 Mon Sep 17 00:00:00 2001 From: Vadim Yanitskiy Date: Wed, 31 Oct 2018 19:18:41 +0700 Subject: sock_events.c: also track child file descriptors In some applications, such as OsmocomBB, a single UNIX socket can be used by multiple processes (i.e. a server and multiple clients). Previously this caused a segmentation fault. Let's modify both sock_ev_accept() and sock_ev_accept4() in order to handle such connections properly, by using both socket path and dissector from the parent. --- sock_events.c | 6 ++++-- utils.c | 26 ++++++++++++++++++++++++++ utils.h | 3 +++ 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/sock_events.c b/sock_events.c index 9340d7d..a2b4108 100644 --- a/sock_events.c +++ b/sock_events.c @@ -85,7 +85,8 @@ void sock_ev_accept(int fd, int ret, int err, struct sockaddr *addr, { if (ret < 0) return; - udtrace_add_fd(ret); + LOG("accept(fd=%d on parent fd=%d)\n", ret, fd); + udtrace_add_fd_child(fd, ret); } void sock_ev_accept4(int fd, int ret, int err, struct sockaddr *addr, @@ -93,7 +94,8 @@ void sock_ev_accept4(int fd, int ret, int err, struct sockaddr *addr, { if (ret < 0) return; - udtrace_add_fd(ret); + LOG("accept(fd=%d on parent fd=%d)\n", ret, fd); + udtrace_add_fd_child(fd, ret); } void sock_ev_send(int fd, int ret, int err, const void *buf, size_t bytes, diff --git a/utils.c b/utils.c index f188205..e1b0d7d 100644 --- a/utils.c +++ b/utils.c @@ -85,6 +85,32 @@ void udtrace_add_fd(int fd) ss->fd = fd; } +/* add a file descriptor from the list of to-be-traced ones */ +void udtrace_add_fd_child(int pfd, int cfd) +{ + struct sock_state *pss, *css; + + /* Find the parent socket state first */ + pss = udtrace_sstate_by_fd(pfd); + if (!pss) { + LOG("Couldn't find parent UNIX FD %d for %d\n", pfd, cfd); + return; + } + + /* Find an unused state in unix_fds */ + css = udtrace_sstate_by_fd(-1); + if (!css) { + LOG("Couldn't add UNIX FD %d (no space in unix_fds)\n", cfd); + return; + } + + LOG("Adding FD %d as a child of %d\n", cfd, pfd); + + css->dissector = pss->dissector; + css->path = strdup(pss->path); + css->fd = cfd; +} + /* delete a file descriptor from the list of to-be-traced ones */ void udtrace_del_fd(int fd) { diff --git a/utils.h b/utils.h index 8145c9b..6829ffe 100644 --- a/utils.h +++ b/utils.h @@ -21,6 +21,9 @@ struct sock_state *udtrace_sstate_by_fd(int fd); /* add a file descriptor from the list of to-be-traced ones */ void udtrace_add_fd(int fd); +/* add a file descriptor from the list of to-be-traced ones */ +void udtrace_add_fd_child(int pfd, int cfd); + /* delete a file descriptor from the list of to-be-traced ones */ void udtrace_del_fd(int fd); -- cgit v1.2.3