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
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 > 65535andmsgseg/msgsszruntime tunables are raised somsgmax > 65535(both admin-controlled). Not exploitable in default configuration. No code execution. Strictly weaker than DF-0046 (which was exploitable in default config becausesemvalu_shortwraps atSEMVMX=32767). POSIX-conformance / latent hardening.
Recommended fix
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.cSEMVMX). - 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.