DragonFlyBSD Kernel Audit
DF-2780 / fix.diff
← back to finding ↓ download raw
Fix for DF-2780: inherit p_mqueue_cnt across fork + >= checks + existing-path check.

--- sys_mqueue.c	2026-09-01 04:01:55.500648734 +0000
+++ sys_mqueue.2780.only	2026-09-01 04:03:50.167194127 +0000
@@ -449,7 +449,7 @@
 		u_int i;
 
 		/* Check the limit */
-		if (p->p_mqueue_cnt == mq_open_max) {
+		if (p->p_mqueue_cnt >= mq_open_max) {
 			kfree(name, M_MQBUF);
 			return EMFILE;
 		}
@@ -561,6 +561,12 @@
 			error = EACCES;
 			goto exit;
 		}
+
+		/* Enforce the per-process limit on this path too */
+		if (p->p_mqueue_cnt >= mq_open_max) {
+			error = EMFILE;
+			goto exit;
+		}
 	} else {
 		/* Fail if mqueue neither exists, nor we create it */
 		if ((oflag & O_CREAT) == 0) {
@@ -574,7 +580,7 @@
 		}
 
 		/* Check the limit */
-		if (p->p_mqueue_cnt == mq_open_max) {
+		if (p->p_mqueue_cnt >= mq_open_max) {
 			error = EMFILE;
 			goto exit;
 		}

--- kern_fork.c	2026-09-01 04:01:55.500648734 +0000
+++ kern_fork.c.new	2026-09-01 04:08:18.687790250 +0000
@@ -40,6 +40,7 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/sysmsg.h>
+#include <sys/file.h>
 #include <sys/filedesc.h>
 #include <sys/kernel.h>
 #include <sys/sysctl.h>
@@ -553,6 +554,22 @@
 			error = ENOMEM;
 			goto done;
 		}
+		{
+			struct filedesc *nfd = p2->p_fd;
+			int nfdi;
+
+			/*
+			 * Inherit the POSIX mqueue descriptor count so the
+			 * decrement in mq_close_fop() (which runs in
+			 * whichever process drops the last file ref) stays
+			 * balanced across fork().
+			 */
+			for (nfdi = 0; nfdi <= nfd->fd_lastfile; nfdi++) {
+				if (nfd->fd_files[nfdi].fp &&
+				    nfd->fd_files[nfdi].fp->f_type == DTYPE_MQUEUE)
+					p2->p_mqueue_cnt++;
+			}
+		}
 		fdtol = NULL;
 	} else {
 		p2->p_fd = fdshare(p1);