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); } /*