git: 9d9fa9a2c22f - main - unix: Fix handling of listening sockets during garbage collection
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 14 Nov 2025 00:46:15 UTC
The branch main has been updated by markj:
URL: https://cgit.FreeBSD.org/src/commit/?id=9d9fa9a2c22f67d5f8afec18106c9f0072d6b3d4
commit 9d9fa9a2c22f67d5f8afec18106c9f0072d6b3d4
Author: Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2025-11-13 22:56:15 +0000
Commit: Mark Johnston <markj@FreeBSD.org>
CommitDate: 2025-11-14 00:43:38 +0000
unix: Fix handling of listening sockets during garbage collection
socantrcvmore() and unp_dispose() assume that the socket's socket
buffers are initialized, which isn't the case for listening sockets.
Reported by: syzbot+a62883292a5c257703be@syzkaller.appspotmail.com
MFC after: 1 week
Reviewed by: glebius
Differential Revision: https://reviews.freebsd.org/D53743
---
sys/kern/uipc_usrreq.c | 10 ++++++----
tests/sys/kern/unix_passfd_test.c | 29 +++++++++++++++++++++++++++++
2 files changed, 35 insertions(+), 4 deletions(-)
diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c
index 807271488af2..8c9fa4c012e4 100644
--- a/sys/kern/uipc_usrreq.c
+++ b/sys/kern/uipc_usrreq.c
@@ -4208,10 +4208,12 @@ unp_gc(__unused void *arg, int pending)
struct socket *so;
so = unref[i]->f_data;
- CURVNET_SET(so->so_vnet);
- socantrcvmore(so);
- unp_dispose(so);
- CURVNET_RESTORE();
+ if (!SOLISTENING(so)) {
+ CURVNET_SET(so->so_vnet);
+ socantrcvmore(so);
+ unp_dispose(so);
+ CURVNET_RESTORE();
+ }
}
/*
diff --git a/tests/sys/kern/unix_passfd_test.c b/tests/sys/kern/unix_passfd_test.c
index 7dc4541ad402..66bb406ea14e 100644
--- a/tests/sys/kern/unix_passfd_test.c
+++ b/tests/sys/kern/unix_passfd_test.c
@@ -1189,6 +1189,34 @@ ATF_TC_CLEANUP(cross_jail_dirfd, tc)
err(1, "jail_remove");
}
+ATF_TC_WITHOUT_HEAD(listening_socket);
+ATF_TC_BODY(listening_socket, tc)
+{
+ struct sockaddr_un sun;
+ int error, ls, s[2];
+
+ ls = socket(AF_UNIX, SOCK_STREAM, 0);
+ ATF_REQUIRE(ls != -1);
+
+ memset(&sun, 0, sizeof(sun));
+ sun.sun_len = sizeof(sun);
+ sun.sun_family = AF_UNIX;
+ snprintf(sun.sun_path, sizeof(sun.sun_path), "listen.sock");
+ error = bind(ls, (struct sockaddr *)&sun, sizeof(sun));
+ ATF_REQUIRE_MSG(error == 0, "bind failed: %s", strerror(errno));
+ error = listen(ls, 0);
+
+ error = socketpair(AF_UNIX, SOCK_STREAM, 0, s);
+ ATF_REQUIRE_MSG(error == 0, "socketpair failed: %s", strerror(errno));
+
+ sendfd(s[0], ls);
+ sendfd(s[0], s[0]);
+ sendfd(s[0], s[1]);
+ close(ls);
+ close(s[0]);
+ close(s[1]);
+}
+
ATF_TP_ADD_TCS(tp)
{
@@ -1211,6 +1239,7 @@ ATF_TP_ADD_TCS(tp)
ATF_TP_ADD_TC(tp, empty_rights_message);
ATF_TP_ADD_TC(tp, control_creates_records);
ATF_TP_ADD_TC(tp, cross_jail_dirfd);
+ ATF_TP_ADD_TC(tp, listening_socket);
return (atf_no_error());
}