Module Name:    src
Committed By:   snj
Date:           Thu Dec 10 23:08:43 UTC 2009

Modified Files:
        src/sys/kern [netbsd-5]: sys_mqueue.c

Log Message:
Pull up following revision(s) (requested by drochner in ticket #1188):
        sys/kern/sys_mqueue.c: revision 1.28 via patch
fix some security critical bugs:
-an invalid signal number passed to mq_notify(2) could crash the kernel
on delivery -- add a boundary check
-mq_receive(2) from an empty queue crashed the kernel by NULL dereference
in timeout calculation -- handle the NULL case
-likewise for mq_send(2) to a full queue
-a user could set mq_maxmsg (the maximal number of messages in a queue)
to a huge value on mq_open(O_CREAT) and later use up all kernel
memory by mq_send(2) -- add a sysctl'able limit which defaults
to 16*mq_def_maxmsg
(mq_notify(2) should get some more checks, and SIGEV_* values other
than SIGEV_SIGNAL should be handled somehow, but this doesn't look
security critical)


To generate a diff of this commit:
cvs rdiff -u -r1.12.4.5 -r1.12.4.6 src/sys/kern/sys_mqueue.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/kern/sys_mqueue.c
diff -u src/sys/kern/sys_mqueue.c:1.12.4.5 src/sys/kern/sys_mqueue.c:1.12.4.6
--- src/sys/kern/sys_mqueue.c:1.12.4.5	Fri Oct 16 06:37:51 2009
+++ src/sys/kern/sys_mqueue.c	Thu Dec 10 23:08:43 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: sys_mqueue.c,v 1.12.4.5 2009/10/16 06:37:51 snj Exp $	*/
+/*	$NetBSD: sys_mqueue.c,v 1.12.4.6 2009/12/10 23:08:43 snj Exp $	*/
 
 /*
  * Copyright (c) 2007-2009 Mindaugas Rasiukevicius <rmind at NetBSD org>
@@ -42,7 +42,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sys_mqueue.c,v 1.12.4.5 2009/10/16 06:37:51 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sys_mqueue.c,v 1.12.4.6 2009/12/10 23:08:43 snj Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -77,6 +77,7 @@
 
 static u_int			mq_max_msgsize = 16 * MQ_DEF_MSGSIZE;
 static u_int			mq_def_maxmsg = 32;
+static u_int			mq_max_maxmsg = 16 * 32;
 
 static kmutex_t			mqlist_mtx;
 static pool_cache_t		mqmsg_cache;
@@ -331,7 +332,9 @@
 				kmem_free(name, MQ_NAMELEN);
 				return error;
 			}
-			if (attr.mq_maxmsg <= 0 || attr.mq_msgsize <= 0 ||
+			if (attr.mq_maxmsg <= 0 ||
+			    attr.mq_maxmsg > mq_max_maxmsg ||
+			    attr.mq_msgsize <= 0 ||
 			    attr.mq_msgsize > mq_max_msgsize) {
 				kmem_free(name, MQ_NAMELEN);
 				return EINVAL;
@@ -506,10 +509,12 @@
 			error = EAGAIN;
 			goto error;
 		}
-		error = abstimeout2timo(ts, &t);
-		if (error) {
-			goto error;
-		}
+		if (ts) {
+			error = abstimeout2timo(ts, &t);
+			if (error)
+				goto error;
+		} else
+			t = 0;
 		/*
 		 * Block until someone sends the message.
 		 * While doing this, notification should not be sent.
@@ -672,10 +677,12 @@
 			error = EAGAIN;
 			goto error;
 		}
-		error = abstimeout2timo(ts, &t);
-		if (error) {
-			goto error;
-		}
+		if (ts) {
+			error = abstimeout2timo(ts, &t);
+			if (error)
+				goto error;
+		} else
+			t = 0;
 		/* Block until queue becomes available */
 		error = cv_timedwait_sig(&mq->mq_recv_cv, &mq->mq_mtx, t);
 		if (error || (mq->mq_attrib.mq_flags & MQ_UNLINK)) {
@@ -696,7 +703,8 @@
 
 	/* Check for the notify */
 	if (mq->mq_attrib.mq_curmsgs == 0 && mq->mq_notify_proc &&
-	    (mq->mq_attrib.mq_flags & MQ_RECEIVE) == 0) {
+	    (mq->mq_attrib.mq_flags & MQ_RECEIVE) == 0 &&
+	    mq->mq_sig_notify.sigev_notify == SIGEV_SIGNAL) {
 		/* Initialize the signal */
 		KSI_INIT(&ksi);
 		ksi.ksi_signo = mq->mq_sig_notify.sigev_signo;
@@ -791,6 +799,9 @@
 		    sizeof(struct sigevent));
 		if (error)
 			return error;
+		if (sig.sigev_notify == SIGEV_SIGNAL &&
+		    (sig.sigev_signo <=0 || sig.sigev_signo >= NSIG))
+			return EINVAL;
 	}
 
 	error = mqueue_get(SCARG(uap, mqdes), &fp);
@@ -1013,6 +1024,12 @@
 		SYSCTL_DESCR("Default maximal message count"),
 		NULL, 0, &mq_def_maxmsg, 0,
 		CTL_CREATE, CTL_EOL);
+	sysctl_createv(clog, 0, &node, NULL,
+		CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
+		CTLTYPE_INT, "mq_max_maxmsg",
+		SYSCTL_DESCR("Maximal allowed message count"),
+		NULL, 0, &mq_max_maxmsg, 0,
+		CTL_CREATE, CTL_EOL);
 }
 
 /*

Reply via email to