Module Name: src
Committed By: snj
Date: Fri Dec 18 05:27:56 UTC 2009
Modified Files:
src/sys/kern [netbsd-5-0]: sys_mqueue.c
Log Message:
Pull up following revision(s) (requested by tron 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
-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.1.2.3 -r1.12.4.1.2.4 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.1.2.3 src/sys/kern/sys_mqueue.c:1.12.4.1.2.4
--- src/sys/kern/sys_mqueue.c:1.12.4.1.2.3 Tue Jul 21 00:21:21 2009
+++ src/sys/kern/sys_mqueue.c Fri Dec 18 05:27:56 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: sys_mqueue.c,v 1.12.4.1.2.3 2009/07/21 00:21:21 snj Exp $ */
+/* $NetBSD: sys_mqueue.c,v 1.12.4.1.2.4 2009/12/18 05:27:56 snj Exp $ */
/*
* Copyright (c) 2007, 2008 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.1.2.3 2009/07/21 00:21:21 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sys_mqueue.c,v 1.12.4.1.2.4 2009/12/18 05:27:56 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;
@@ -330,7 +331,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;
@@ -688,7 +691,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;
@@ -780,6 +784,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);
@@ -1002,6 +1009,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);
}
/*