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.
This commit is contained in:
Vadim Yanitskiy 2018-10-31 19:18:41 +07:00
parent 0578d751b1
commit 04ac475170
3 changed files with 33 additions and 2 deletions

View File

@ -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,

26
utils.c
View File

@ -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)
{

View File

@ -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);