summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorrobert <robert@FreeBSD.org>2003-07-17 23:49:10 +0000
committerrobert <robert@FreeBSD.org>2003-07-17 23:49:10 +0000
commitab57004058eee4b698f7d9cece99440ad9b49bbb (patch)
treeaf5c6b63b4afd1e633ebf9934eefff4ed33989da /sys
parent242d14a38d959afc315ff9143d62e22fe10d7176 (diff)
downloadFreeBSD-src-ab57004058eee4b698f7d9cece99440ad9b49bbb.zip
FreeBSD-src-ab57004058eee4b698f7d9cece99440ad9b49bbb.tar.gz
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
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/uipc_socket.c8
-rw-r--r--sys/sys/socketvar.h1
2 files changed, 8 insertions, 1 deletions
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index f1376f3..0c85717 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 e5f8756..223ccc2 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 */
OpenPOWER on IntegriCloud