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)
PoC verification
Evidence pack
findings/poc/DF-0457 Β· 11 files| File | Type | Description | Size | |
|---|---|---|---|---|
| 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 |
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_testablenot_testable (root-only reach); fix.diff applies + compiles.
not_testable (root-only reach); fix.diff applies + compiles.
Confirmed kernel references
- s
- y
- s
- /
- n
- e
- t
- g
- r
- a
- p
- h
- /
- p
- p
- p
- o
- e
- /
- n
- g
- _
- p
- p
- p
- o
- e
- .
- c
- :
- 9
- 2
- 5
- s
- y
- s
- /
- n
- e
- t
- g
- r
- a
- p
- h
- /
- p
- p
- p
- o
- e
- /
- n
- g
- _
- p
- p
- p
- o
- e
- .
- c
- :
- 2
- 8
- 6
- s
- y
- s
- /
- n
- e
- t
- g
- r
- a
- p
- h
- /
- p
- p
- p
- o
- e
- /
- n
- g
- _
- p
- p
- p
- o
- e
- .
- c
- :
- 9
- 6
- 8
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.
No comments yet.