Since at least 2.4.21-ac4 there is a bug that causes a leak of socket descriptors when unix domain sockets are poll()ed. The dgram_poll() function in af_unix.c retrieves the peer socket with unix_get_peer(). There the peer socket is sock_hold()ed but never released. The attached patches adds a sock_put() at the end of dgram_poll() to fix this. I have also attached a test code to trigger the bug. Is causes the "sock" entry in /proc/slabinfo to increase by one if the bug is present.
Greetings, Wilfried -- ___________________________________ Mr Wilfried Weissmann System Engineer phion Information Technologies GmbH Eduard-Bodem-Gasse 1 A-6020 Innsbruck http://www.phion.com tel: +43 512 39 45 45 fax: +43 512 39 45 45 20
--- linux-2.4.21/net/unix/af_unix.c Tue Aug 19 12:33:22 2003 +++ linux-2.4.21/net/unix/af_unix.c.new Wed Aug 20 01:21:24 2003 @@ -1737,6 +1737,8 @@ static unsigned int dgram_poll(struct fi else set_bit(SOCK_ASYNC_NOSPACE, &sk->socket->flags); + if (other) sock_put(other); + return mask; }
#include <sys/types.h> #include <sys/socket.h> #include <sys/un.h> #include <sys/poll.h> #include <string.h> #include <stdio.h> #define STRING "hallo\n" int main(void) { int sock[2]; struct pollfd ufdp = { .events=POLLIN|POLLPRI|POLLERR|POLLHUP, .revents=0, }; if(socketpair(PF_UNIX, SOCK_DGRAM, 0, sock)) goto oops; if(write(sock[0], STRING, strlen(STRING)) < 0) goto oops; ufdp.fd=sock[1]; if(poll(&ufdp, 1, -1) > 0) { printf("Test completed.\n"); } else { oops: printf("Oops, that's no good news at all!\n"); return 1; } return 0; }