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

ksprintf overflows 9-byte msp/dpl version string buffers by up to 2 bytes (lands in struct padding, no impact today)

Field Value
ID DF-1850
Status new
Severity Info
CVSS 3.1 CVSS:3.1/AV:L/AC:H/PR:H/UI:N/S:U/C:N/I:N/A:N
CWE CWE-787 Out-of-bounds Write
File sys/dev/video/bktr/bktr_audio.c
Lines 442, 598
Area dev/video (bktr audio probe)
Confidence certain
Discovered 2026-07-20
Reported pending
Known CVE none
CVE match dfly_specific

Summary

msp_read_id() and dpl_read_id() ksprintf into char[9] buffers using format "34%02d%c-%c%d". The %02d conversion produces a minimum of 2 digits but does NOT cap at 2 β€” for input value 100..255 it emits 3 digits, making total output up to 10 chars + NUL = 11 bytes into a 9-byte buffer. The 2-byte overrun currently lands in compiler-inserted struct padding before the adjacent int field, so there is no security impact today, but it is undefined behavior and a latent corruption risk if the struct is ever repacked or the field reordered.

Root cause

At bktr_audio.c:442-443, msp_read_id() calls:

ksprintf(bktr->msp_version_string, "34%02d%c-%c%d",
    (rev2>>8)&0xff, (rev1&0xff)+'@', ((rev1>>8)&0xff)+'@', rev2&0x1f);

bktr->msp_version_string is declared char[9] at bktr_reg.h:572. The format breakdown for worst-case I2C read (rev2=0xffff β†’ (rev2>>8)&0xff=255, rev2&0x1f=31):

Part Chars
"34" 2
"%02d", 255 3 ("255" β€” %02d is min-width-2, NOT max-width-2)
"%c" 1
"-" 1
"%c" 1
"%d", 31 2
NUL 1
Total 11 bytes into 9-byte buffer β†’ 2-byte overflow

The identical pattern exists at bktr_audio.c:598-599 in dpl_read_id() writing to char dpl_version_string[9] (bktr_reg.h:574).

The overflow bytes land at struct offsets 9 and 10. In struct bktr_softc (bktr_reg.h:572-575) the next field after char[9] is int msp_addr (4-byte aligned), so the compiler inserts 3 padding bytes at offsets 9-11. The overrun is absorbed by padding. No struct is declared __packed.

Threat model & preconditions

  • Attacker position: none user-reachable. The rev1/rev2 values come from msp_dpl_read() I2C transactions against the MSP34xx/DPL35xx chip (bktr_audio.c:439-440, 595-596). These functions are only called from bktr_card.c:1263 and bktr_card.c:1277 during device probe/attach (NOT from any user ioctl path), and only after i2cRead() confirms the chip is present.
  • Privileges gained or impact: none. The overflow lands in struct padding and corrupts nothing. No path exists for an unprivileged local user to trigger this.
  • Required config or capabilities: malicious PCI hardware that returns crafted I2C bytes at probe time, or a glitchy MSP chip returning 0xffff.
  • Reachability: device probe/attach only.

Proof of concept

Not exploitable for security impact. To demonstrate the overflow itself (requires a Bt848/Bt878 card with an MSP34xx chip whose S/N register returns 0xffff):

  1. Boot a DragonFlyBSD system with such a card.
  2. The probe path in bktr_card.c:1263 calls msp_read_id() which reads rev1=0xffff, rev2=0xffff.
  3. ksprintf writes 11 bytes to the 9-byte msp_version_string[].
  4. Confirm with KASSERT/KASAN or by adding a printf of output length vs buffer.

No panic, no corruption observable β€” bytes land in padding. Hardening/UB issue only.

Impact

Info-level undefined behavior. No memory corruption today because the overflow lands in compiler-inserted struct padding. Latent risk if the struct is ever repacked or the field reordered.

Use ksnprintf with the buffer size (truncates safely), or enlarge the buffers.

--- a/sys/dev/video/bktr/bktr_audio.c
+++ b/sys/dev/video/bktr/bktr_audio.c
@@ -439,7 +439,8 @@ void msp_read_id( bktr_ptr_t bktr ){
     rev2 = msp_dpl_read(bktr, bktr->msp_addr, 0x12, 0x001f);

-    ksprintf(bktr->msp_version_string, "34%02d%c-%c%d",
+    ksnprintf(bktr->msp_version_string,
+      sizeof(bktr->msp_version_string), "34%02d%c-%c%d",
       (rev2>>8)&0xff, (rev1&0xff)+'@', ((rev1>>8)&0xff)+'@', rev2&0x1f);

 }
@@ -595,7 +596,8 @@ void dpl_read_id( bktr_ptr_t bktr ){
     rev2 = msp_dpl_read(bktr, bktr->dpl_addr, 0x12, 0x001f);

-    ksprintf(bktr->dpl_version_string, "34%02d%c-%c%d",
+    ksnprintf(bktr->dpl_version_string,
+      sizeof(bktr->dpl_version_string), "34%02d%c-%c%d",
       ((rev2>>8)&0xff)-1, (rev1&0xff)+'@', ((rev1>>8)&0xff)+'@', rev2&0x1f);
 }

Alternatively, enlarge both char[9] fields to char[12] in bktr_reg.h:572,574 β€” since 3 bytes of padding already exist before the adjacent int fields, this costs zero additional memory and eliminates the UB entirely.

Timeline

  • 2026-07-20 Discovered during automated audit.
  • 2026-07-20 Reported to DragonFlyBSD security contact (pending).

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-1850 Β· 1 files
FileTypeDescriptionSize
fix.diff suggested-fix ksprintf overflows 9-byte msp/dpl version string buffers by up to 2 bytes (lands 690 B view raw

Fix verification

fixed
baseline reproduced→ patch + rebuild →patched clean

fix.diff applied + combined nativekernel build rc=0 (-Werror)

fix.diff applied + combined nativekernel build rc=0 (-Werror)
↓ fix.diffcombined build rc=0

Confirmed kernel references

β€”

Detail

Exploit chain

none (Info severity)

Evidence (decisive lines)

Source-confirmed at sys/dev/video/bktr/bktr_audio.c:442: ksprintf overflows 9-byte msp/dpl version string buffers by up to 2 bytes

Verified recommended fix

Source-confirmed at sys/dev/video/bktr/bktr_audio.c:442: ksprintf overflows 9-byte msp/dpl version string buffers by up to 2 bytes

Verdict

Source-confirmed at sys/dev/video/bktr/bktr_audio.c:442: ksprintf overflows 9-byte msp/dpl version string buffers by up to 2 bytes