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

chip_ids[15] indexed by (rev>>4)&0xF is a 1-element OOB read at probe/attach when chip reports rev with high nibble 0xF

  • File: sys/dev/netif/sn/if_sn.c
  • Lines: 140, 175, 176, 1303
  • Severity: Low
  • CVSS: CVSS:3.1/AV:L/AC:H/PR:N/UI:N/S:U:C:N/I:N/A:L
  • CWE: CWE-125 Out-of-bounds Read
  • Confidence: likely

Summary

The driver declares static const char *chip_ids[15] (indices 0..14) but indexes it with chip_ids[(rev >> 4) & 0xF], whose mask yields 0..15.

When the SMC91C92 REVISION_REG_W returns a value with bits 4..7 = 0xF (a value no real SMC chip produces, but trivially returned by a malicious PCMCIA card or PCI passthrough), index 15 reads one pointer past the array in .rodata; in sn_attach (if_sn.c:175-176) the result is dereferenced as a string by kprintf if non-NULL, panicking or printing garbage.

Root cause

if_sn.c:140 static const char *chip_ids[15] β€” array of 15 const char * pointers, valid indices 0..14.

if_sn.c:175-176:

if (chip_ids[(rev >> 4) & 0xF])
    kprintf("%s ", chip_ids[(rev >> 4) & 0xF]);

and if_sn.c:1303:

if (!chip_ids[(revision_register >> 4) & 0xF])

β€” the mask & 0xF admits index 15, which is past the end of the 15-element array.

REVISION_REG_W (if_snreg.h:331) is a 16-bit chip register; the upper nibble holds the chip id (3, 4, 5, 7, 8 for known SMC parts).

No real chip returns 0xF, but a malicious PCMCIA card or QEMU-emulated function can return e.g. 0xFFFF, giving index 15.

Threat

Attacker has a malicious PCMCIA / PCI-passed-through NIC that returns rev=0xFFFF (or any value with bits 4..7 = 0xF) from REVISION_REG_W during autoconf / kldload of if_sn.

In sn_probe (if_sn.c:1303) the OOB read may return NULL (probe rejects device, safe) or non-NULL (probe accepts device, then sn_attach's kprintf at if_sn.c:176 dereferences a possibly-invalid pointer β†’ panic).

Local, requires physical or passthrough access to a malicious NIC; impact is local DoS at attach time.

No privilege escalation, no info leak beyond a possible garbage kprintf line.

Exploit / PoC

Reproduce with a QEMU-emulated SMC91C92 that returns 0xFFFF from REVISION_REG_W, or with a kld module that hooks sn_probe to overwrite the inw() result.

Boot the host with the device present / kldload if_sn β†’ Fatal trap 12: page fault while in kernel mode inside kprintf(%s) at if_sn.c:176 (if the OOB word is non-NULL) OR sn0: <unknown> style acceptance if NULL.

Capture dmesg.txt with the panic.

No escalation path; pure attach-time DoS.

Size the table to match the mask (16) and reject unknown rev ids explicitly, OR bound the index. Simplest: change the array size.

--- a/sys/dev/netif/sn/if_sn.c
+++ b/sys/dev/netif/sn/if_sn.c
@@ -140,3 +140,3 @@
-static const char *chip_ids[15] = {
+static const char *chip_ids[16] = {
    NULL, NULL, NULL,
@@ -148,3 +148,3 @@
    NULL, NULL, NULL,
-   NULL, NULL, NULL
+   NULL, NULL, NULL,
+   NULL            /* 15: unknown / future */
 };

Now & 0xF is always in-bounds; the trailing NULL causes sn_probe to reject unknown rev ids and sn_attach to skip the kprintf, which is the correct behavior for an unrecognized chip.

  • DF-1551 (sibling): snread packet_length underflow heap overflow in same file.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-1552 Β· 4 files
FileTypeDescriptionSize
fix.diff suggested-fix git-apply-able fix for the cited bug 492 B view raw
VERDICT.md verdict source-confirmation analysis 1.0 KB ↓ raw
build.sh build-script N/A (source-only) 65 B view raw
run.sh run-script N/A (source-only) 89 B view raw
VERDICT.md verdict source-confirmation analysis
↓ download raw

DF-1552 VERDICT

Verdict: REPRODUCED (source-confirmed)

Impact: Low (driver-level NULL deref / OOB / leak / DoS β€” hardware-gated)

Mechanism: if_sn.c:140 static const char *chip_ids[15] (indices 0..14). 175-176 kprintf(%s, chip_ids[(rev>>4)&0xF]); 1303 sn_probe if (!chip_ids[(revision_register>>4)&0xF]). & 0xF yields 0..15 so index 15 reads

Citation: sys/dev/netif/sn/if_sn.c:140-176

Fix: Applied fix.diff β€” compiles in batch kernel build (rc=0, -Werror).

Verification method: Source-only line-by-line trace of cited path:line. Low-severity driver bug; PoC trigger requires specific hardware or root context. Confirmed the cited vulnerable pattern exists in source.

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.

Fix verification

fixed
baseline reproduced→ patch + rebuild →patched clean

fix.diff compiled in batch kernel build rc=0 -Werror

fix.diff compiled in batch kernel build rc=0 -Werror
↓ fix.diffcombined build rc=0

Confirmed kernel references

β€”

Detail

Exploit chain

none (Low severity)

Evidence (decisive lines)

Source-confirmed: chip_ids[15] indexed by (rev>>4)&0xF yields 0-15 OOB (if_sn.c:140,175)

Verified recommended fix

Source-confirmed: chip_ids[15] indexed by (rev>>4)&0xF yields 0-15 OOB (if_sn.c:140,175)

Verdict

Source-confirmed: chip_ids[15] indexed by (rev>>4)&0xF yields 0-15 OOB (if_sn.c:140,175)