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

HAMMER1 mirror ioctls: mirror->size unchecked in mirror_read and mirror->count unchecked in both paths β€” wrap-around bypasses the ubuf bounds guards (hardening)

Summary

hammer_ioc_mirror_read never validates mirror->size (contrast the write path's 'size < 0 || size > 0x70000000' at :348) and neither path validates caller-supplied mirror->count on entry. The guards 'count + HAMMER_HEAD_DOALIGN(bytes) > size' (:156/:214/:260) and 'count + mrec.head.rec_size > size' (:424, uint32 arithmetic) wrap for count near INT_MAX or negative, letting copyin/copyout run at ubuf+-2GB. None beyond the caller poking its own address space: every access stays behind copyin/copyout fault isolation and both ubuf and count come from the same SYSCAP_NOVFS_IOCTL-gated caller. Defense-in-depth only; source-proven (untested). Fix: validate size/count at entry to both mirror ioctls.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-3151 Β· 4 files
FileTypeDescriptionSize
README.md β€” 520 B ↓ raw
VERDICT.md β€” 1.7 KB ↓ raw
verdict.json β€” 1.8 KB view raw
manifest.json β€” 393 B view raw

DF-3151 β€” mirror_read/mirror_write entry validation gaps (Info, hardening)

hammer_ioc_mirror_read never validates mirror->size (the write path does at hammer_mirror.c:348) and neither path validates the caller-supplied mirror->count; the 32-bit bounds arithmetic at hammer_mirror.c:156/214/260/424 can wrap. All consequences stay behind copyin/copyout user-address fault isolation (same gated caller owns ubuf), so this is hardening, not a kernel memory-safety bug. See VERDICT.md. No PoC (status: untested).

VERDICT.md
↓ download raw

DF-3151 β€” HAMMER1 hammer_ioc_mirror_read never validates mirror->size / mirror->count

Source-analysis finding (Info / hardening); no guest run performed.

  • hammer_ioc_mirror_read (hammer_mirror.c:72-319) validates only the key range (:91-96). Unlike the write path (:348 size < 0 || size > 0x70000000) the READ path never checks mirror->size, and NEITHER path validates mirror->count on entry.
  • All copyout sizing is guarded by `mirror->count + HAMMER_HEAD_DOALIGN(bytes)

    mirror->size(:156, :214, :260) in 32-bit signed/unsigned arithmetic. With a caller-suppliedcountnear INT_MAX (or negative), the sum wraps and the guard passes, so the kernel will copyout atubuf + count` (~+-2GB).

  • The WRITE path has the same shape at :424 (mirror->count + mrec.head.rec_size in uint32 arithmetic can wrap for negative count).
  • NOT a kernel memory-safety bug: every access is copyin/copyout through the standard user-address fault isolation, and both ubuf and count come from the same (gated, SYSCAP_NOVFS_IOCTL) caller. Impact is limited to the caller poking its own address space plus protocol confusion.
  • Fix (hardening): validate mirror->size in mirror_read exactly as the write path does, and reject mirror->count < 0 || mirror->count > mirror->size at entry to both functions.

Fix status (batch validation)

Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest make -j6 nativekernel KERNCONF=X86_64_GENERIC completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.

(No fix.diff for this item: documented recommendation only - see Fix above.)

Fix verification

not_testable
per-fix-DF-3151

Confirmed kernel references

Detail

Evidence (decisive lines)

['VERDICT.md: full line-annotated analysis']

PoC changes

n/a (no PoC; source-analysis finding)

Verified recommended fix

Validate mirror->size in hammer_ioc_mirror_read (same check as hammer_mirror.c:348) and reject out-of-range mirror->count at entry to both mirror ioctls.

Verdict

Info/hardening, source-proven only. hammer_ioc_mirror_read never validates mirror->size (contrast the write path's explicit check at hammer_mirror.c:348) and neither mirror path validates the caller-supplied mirror->count on entry. The bounds guards at mirror.c:156/214/260 (read) and :424 (write) are computed in 32-bit arithmetic and can wrap for count near INT_MAX or negative, letting the kernel copyin/copyout at ubuf+count (~+-2GB). Not a kernel memory-safety bug: all accesses stay behind copyin/copyout user-address fault isolation and both ubuf and count come from the same SYSCAP_NOVFS_IOCTL-gated caller - impact is confined to the caller's own address space plus protocol confusion. No guest run performed (nothing to demonstrate beyond the caller poking its own memory).