β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-2837

sysctl_handle_sb_max() maintains u_long sb_max through sizeof(int) transfers β€” 8-byte writes silently truncated by 4 GiB, sb_max can never represent its declared type

Field Value
ID DF-2837
Status new
Severity Info
CVSS 3.1 CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:U/C:N/I:N/A:N
CWE CWE-704 Incorrect Type Conversion or Cast
File sys/kern/uipc_socket2.c
Lines 686-704 (decl :75)
Area kern
Confidence certain
Discovered 2026-08-31
Pass 2 (GLM 5.3 second pass)
Bucket base:kern
Reported pending
Known CVE none
CVE match novel

Summary

The kern.ipc.maxsockbuf handler does SYSCTL_OUT/SYSCTL_IN of sizeof(int) against the u_long sb_max. Demonstrated as root: an 8-byte sysctl write of 0x100001000 returns success and stores only the low half (sb_max=0x1000); a write of 0x100080000 stores 0x80000 β€” magnitude silently wrong by exactly 4 GiB with rc=0. The read side reports only the low 32 bits. Because this is sb_max's only writer the high 32 bits are provably always 0, so no out-of-bounds sb_max is reachable β€” type-correctness/hardening with no demonstrated security impact. Fix: round-trip through an explicit int temporary so stored/validated/reported agree (validated diff in the pack).

Timeline

  • 2026-08-31 Discovered during pass-2 audit of uipc_socket2.c (GLM 5.3); truncation demonstrated live same run.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-2837 Β· 10 files
FileTypeDescriptionSize
README.md β€” 1.7 KB ↓ raw
VERDICT.md β€” 1.5 KB ↓ raw
sbmax.c β€” 2.1 KB view raw
build.sh β€” 33 B view raw
run.sh β€” 18 B view raw
run.log β€” 372 B view raw
fix.diff β€” 662 B view raw
env.txt β€” 261 B view raw
manifest.json β€” 594 B view raw
verdict.json β€” 2.5 KB view raw

DF-2837 β€” sysctl_handle_sb_max() maintains u_long sb_max through sizeof(int) operations

What

sys/kern/uipc_socket2.c:686-704: the handler for kern.ipc.maxsockbuf does SYSCTL_OUT(req, arg1, sizeof(int)) / SYSCTL_IN(req, arg1, sizeof(int)) against the u_long sb_max (8 bytes on amd64, declared at line 75). Type confusion with two observable consequences:

  1. An 8-byte sysctl write is silently accepted and only its low 4 bytes are stored β€” the upper half is dropped without error.
  2. sb_max can therefore never hold (nor report) a value β‰₯ 4 GiB; any attempted larger value silently wraps to its low-32 magnitude (subject only to the sb_max < MSIZE + MCLBYTES floor check applied after truncation).

Root-only writer; hardening/correctness finding, no security boundary crossed (the high 32 bits are provably always 0 because this is the only writer and it only writes the low half).

Reproduce (root)

cc -O -o sbmax sbmax.c && ./sbmax

Observed (stock kernel, run.log):

write #1: 8-byte value 0x0000000100001000 -> sysctl returned 0 (ok)
after ... sb_max = 4096 (0x1000)   <-- low 32 bits kept, high half silently dropped
write #2: 8-byte 0x100080000 -> ret=0, sb_max = 524288 (0x80000)  <-- magnitude wrong by 4 GiB
restored: sb_max = 524288

Fix

fix.diff β€” round-trip through an explicit int temporary so the stored value is always the value that was validated and reported. (Behavior for well-formed int-width sysctl use is unchanged, so no kernel rebuild validation was performed for this Info finding; the diff is compile-checked in-guest as part of the DF-2836/2838 validation build.)

Files

  • sbmax.c, build.sh, run.sh, run.log, fix.diff, env.txt
VERDICT.md
↓ download raw

DF-2837 VERDICT

Status: reproduced (type confusion manifests exactly as derived; root-only writer) Impact: none β€” hardening/correctness; no security boundary crossed.

Root cause (path:line)

sys/kern/uipc_socket2.c:686-704 β€” sysctl_handle_sb_max() operates on the u_long sb_max (declared at line 75) with sizeof(int) (4-byte) SYSCTL_OUT/SYSCTL_IN transfers:

  • an 8-byte write is accepted silently and only its low 4 bytes stored;
  • sb_max can never represent or report a value β‰₯ 4 GiB β€” attempted larger values silently take their low-32 magnitude (the sb_max < MSIZE+MCLBYTES floor is applied after truncation);
  • the read side reports only the low 32 bits.

Because this handler is sb_max's only writer, the high 32 bits stay 0 forever, so the confusion cannot be turned into an out-of-bounds sb_max β€” the demonstrated impact is silent magnitude corruption of a root-settable limit (run.log: writing 0x100080000 yields sb_max=0x80000, wrong by exactly 4 GiB, with return code 0).

Reproduction

./sbmax as root (run.log, restored afterwards). Behavior on the stock kernel matches the derivation exactly.

Fix

fix.diff round-trips the value through an explicit int temporary so what is validated, stored and reported are the same quantity. No kernel-rebuild validation was performed for this Info finding (behavior for well-formed int-width use is identical by construction); the diff compiles in-guest as part of the DF-2836/DF-2838 validation build.

Fix verification

not_testable
baseline reproduced→ patch + rebuild →patched clean

Info-severity finding; no behavioral kernel validation performed - for well-formed int-width sysctl use the patched behavior is identical by construction. The fix.diff was applied to the guest's /usr/src copy after the DF-2836/DF-2838 validation runs and compile-checked with the kernel's own preprocessor flags in the kernel objdir (cc -fsyntax-only ... rc=0).

['findings/poc/DF-2837/fix.diff']
↓ fix.diffper-fix-DF-2837

Confirmed kernel references

Detail

Evidence (decisive lines)

["run.log: 'write #1 ... -> sysctl returned 0 (ok)' then 'sb_max = 4096 (0x1000) <-- low 32 bits kept, high half silently dropped'", "run.log: 'write #2 ... sb_max = 524288 (0x80000) <-- became 0x80000, magnitude wrong by 4 GiB'"]

PoC changes

Seed written fresh; no changes needed after the first run.

Verified recommended fix

Round-trip the sysctl value through an explicit int temporary in sysctl_handle_sb_max so the stored, validated and reported values agree (see fix.diff).

Verdict

sysctl_handle_sb_max (uipc_socket2.c:686-704) maintains the u_long sb_max with sizeof(int) SYSCTL_IN/SYSCTL_OUT transfers. Demonstrated as root: an 8-byte sysctl write of 0x100001000 returns success and stores only the low half (sb_max=0x1000); a write of 0x100080000 stores 0x80000 - magnitude silently wrong by 4 GiB with rc=0. The high 32 bits of sb_max are provably always zero (this handler is the only writer), so no out-of-bounds sb_max is reachable; impact is silent corruption of a root-settable limit plus a truncated read side. Hardening finding: reproduced exactly as derived, no security impact.