CVE-2026-98158 Overview
CVE-2026-98158 is a Linux kernel vulnerability in the ppp_async driver that corrupts socket buffer (skb) headroom on the receive error path. The flawed error handler in process_input_packet() zeroes the headroom of a reused skb while claiming to restore it to a freshly allocated state. Subsequent calls to skb_push() in ppp_receive_nonmp_frame() then write below skb->head, triggering a skb_under_panic and kernel BUG. A remote peer that sends a malformed frame followed by a crafted follow-up frame can crash the kernel, producing a denial-of-service condition.
Critical Impact
A remote PPP peer can panic the Linux kernel by sending two crafted frames after a root-configured PPP session is established, with a reproducer that triggers the crash in approximately one second.
Affected Products
- Linux kernel versions containing the ppp_async driver prior to the fix commits
- Systems running Point-to-Point Protocol (PPP) over asynchronous transports (serial, pty)
- Distributions shipping the vulnerable drivers/net/ppp/ppp_async.c code path
Discovery Timeline
- 2026-09-25 - CVE-2026-98158 published to the National Vulnerability Database
- 2026-09-30 - Last updated in NVD database
Technical Details for CVE-2026-98158
Vulnerability Analysis
The vulnerability resides in the PPP asynchronous receive path. ppp_receive_nonmp_frame() prepends a two-byte direction tag using skb_push(skb, 2) before executing the Berkeley Packet Filter (BPF) pass and active filters. The receive path assumes the skb always carries at least NET_SKB_PAD bytes of headroom, which dev_alloc_skb() guarantees for freshly allocated buffers.
The error handler in process_input_packet() violates this invariant. On a frame error, the code calls skb_trim(skb, 0) followed by skb_reserve(skb, -skb_headroom(skb)), which zeroes the headroom. The comment claims this restores the skb to a freshly allocated state, but a real fresh skb retains NET_SKB_PAD. Because ap->rpkt still points at this corrupted buffer, the next incoming frame is reassembled into it with zero headroom.
A peer that transmits a bad-FCS frame followed by a frame beginning with ff 03 leaves only a single byte of headroom when the filter tag push occurs. The resulting skb_push() writes one byte below skb->head, triggering skb_under_panic at net/core/skbuff.c:214 and a fatal kernel exception in interrupt context.
Root Cause
The root cause is an incorrect assumption in the error-recovery path about what constitutes a freshly allocated skb. By negating headroom entirely, the error handler breaks the NET_SKB_PAD contract that the rest of the receive path depends on. The same corrupted buffer also causes ppp_decompress_frame() to pass skb->data - 2 to ->decompress() and ->incomp() callbacks when CCP compression is enabled, producing an out-of-bounds read before skb->head.
Attack Vector
Exploitation requires a PPP session configured by a privileged local user, with a malicious or malformed remote peer on the other end of the link. The peer transmits two crafted frames: one with a bad frame check sequence to trigger the error path, followed by a frame whose header reduces available headroom to one byte. The second frame's filter-tag push then writes below skb->head, panicking the kernel. The attack is unauthenticated at the PPP layer once the session is established and can be executed over a pseudo-terminal, serial line, or any asynchronous transport that carries PPP.
No exploitation code is published with the advisory. The upstream commit message references a private fuzzing reproducer (repro-ppp-skb.c) that panics the kernel in approximately one second.
Detection Methods for CVE-2026-98158
Indicators of Compromise
- Kernel panic messages containing skb_under_panic with a call trace through skb_push, ppp_receive_nonmp_frame, ppp_input, and ppp_async_process
- Unexpected system reboots or crashes on hosts running pppd or terminating PPP sessions
- BUG at net/core/skbuff.c:214 with RIP: skb_panic in the kernel log before the crash
- Out-of-bounds read reports from KASAN inside ppp_decompress_frame when CCP is enabled
Detection Strategies
- Audit hosts for loaded ppp_async and ppp_generic kernel modules using lsmod and inventory active PPP interfaces with ip link show type ppp
- Compare running kernel versions against distribution advisories referencing commits 0c53eb14, 71713722, 8dc5d98a, and d0fc3dab
- Enable kernel crash dumps (kdump) so post-crash analysis can confirm the signature when a panic occurs
Monitoring Recommendations
- Forward /var/log/kern.log, dmesg, and journalctl -k output to a centralized log pipeline and alert on skb_under_panic or ppp_receive_nonmp_frame strings
- Monitor PPP session establishment events and correlate them with subsequent kernel instability on the same host
- Track unplanned reboots on systems exposing PPP endpoints and investigate any clustered occurrences
How to Mitigate CVE-2026-98158
Immediate Actions Required
- Apply the upstream Linux kernel patches referenced in the stable tree commits as soon as distribution packages are available
- Restrict which users can configure PPP interfaces by auditing CAP_NET_ADMIN grants and pppd setuid configuration
- Disable PPP services on hosts that do not require them by unloading ppp_async and ppp_generic modules and blacklisting them in /etc/modprobe.d/
Patch Information
The upstream fix drops the errored frame and clears ap->rpkt so the next frame is reassembled into a freshly allocated skb with proper headroom, matching the behavior already present in ppp_synctty. The fix is distributed across the following stable kernel commits: Kernel Git Commit 0c53eb149, Kernel Git Commit 717137221, Kernel Git Commit 8dc5d98a16, and Kernel Git Commit d0fc3dabfe. Rebuild and reboot affected systems after applying the patch.
Workarounds
- Terminate PPP sessions with untrusted peers until the kernel patch is deployed
- Where PPP is required, restrict peers to authenticated and trusted endpoints over physically controlled links
- Unload the ppp_async module on systems that do not actively need asynchronous PPP support
# Prevent ppp_async from loading until patched kernel is deployed
echo 'blacklist ppp_async' | sudo tee /etc/modprobe.d/disable-ppp-async.conf
sudo rmmod ppp_async 2>/dev/null || true
# Verify the module is no longer loaded
lsmod | grep ppp_async
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.