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

Translation table size never validated: heap OOB read and NULL-deref panic via undersized/NULL d_table

Summary

iconv_xlat_conv indexes dp->d_table[(u_char)*src] across full 0..255 range (iconv_xlat.c:99) and iconv_xlat_open blindly trusts csp->cp_data (iconv_xlat.c:61) with zero validation table is 256 bytes. Only registration-layer check is upper bound (iconv.c:410 ia_datalen<=ICONV_CSMAXDATALEN=266240) no lower bound no equality check. cspair registered with ia_datalen==0 yields cp_data==NULL (allocation skipped iconv.c:426) first conversion dereferences NULL+offset panics. cspair with 0<ia_datalen<256 reads up to (256-ia_datalen) bytes past kmalloc table object writes into caller output buffer kernel-heap info leak. struct iconv_cspair does not carry data length converter cannot defend itself at open time. Legitimate kiconv_add_xlat_table always passes 256. Attacker: host root kern.iconv.add sysctl requires SYSCAP_NOSYSCTL_WR OID lacks CTLFLAG_PRISON jailed root blocked. Defense-in-depth/hardening gap becomes real primitive if sysctl exposed to confined-privileged context. [VERIFIED pass2: datalen 0 pair NULL-derefs at VA 0x42, 64-byte table sweeps 192 of 192 output bytes past the allocation with stable pointer-like heap content across 3 boots; cp_datalen equals 256 validation fix-validated EINVAL]

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-2247 Β· 14 files
FileTypeDescriptionSize
run.log β€” 2.0 KB view raw
panic.txt β€” 371 B view raw
leak_sample1.txt β€” 805 B view raw
leak_sample2.txt β€” 805 B view raw
leak_sample3.txt β€” 805 B view raw
run_stock_t1_boot.log β€” 14.7 KB view raw
run_controls_boot.log β€” 17.4 KB view raw
fix.diff β€” 923 B view raw
dfh.c β€” 24.3 KB view raw
dfarm.c β€” 2.4 KB view raw
harness.diff β€” 2.2 KB view raw
build.sh β€” 66 B view raw
run.sh β€” 201 B view raw
env.txt β€” 234 B view raw

Fix verification

fixed
baseline reproduced→ patch + rebuild →patched clean

Stock: NULL-table panic (VA 0x42) and 192/192 heap-pattern output bytes for the undersized table. Fixed: both bad pairs rejected at iconv_open with EINVAL; 256-byte control byte-identical.

run_stock_t1_boot.log, leak_sample*.txt vs fixed-boot run.log (iconv_open FAILED ret=22) and control equality.
↓ fix.diffDragonFly dfbsd 6.5-DEVELOPMENT #8 DFHARNESS x86_64 (stock-behavior kernels #4/#6, fixed #8; base 6.5-DEVELOPMENT 600519)

Confirmed kernel references

Detail

Exploit chain

armed registrar registers undersized table -> any conversion sweeps d_table[0..255] -> kernel heap bytes adjacent to the 64-byte allocation are copied into the converted output (e.g. filename buffer) -> limited kernel heap disclosure; NULL variant panics the box.

Evidence (decisive lines)

panic.txt: fault VA 0x42, Stopped at iconv_xlat_conv+0x5e. leak_sample1/2/3.txt: identical 256-byte dumps, indices >=64 all non-0xAA heap pattern. run.log fixed section: iconv_open FAILED ret=22.

PoC changes

Reused the DF-2237 rig shape (kern.iconv.add wire format) but kernel-compiled (options LIBICONV) because runtime kldload was ruled out for this batch; dfarm takes datalen/fill/idx:val args; harness sweeps 0..255 with a 0xAA-filled undersized table for attribution.

Verified recommended fix

Record ia_datalen in struct iconv_cspair at registration and reject xlat opens whose table is not exactly 256 bytes.

Verdict

Both halves mechanical: a datalen=0 pair (allocation skipped in iconv.c) NULL-derefs at exactly NULL+0x42 on the first conversion (Fatal trap 12, iconv_xlat_conv+0x5e movzbl (%r10,%r9,1)); a 64-byte table yields 192/192 output bytes read past the kmalloc object into converter output, stable pointer-like heap pattern across 3 boots. Only the registration layer upper-bounds datalen; no lower bound or equality check exists. Reach = root-armed kern.iconv.add registrar (mount helpers); legit callers pass 256. Read-only primitives, no write, no uid=0 chain; fixed by recording cp_datalen at registration and validating 256 bytes at open (EINVAL now returned).