DF-2781 / fix.diff
Fix for DF-2781: system-wide queue cap (kern.mqueue.mq_max_queues=256), cap check placed after mq_mtx acquisition so the shared exit path releases a held lock. --- sys/kern/sys_mqueue.c +++ sys/kern/sys_mqueue.c @@ -75,6 +75,9 @@ static u_int mq_def_maxmsg = 32; static u_int mq_max_maxmsg = 16 * 32; +static u_int mq_max_queues = 256; +static u_int mq_total_queues; + static struct lock mqlist_mtx; static LIST_HEAD(, mqueue) mqueue_head = LIST_HEAD_INITIALIZER(mqueue_head); @@ -394,6 +397,7 @@ */ if (mq->mq_refcnt == 0 && (mq->mq_attrib.mq_flags & MQ_UNLINK)) { LIST_REMOVE(mq, mq_list); + mq_total_queues--; destroy = true; } else destroy = false; @@ -582,7 +586,15 @@ /* Insert the queue to the list */ mq = mq_new; lockmgr(&mq->mq_mtx, LK_EXCLUSIVE); + + /* Check the system-wide queue count limit */ + if (mq_total_queues >= mq_max_queues) { + error = ENOMEM; + goto exit; + } + LIST_INSERT_HEAD(&mqueue_head, mq, mq_list); + mq_total_queues++; mq_new = NULL; getnanotime(&mq->mq_btime); mq->mq_atime = mq->mq_mtime = mq->mq_btime; @@ -1122,8 +1134,10 @@ KNOTE(&mq->mq_wkq.ki_note, 0); refcnt = mq->mq_refcnt; - if (refcnt == 0) + if (refcnt == 0) { LIST_REMOVE(mq, mq_list); + mq_total_queues--; + } lockmgr(&mq->mq_mtx, LK_RELEASE); error: @@ -1166,4 +1180,8 @@ CTLFLAG_RW, &mq_max_maxmsg, 0, "Maximal allowed message count"); +SYSCTL_INT(_kern_mqueue, OID_AUTO, mq_max_queues, + CTLFLAG_RW, &mq_max_queues, 0, + "Maximal number of message queues system-wide"); + SYSINIT(sys_mqueue_init, SI_SUB_PRE_DRIVERS, SI_ORDER_ANY, mqueue_sysinit, NULL); |