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)
This commit is contained in:
parent
af4728306c
commit
fe1db36da9
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: sys_mqueue.c,v 1.27 2009/12/09 21:32:59 dsl Exp $ */
|
||||
/* $NetBSD: sys_mqueue.c,v 1.28 2009/12/10 12:22:48 drochner 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.27 2009/12/09 21:32:59 dsl Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: sys_mqueue.c,v 1.28 2009/12/10 12:22:48 drochner Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
|
@ -82,6 +82,7 @@ static u_int mq_open_max = MQ_OPEN_MAX;
|
|||
static u_int mq_prio_max = MQ_PRIO_MAX;
|
||||
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;
|
||||
|
@ -447,7 +448,9 @@ sys_mq_open(struct lwp *l, const struct sys_mq_open_args *uap,
|
|||
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;
|
||||
|
@ -630,10 +633,12 @@ mq_recv1(mqd_t mqdes, void *msg_ptr, size_t msg_len, u_int *msg_prio,
|
|||
error = EAGAIN;
|
||||
goto error;
|
||||
}
|
||||
if (ts) {
|
||||
error = abstimeout2timo(ts, &t);
|
||||
if (error) {
|
||||
if (error)
|
||||
goto error;
|
||||
}
|
||||
} else
|
||||
t = 0;
|
||||
/*
|
||||
* Block until someone sends the message.
|
||||
* While doing this, notification should not be sent.
|
||||
|
@ -815,10 +820,12 @@ mq_send1(mqd_t mqdes, const char *msg_ptr, size_t msg_len, u_int msg_prio,
|
|||
error = EAGAIN;
|
||||
goto error;
|
||||
}
|
||||
if (ts) {
|
||||
error = abstimeout2timo(ts, &t);
|
||||
if (error) {
|
||||
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 || (mqattr->mq_flags & MQ_UNLINK)) {
|
||||
|
@ -844,7 +851,8 @@ mq_send1(mqd_t mqdes, const char *msg_ptr, size_t msg_len, u_int msg_prio,
|
|||
|
||||
/* Check for the notify */
|
||||
if (mqattr->mq_curmsgs == 0 && mq->mq_notify_proc &&
|
||||
(mqattr->mq_flags & MQ_RECEIVE) == 0) {
|
||||
(mqattr->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;
|
||||
|
@ -938,6 +946,9 @@ sys_mq_notify(struct lwp *l, const struct sys_mq_notify_args *uap,
|
|||
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);
|
||||
|
@ -1161,6 +1172,12 @@ SYSCTL_SETUP(sysctl_mqueue_setup, "sysctl mqueue setup")
|
|||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue