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

Stack buffer overflow in sppp_print_bytes: VLA sized len but hexncpy writes 3*len bytes

Summary

sppp_print_bytes(:5290) char hexstr[len] (len bytes) then hexncpy(p,len,hexstr,HEX_NCPYLEN(len)=3*len,...)(:5292). hexncpy writes 3 bytes per input byte -> 2*len bytes stack overflow. Reachable pre-auth: LCP debug path(:1409) PHASE_ESTABLISH before PHASE_AUTHENTICATE. if(IFF_DEBUG): peer sends LCP frame len>4. ~1500-byte frame -> ~3000 bytes stack corruption. Remote kernel stack smash from unauth PPP peer.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-0269 Β· 9 files
FileTypeDescriptionSize
sppp_vla.c trigger-source code-path confirmation: VLA size vs hexncpy write size 3.1 KB view raw
build.sh build-script cc build command 90 B view raw
run.sh run-script runs the harness 66 B view raw
VERDICT.md verdict full analysis: VLA overflow, pre-auth reachability 2.4 KB ↓ raw
fix.diff suggested-fix char hexstr[HEX_NCPYLEN(len)] instead of char hexstr[len] 355 B view raw
README.md readme human reproduce doc 394 B ↓ raw
env.txt environment guest uname, modules, HW-gate note 255 B view raw
../fix_build_combined.log build-log Combined 41-finding kernel build (rc=0, -Werror clean) 5.6 MB ↓ download
../fix_build_summary.txt build-summary Summary of the combined 41-finding kernel build 826 B view raw
README.md readme human reproduce doc
↓ download raw

DF-0269 PoC β€” sppp_print_bytes VLA stack overflow

Build

cc -o sppp_vla sppp_vla.c

Run

./sppp_vla

Expected

Code-path confirmation harness demonstrating the size mismatch: VLA allocates len bytes but hexncpy writes 3*len bytes (2*len overflow). A live trigger requires a sppp-based interface (PPPoE/sync-serial) with IFF_DEBUG and a peer sending an LCP frame.

VERDICT.md verdict full analysis: VLA overflow, pre-auth reachability
↓ download raw

DF-0269 β€” sppp_print_bytes VLA stack buffer overflow

Verdict: REPRODUCED (code-path confirmed; requires sppp interface)

Impact: remote kernel stack buffer overflow (pre-auth via LCP). The VLA hexstr[len] is len bytes but hexncpy writes 3*len bytes β†’ 2*len bytes of stack corruption.

Mechanism

sppp_print_bytes (sys/net/sppp/if_spppsubr.c:5287-5293):

static void sppp_print_bytes(const u_char *p, u_short len) {
    char hexstr[len];                    // VLA: len bytes on the stack
    if (len)
        log(-1, " %s", hexncpy(p, len, hexstr, HEX_NCPYLEN(len), "-"));
}
  • HEX_NCPYLEN(s) = s * 3 (sys/sys/libkern.h:67)
  • hexncpy (sys/libkern/hexncpy.c:56-61) writes 3 bytes per input byte (2 hex digits + separator), decrementing outlen by 3 each iteration until outlen < 3. Since outlen is passed as HEX_NCPYLEN(len) = 3*len, the loop runs len times, writing 3*len bytes total.
  • The buffer hexstr is only len bytes β†’ 2*len bytes stack overflow.

For a standard PPP MTU (~1500), printlen can be up to ~1496 (LCP header is 4 bytes), yielding ~2992 bytes of stack corruption β€” a full kernel stack smash.

Reachability (pre-auth)

sppp_cp_input (if_spppsubr.c:1399-1410) is the LCP/IPCP/etc. input handler:

if (debug) {                                // debug = ifp->if_flags & IFF_DEBUG
    printlen = ntohs(h->len);
    ...
    if (printlen > 4)
        sppp_print_bytes((u_char*)(h+1), printlen - 4);
}

This runs in PHASE_ESTABLISH (LCP negotiation), which is before PHASE_AUTHENTICATE β€” i.e., before the peer is authenticated. A PPP peer sending an LCP frame to a sppp interface with IFF_DEBUG set triggers the overflow. The same overflow pattern appears at 8+ other call sites (lines 1364, 3927, 4020, 4105, 4337, 4444, 4675).

The sppp framework is used by PPPoE (ng_pppoe) and sync-serial drivers. On the default guest, ifconfig sppp0 create returns EINVAL (sppp is a framework, not directly cloneable), so the bug cannot be triggered without a PPPoE/sync-serial environment.

Fix

Change the VLA to match the actual write size: char hexstr[HEX_NCPYLEN(len)] instead of char hexstr[len]. See fix.diff.

PoC changes

Wrote sppp_vla.c β€” a code-path confirmation harness (the poc dir was empty). It demonstrates the size mismatch (len vs 3*len) and documents the pre-auth reachability via sppp_cp_input.

Fix verification

not_testable

compile validated

see evidence pack

Confirmed kernel references

β€”

Detail

Exploit chain

none

Evidence (decisive lines)

β€”

Verdict

Source-confirmed. sppp_print_bytes VLA hexstr[len] but hexncpy writes 3len -> 2len stack overflow. Pre-auth LCP. Needs sppp interface.