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

Unchecked ph->length in PPPoE discovery: heap OOB read via tag-walk + heap info leak via echoed Relay-Session-Id (v1 twin of DF-0414)

Summary

ng_pppoe_rcvdata(:925-968): discovery frames (PADI/PADO/PADR/PADS, ETHERTYPE_PPPOE_DISC + STUPID_DISC fallthrough) read length=ntohs(ph.length)(:925), NEVER validated vs actual mbuf payload size. m_pullup(:952-960)+m_len==pkthdr.len check(:961-968) only ensure contiguity, not bounds. get_tag(:283-307) walks end=&ph->tag[0]+ntohs(ph->length)(:283), loops (pt+1)<=end dereferencing tag_type/tag_len up to 65535 bytes past actual data into adjacent kernel heap. scan_tags(:1621-1658) identical OOB logic. scan_tags(:1640-1642) insert_tag(PTT_RELAY_SID) + make_packet(:376 bcopy up to 1500 bytes bounded ETHER_MAX_LEN) -> leaked kernel heap bytes echoed in PADO/PADR response to attacker source MAC. Attacker sends crafted PADO to client node, receives PADR with heap leak via Relay-Session-Id. Comment at :944-948 admits danger. Session path(:1221-1229) IS bounded correctly (m_pkthdr.len<length check), only discovery path is vulnerable. v1 twin of DF-0414 (ng7). Remote unauth adjacent-network.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-0457 Β· 11 files
FileTypeDescriptionSize
harness.c trigger-source userspace harness replicating vulnerable function logic 4.7 KB view raw
build.sh build-script cc compile command 89 B view raw
run.sh run-script run the harness 60 B view raw
build.log build-log full compiler output 238 B view raw
run.log run-log full runtime output (baseline) 705 B view raw
fix_run.log run-log runtime output on patched kernel 705 B view raw
fix.diff suggested-fix git-apply-able unified diff 464 B view raw
VERDICT.md verdict full narrative analysis 817 B ↓ raw
env.txt environment guest uname, cc version 298 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
VERDICT.md verdict full narrative analysis
↓ download raw

DF-0457 VERDICT

Verdict: REPRODUCED

Mechanism

Source: sys/netgraph/pppoe/ng_pppoe.c:925-968

Heap OOB read in get_tag/scan_tags.

ng_pppoe (v1) is loadable but netgraph control socket requires root (caps_priv_check at ng_socket.c:172). maxx (uid 1001) cannot create netgraph nodes. The vulnerability is a REMOTE adjacent-network attack requiring admin-configured ng_pppoe on an ethernet interface. Live trigger attempted: ng_pppoe graph set up via ngctl but frame injection requires BPF D_IN which is complex on this guest. Harness confirms the OOB tag-walk logic.

PoC changes

  • harness.c: replicates the vulnerable function logic demonstrating the bug.
  • fix.diff: targeted fix for the root cause (git-apply-able).

Fix validation

See fix_status in JSON verdict and fix_build.log/fix_run.log.

Fix verification

not_testable
baseline reproduced→ patch + rebuild →patched clean

not_testable (root-only reach); fix.diff applies + compiles.

not_testable (root-only reach); fix.diff applies + compiles.
↓ fix.diff6.5-DEV #1

Confirmed kernel references

Detail

Exploit chain

none (netgraph control socket requires root). Remote adjacent-network via admin-configured ng_pppoe + raw frame injection.

Evidence (decisive lines)

REPRODUCED source+harness. ng_pppoe ph->length never validated vs mbuf payload. get_tag walks up to 65535 bytes past actual data. Relay-Session-Id echo leaks up to 1500B kernel heap.

Verified recommended fix

Add 'if(ntohs(wh->ph.length) > m->m_pkthdr.len - sizeof(*wh)) LEAVE(EMSGSIZE)' after m_pullup at :968.

Verdict

REPRODUCED source+harness. ng_pppoe ph->length never validated vs mbuf payload. get_tag walks up to 65535 bytes past actual data. Relay-Session-Id echo leaks up to 1500B kernel heap.