From 4e19fe1081352c45aa6de13e465e729feab8613c Mon Sep 17 00:00:00 2001 From: Robert Drehmel Date: Thu, 17 Jul 2003 23:49:10 +0000 Subject: [PATCH] To avoid a kernel panic provoked by a NULL pointer dereference, do not clear the `sb_sel' member of the sockbuf structure while invalidating the receive sockbuf in sorflush(), called from soshutdown(). The panic was reproduceable from user land by attaching a knote with EVFILT_READ filters to a socket, disabling further reads from it using shutdown(2), and then closing it. knote_remove() was called to remove all knotes from the socket file descriptor by detaching each using its associated filterops' detach call- back function, sordetach() in this case, which tried to remove itself from the invalidated sockbuf's klist (sb_sel.si_note). PR: kern/54331 --- sys/kern/uipc_socket.c | 8 +++++++- sys/sys/socketvar.h | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index f1376f373bf..0c857173501 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -1133,8 +1133,14 @@ sorflush(so) socantrcvmore(so); sbunlock(sb); asb = *sb; - bzero(sb, sizeof (*sb)); + /* + * Invalidate/clear most of the sockbuf structure, but keep + * its selinfo structure valid. + */ + bzero(&sb->sb_startzero, + sizeof(*sb) - offsetof(struct sockbuf, sb_startzero)); splx(s); + if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose) (*pr->pr_domain->dom_dispose)(asb.sb_mb); sbrelease(&asb, so); diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h index e5f875686b8..223ccc2b2be 100644 --- a/sys/sys/socketvar.h +++ b/sys/sys/socketvar.h @@ -100,6 +100,7 @@ struct socket { */ struct sockbuf { struct selinfo sb_sel; /* process selecting read/write */ +#define sb_startzero sb_mb struct mbuf *sb_mb; /* the mbuf chain */ u_int sb_cc; /* actual chars in buffer */ u_int sb_hiwat; /* max actual char count */