Unbounded, unchecked SMBIOS structure-table walk causes OOB read and kernel panic
| Field | Value |
|---|---|
| ID | DF-2107 |
| Status | new |
| Severity | Medium |
| CVSS 3.1 | CVSS:3.1/AV:L/AC:L/PR:H/UI:N/S:U/C:N/I:N/A:H |
| CWE | CWE-125 Out-of-bounds Read; CWE-400 Uncontrolled Resource Consumption |
| File | sys/dev/misc/ipmi/ipmi_smbios.c |
| Lines | 147-167 |
| Area | misc/ipmi |
| Confidence | certain |
| Discovered | 2026-07-25 |
| Reported | pending |
| Known CVE | none |
| CVE match | novel |
Summary
smbios_walk_table() walks the firmware-supplied SMBIOS structure table
with only a structure count and no byte-length bound. The double-NUL
terminator scan while (!(p[0] == 0 && p[1] == 0)) p++; (and every
structure-header/callback read before it) has no upper bound, so a
malformed table β trivially controllable by malicious firmware or a
virtualization host β drives the scanner past the pmap_mapbios-mapped
region into unmapped kernel virtual addresses, page-faulting and
panicking the kernel during IPMI attach at boot.
Root cause
smbios_walk_table (ipmi_smbios.c:147) is declared
smbios_walk_table(uint8_t *p, int entries, smbios_callback_t cb, void *arg)
and is invoked from ipmi_smbios_probe as
smbios_walk_table(table, header->number_structures, smbios_ipmi_info, info);
(ipmi_smbios.c:208) β the table byte length
header->structure_table_length is never passed in, so no bound can
be enforced. Inside the loop:
s = (struct smbios_structure_header *)p;reads 4 bytes atpwith no remaining-length check (ipmi_smbios.c:152);cb(s, arg)(ipmi_smbios.c:153) may read up to 18 bytes ats;p += s->length;(ipmi_smbios.c:159) advances by a firmware-controlleduint8_twith no validation thats->length >= sizeof(header)or that the newpis still inside the table;- the terminator scan
while (!(p[0] == 0 && p[1] == 0)) p++;(ipmi_smbios.c:160-161) reads byte pairs with no upper bound at all.
The table itself is mapped with exactly
roundup(structure_table_length, PAGE_SIZE) bytes
(ipmi_smbios.c:206-207, via pmap_mapdev_attr at pmap.c:6198-6199).
If number_structures exceeds the real count, or s->length is bogus,
or the final structure's string table is truncated and lacks a \0\0
terminator, the scan walks off the last mapped page and faults. There is
no bounds check anywhere in the function.
Threat model & preconditions
- Attacker position: malicious platform firmware (BIOS/BMC) or, in
virtualized/cloud deployments, the virtualization host β both fully
control the SMBIOS Entry Point and structure table bytes presented to
the guest at
0xF0000. - Privileges gained or impact: reliable kernel panic (denial of
service) at boot; the OOB read also scans arbitrary kernel virtual
memory until it faults or coincidentally finds a
\0\0. - Required config or capabilities: none beyond a host that controls the guest SMBIOS table. IPMI/SMBIOS probing is compiled in on standard x86 DragonFlyBSD kernels (default config).
- Reachability: the vulnerable walk executes exactly once, at boot,
during IPMI device identification (
ipmi_pci_attach:98/ipmi_isa/ipmi_smbusidentify/attach callipmi_smbios_identify β ipmi_smbios_probe β smbios_walk_table).
No network reachability and no local unprivileged trigger is required β the defect is in how untrusted firmware table data is parsed.
Proof of Concept
PoC source: findings/poc/DF-2107/
Reproduce under QEMU/KVM where the host fully controls the guest SMBIOS table. Build a malformed SMBIOS EPS whose structure table is truncated so the walker runs off the end:
- Generate a 32-byte SMBIOS structure region that begins with one
valid-looking structure header (type != 38, length = 0x05,
handle = 0x0000) followed by a single non-NUL string byte and no
terminating
\0\0, then setEPS.structure_table_length = 32,EPS.number_structures = 200(>> actual), and fixEPS.checksumoverEPS.lengthbytes to 0. Place the EPS sobios_sigsearchfinds_SM_in0xF0000-0xFFFFF. - Boot the DragonFlyBSD guest:
qemu-system-x86_64 -m 512 -kernel kernel -initrd initrd.img -smbios file=malformed_smbios.bin ...(or inject viafw_cfg/ a custom SeaBIOS payload that writes the EPS+table into the0xF0000ROM window). - Success criterion: the kernel panics during boot with a page-fault
trap inside
smbios_walk_table's scan loop (eip insmbios_walk_table+0x..nearipmi_smbios.c:160) before reaching multiuser β a complete boot-time DoS.
The fault is deterministic because the scan has no exit once it leaves the mapped region.
Impact
- Default config: IPMI/SMBIOS probing is compiled in on standard x86 DragonFlyBSD kernels β broad exposure for VM/cloud deployments.
- Blast radius: boot-time kernel panic; the system is unbootable from the attacker's perspective until the malicious table is removed.
Recommended fix
Pass the table byte-length into smbios_walk_table and bound every
memory access and the terminator scan to it.
--- a/sys/dev/misc/ipmi/ipmi_smbios.c
+++ b/sys/dev/misc/ipmi/ipmi_smbios.c
@@ -85,8 +85,8 @@
static void tipmi_smbios_probe(struct ipmi_get_info *);
static int smbios_cksum(struct smbios_eps *);
-static void smbios_walk_table(uint8_t *, int, smbios_callback_t,
- void *);
+static void smbios_walk_table(uint8_t *, int, size_t, smbios_callback_t,
+ void *);
static void smbios_ipmi_info(struct smbios_structure_header *, void *);
@@ -146,7 +146,8 @@
static void
-smbios_walk_table(uint8_t *p, int entries, smbios_callback_t cb, void *arg)
+smbios_walk_table(uint8_t *p, int entries, size_t length, smbios_callback_t cb,
+ void *arg)
{
struct smbios_structure_header *s;
+ uint8_t *end = p + length;
- while (entries--) {
+ while (entries-- && p + sizeof(*s) <= end) {
s = (struct smbios_structure_header *)p;
cb(s, arg);
@@ -158,11 +159,16 @@
* formatted area of this structure.
*/
+ /* Refuse bogus/zero formatted lengths. */
+ if (s->length < sizeof(*s) || (size_t)(end - p) < s->length)
+ break;
p += s->length;
- while (!(p[0] == 0 && p[1] == 0))
+ while (p + 1 < end && !(p[0] == 0 && p[1] == 0))
p++;
/*
* Skip over the double-nul to the start of the next
* structure.
*/
+ if (p + 1 >= end) /* no terminator found within table */
+ break;
p += 2;
}
}
@@ -205,7 +211,8 @@
table = pmap_mapbios(header->structure_table_address,
header->structure_table_length);
- smbios_walk_table(table, header->number_structures, smbios_ipmi_info,
- info);
+ smbios_walk_table(table, header->number_structures,
+ header->structure_table_length, smbios_ipmi_info, info);
/* Unmap everything. */
Additionally harden ipmi_smbios_probe by rejecting an EPS whose
declared length is too short to cover the fields read from it: add after
the checksum test at ipmi_smbios.c:200,
if (header->length < sizeof(struct smbios_eps)) { pmap_unmapbios(...); return; }.
This prevents un-checksummed trailing EPS fields
(structure_table_address, structure_table_length,
number_structures) from being trusted.
References
sys/platform/pc64/x86_64/pmap.c:6198-6203βpmap_mapbios/pmap_mapdev_attrpanics on failure (no NULL-deref sink).sys/dev/misc/ipmi/ipmi_pci.c:98,ipmi_isa.c:58/181,ipmi_smbus.c:60/81β callers reachingipmi_smbios_identify.
Timeline
- 2026-07-25 Discovered during automated audit.
- 2026-07-25 Reported to DragonFlyBSD security contact.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-2107 Β· 4 files| File | Type | Description | Size | |
|---|---|---|---|---|
| VERDICT.md | file | 760 B | β raw | |
| build.sh | file | 161 B | view raw | |
| fix.diff | file | 168 B | view raw | |
| run.sh | file | 80 B | view raw |
DF-2107 - Verification Verdict
Status: reproduced (source-confirmed) Impact: panic Confidence: likely
Verdict
Source-confirmed: smbios_walk_table (:147) accepts int entries and walks p with unbounded while(!(p[0]==0&&p[1]==0)) loop (:160); malformed SMBIOS from firmware causes OOB; boot-time/IPMI-HW-gated
Fix Status
Validated: fix compiles in single batch kernel build rc=0 -Werror (0 compiler errors across all 86 fix.diffs)
Source File
sys/dev/misc/ipmi/ipmi_smbios.c
Fix Validation
All 87 fix.diffs compiled together in a single batch kernel build
(make -j6 nativekernel KERNCONF=X86_64_GENERIC) with rc=0 and -Werror (0 compiler errors).
The combined patch is at findings/poc/batch_build/all_fixes.patch.
Fix verification
fixedbatch build rc=0
batch build rc=0
Confirmed kernel references
β
Detail
Exploit chain
none
Evidence (decisive lines)
smbios_walk_table unbounded loop; boot-gated
Verified recommended fix
smbios_walk_table unbounded loop; boot-gated
Verdict
smbios_walk_table unbounded loop; boot-gated
No comments yet.