โฌข DragonFlyBSD Kernel Audit
โ† dashboard
DF-0051

msgsnd lacks explicit MSGMAX upper-bound check; msg_ts (u_short) silently truncates when MSGMNB compiled > 65535 (latent panic)

Field Value
ID DF-0051
Status new
Severity Info
CVSS 3.1 CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:N/A:L
CWE CWE-190 Integer Overflow; CWE-197 Integer Truncation
File sys/kern/sysv_msg.c
Lines 651 (msg_ts truncation), 513/526 (size gates), 50 (u_short), 179-193 (msg_freehdr panic)
Area kern
Confidence likely
Discovered 2026-06-29
Reported pending

Summary

Direct structural analog of DF-0046 (sysv_sem.c SEMVMX): msgsnd never validates msgsz against the system limit msginfo.msgmax. The only size gate is msgsz > msqptr->msg_qbytes (:526), and msg_qbytes is capped at msginfo.msgmnb (:294). In the default kernel (MSGMNB=2048, msgmax=16384) this is safe (msg_qbytes โ‰ค 2048, well within the u_short msg_ts range). However msghdr->msg_ts is u_short (:50) and is assigned the full size_t msgsz at :651 with no range check. If the kernel is compiled with MSGMNB > 65535 (:62-63 #define; not a runtime tunable) and the msgseg/msgssz runtime tunables are raised (:1079-1080) so msgmax exceeds 65535, msgsz can exceed 65535, msg_ts silently truncates, and msg_freehdr (:179-193) panics at :193 (the truncated msg_ts hits 0 before the full segment chain is walked). Not reachable in default configuration โ€” hardening / POSIX-conformance (msgsnd should return EINVAL when msgsz exceeds the system max).

Root cause

sys/kern/sysv_msg.c:651:

msghdr->msg_ts = msgsz;          /* size_t -> u_short, no upper-bound check */

msg_ts is u_short (:50, max 65535). No check msgsz > msginfo.msgmax exists in msgsnd; the only bound is msgsz <= msg_qbytes <= msginfo.msgmnb (:526, :294, :431). msg_freehdr (:179-193) walks segments keyed on msg_ts; a truncated msg_ts exits the loop early while the msg_spot chain is non-empty โ†’ panic at :193.

Threat model & preconditions

  • Impact: local kernel panic (DoS) only if the kernel is compiled with MSGMNB > 65535 and msgseg/msgssz runtime tunables are raised so msgmax > 65535 (both admin-controlled). Not exploitable in default configuration. No code execution. Strictly weaker than DF-0046 (which was exploitable in default config because semval u_short wraps at SEMVMX=32767). POSIX-conformance / latent hardening.

Validate msgsz against msginfo.msgmax before the size math, and widen msg_ts to int (kernel-internal, no ABI impact):

--- a/sys/kern/sysv_msg.c
+++ b/sys/kern/sysv_msg.c
@@ -511,6 +511,9 @@
    if (msgsz > msqptr->msg_qbytes) { ... EINVAL ... }
+   if (msgsz > (size_t)msginfo.msgmax) {
+       eval = EINVAL;
+       goto done;
+   }
    segs_needed = howmany(msgsz, msginfo.msgssz);

(and struct msg::msg_ts u_short โ†’ int at :50).

References

  • sys/kern/sysv_msg.c:651,513,526,50,179-193 โ€” the truncation + panic path.
  • Analogous to DF-0046 (sysv_sem.c SEMVMX).
  • CWE-190; CWE-197.

Timeline

  • 2026-06-29 Discovered during automated file-by-file audit of sys/kern/sysv_msg.c.
  • pending Reported to DragonFlyBSD security contact.