CVE-2026-46306
Description
Linux kernel flow dissector mishandles PPPoE PFC frames, potentially causing unaligned access exceptions.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Linux kernel flow dissector mishandles PPPoE PFC frames, potentially causing unaligned access exceptions.
Vulnerability
The Linux kernel's flow dissector driver incorrectly handled Protocol Field Compression (PFC) frames in PPPoE, contrary to RFC 2516 recommendations. The driver assumed uncompressed frames, but when PFC is used, the compressed 1-byte protocol field shifts the PPP payload by one byte. This misalignment can lead to a 4-byte misalignment for the network header and an unaligned access exception on certain architectures, such as MIPS. This issue affects versions of the Linux kernel prior to the fix committed on the git.kernel.org stable tree [1].
Exploitation
An attacker can trigger this vulnerability by sending a PPPoE PFC frame to an Ethernet interface of a vulnerable system, specifically a MIPS board with RPS enabled. Crucially, no active PPPoE session is required on the interface for the vulnerability to be triggered. The provided crash dump indicates the exception occurs within __skb_flow_dissect and __skb_get_hash_net functions [1].
Impact
Successful exploitation of this vulnerability results in an unaligned access exception, leading to a kernel crash. This crash can cause a denial of service (DoS) for the affected system. The scope of the compromise is limited to the kernel itself, as it does not grant an attacker elevated privileges or direct control over the system, but rather causes it to become unresponsive.
Mitigation
The vulnerability has been resolved in the Linux kernel. The specific commit that addresses this issue can be found on the git.kernel.org stable tree [1]. Users are advised to update to a fixed version of the Linux kernel as soon as possible. No workarounds are described in the available references, and the End-of-Life (EOL) status or Known Exploited Vulnerabilities (KEV) listing for this issue is not yet disclosed.
AI Insight generated on Jun 8, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
2Patches
16d6c19b31a3c1flow_dissector: do not dissect PPPoE PFC frames
1 file changed · +5 −9
net/core/flow_dissector.c+5 −9 modifieddiff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index 1b61bb25ba0e5..2a98f5fa74eb0 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -1374,16 +1374,13 @@ proto_again: break; } - /* least significant bit of the most significant octet - * indicates if protocol field was compressed + /* PFC (compressed 1-byte protocol) frames are not processed. + * A compressed protocol field has the least significant bit of + * the most significant octet set, which will fail the following + * ppp_proto_is_valid(), returning FLOW_DISSECT_RET_OUT_BAD. */ ppp_proto = ntohs(hdr->proto); - if (ppp_proto & 0x0100) { - ppp_proto = ppp_proto >> 8; - nhoff += PPPOE_SES_HLEN - 1; - } else { - nhoff += PPPOE_SES_HLEN; - } + nhoff += PPPOE_SES_HLEN; if (ppp_proto == PPP_IP) { proto = htons(ETH_P_IP); -- cgit 1.3-korg
e7c811ca372dflow_dissector: do not dissect PPPoE PFC frames
1 file changed · +5 −9
net/core/flow_dissector.c+5 −9 modifieddiff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index c3d64e2d59295..86eb489ee76e0 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -1229,16 +1229,13 @@ proto_again: break; } - /* least significant bit of the most significant octet - * indicates if protocol field was compressed + /* PFC (compressed 1-byte protocol) frames are not processed. + * A compressed protocol field has the least significant bit of + * the most significant octet set, which will fail the following + * ppp_proto_is_valid(), returning FLOW_DISSECT_RET_OUT_BAD. */ ppp_proto = ntohs(hdr->proto); - if (ppp_proto & 0x0100) { - ppp_proto = ppp_proto >> 8; - nhoff += PPPOE_SES_HLEN - 1; - } else { - nhoff += PPPOE_SES_HLEN; - } + nhoff += PPPOE_SES_HLEN; if (ppp_proto == PPP_IP) { proto = htons(ETH_P_IP); -- cgit 1.3-korg
db104b0d8a78flow_dissector: do not dissect PPPoE PFC frames
1 file changed · +5 −9
net/core/flow_dissector.c+5 −9 modifieddiff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index aafa754b6cbab..9432e5362b44f 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -1350,16 +1350,13 @@ proto_again: break; } - /* least significant bit of the most significant octet - * indicates if protocol field was compressed + /* PFC (compressed 1-byte protocol) frames are not processed. + * A compressed protocol field has the least significant bit of + * the most significant octet set, which will fail the following + * ppp_proto_is_valid(), returning FLOW_DISSECT_RET_OUT_BAD. */ ppp_proto = ntohs(hdr->proto); - if (ppp_proto & 0x0100) { - ppp_proto = ppp_proto >> 8; - nhoff += PPPOE_SES_HLEN - 1; - } else { - nhoff += PPPOE_SES_HLEN; - } + nhoff += PPPOE_SES_HLEN; if (ppp_proto == PPP_IP) { proto = htons(ETH_P_IP); -- cgit 1.3-korg
18ae9eacfc95flow_dissector: do not dissect PPPoE PFC frames
1 file changed · +5 −9
net/core/flow_dissector.c+5 −9 modifieddiff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index 5f50e182acd57..77c65b2968a37 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -1270,16 +1270,13 @@ proto_again: break; } - /* least significant bit of the most significant octet - * indicates if protocol field was compressed + /* PFC (compressed 1-byte protocol) frames are not processed. + * A compressed protocol field has the least significant bit of + * the most significant octet set, which will fail the following + * ppp_proto_is_valid(), returning FLOW_DISSECT_RET_OUT_BAD. */ ppp_proto = ntohs(hdr->proto); - if (ppp_proto & 0x0100) { - ppp_proto = ppp_proto >> 8; - nhoff += PPPOE_SES_HLEN - 1; - } else { - nhoff += PPPOE_SES_HLEN; - } + nhoff += PPPOE_SES_HLEN; if (ppp_proto == PPP_IP) { proto = htons(ETH_P_IP); -- cgit 1.3-korg
6044392d9cacflow_dissector: do not dissect PPPoE PFC frames
1 file changed · +5 −9
net/core/flow_dissector.c+5 −9 modifieddiff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index 9cd8de6bebb54..8be2ef8088be2 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -1374,16 +1374,13 @@ proto_again: break; } - /* least significant bit of the most significant octet - * indicates if protocol field was compressed + /* PFC (compressed 1-byte protocol) frames are not processed. + * A compressed protocol field has the least significant bit of + * the most significant octet set, which will fail the following + * ppp_proto_is_valid(), returning FLOW_DISSECT_RET_OUT_BAD. */ ppp_proto = ntohs(hdr->proto); - if (ppp_proto & 0x0100) { - ppp_proto = ppp_proto >> 8; - nhoff += PPPOE_SES_HLEN - 1; - } else { - nhoff += PPPOE_SES_HLEN; - } + nhoff += PPPOE_SES_HLEN; if (ppp_proto == PPP_IP) { proto = htons(ETH_P_IP); -- cgit 1.3-korg
abc5bc84e0f2flow_dissector: do not dissect PPPoE PFC frames
1 file changed · +5 −9
net/core/flow_dissector.c+5 −9 modifieddiff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index 164de39fd262c..7ab80767d94c3 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -1239,16 +1239,13 @@ proto_again: break; } - /* least significant bit of the most significant octet - * indicates if protocol field was compressed + /* PFC (compressed 1-byte protocol) frames are not processed. + * A compressed protocol field has the least significant bit of + * the most significant octet set, which will fail the following + * ppp_proto_is_valid(), returning FLOW_DISSECT_RET_OUT_BAD. */ ppp_proto = ntohs(hdr->proto); - if (ppp_proto & 0x0100) { - ppp_proto = ppp_proto >> 8; - nhoff += PPPOE_SES_HLEN - 1; - } else { - nhoff += PPPOE_SES_HLEN; - } + nhoff += PPPOE_SES_HLEN; if (ppp_proto == PPP_IP) { proto = htons(ETH_P_IP); -- cgit 1.3-korg
7c93f353eab4flow_dissector: do not dissect PPPoE PFC frames
1 file changed · +5 −9
net/core/flow_dissector.c+5 −9 modifieddiff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index 1b61bb25ba0e5..2a98f5fa74eb0 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -1374,16 +1374,13 @@ proto_again: break; } - /* least significant bit of the most significant octet - * indicates if protocol field was compressed + /* PFC (compressed 1-byte protocol) frames are not processed. + * A compressed protocol field has the least significant bit of + * the most significant octet set, which will fail the following + * ppp_proto_is_valid(), returning FLOW_DISSECT_RET_OUT_BAD. */ ppp_proto = ntohs(hdr->proto); - if (ppp_proto & 0x0100) { - ppp_proto = ppp_proto >> 8; - nhoff += PPPOE_SES_HLEN - 1; - } else { - nhoff += PPPOE_SES_HLEN; - } + nhoff += PPPOE_SES_HLEN; if (ppp_proto == PPP_IP) { proto = htons(ETH_P_IP); -- cgit 1.3-korg
0d00b9015069flow_dissector: do not dissect PPPoE PFC frames
1 file changed · +5 −9
net/core/flow_dissector.c+5 −9 modifieddiff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index 1b61bb25ba0e5..2a98f5fa74eb0 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -1374,16 +1374,13 @@ proto_again: break; } - /* least significant bit of the most significant octet - * indicates if protocol field was compressed + /* PFC (compressed 1-byte protocol) frames are not processed. + * A compressed protocol field has the least significant bit of + * the most significant octet set, which will fail the following + * ppp_proto_is_valid(), returning FLOW_DISSECT_RET_OUT_BAD. */ ppp_proto = ntohs(hdr->proto); - if (ppp_proto & 0x0100) { - ppp_proto = ppp_proto >> 8; - nhoff += PPPOE_SES_HLEN - 1; - } else { - nhoff += PPPOE_SES_HLEN; - } + nhoff += PPPOE_SES_HLEN; if (ppp_proto == PPP_IP) { proto = htons(ETH_P_IP); -- cgit 1.3-korg
abc5bc84e0f2flow_dissector: do not dissect PPPoE PFC frames
1 file changed · +5 −9
net/core/flow_dissector.c+5 −9 modifieddiff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index 164de39fd262c..7ab80767d94c3 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -1239,16 +1239,13 @@ proto_again: break; } - /* least significant bit of the most significant octet - * indicates if protocol field was compressed + /* PFC (compressed 1-byte protocol) frames are not processed. + * A compressed protocol field has the least significant bit of + * the most significant octet set, which will fail the following + * ppp_proto_is_valid(), returning FLOW_DISSECT_RET_OUT_BAD. */ ppp_proto = ntohs(hdr->proto); - if (ppp_proto & 0x0100) { - ppp_proto = ppp_proto >> 8; - nhoff += PPPOE_SES_HLEN - 1; - } else { - nhoff += PPPOE_SES_HLEN; - } + nhoff += PPPOE_SES_HLEN; if (ppp_proto == PPP_IP) { proto = htons(ETH_P_IP); -- cgit 1.3-korg
e7c811ca372dflow_dissector: do not dissect PPPoE PFC frames
1 file changed · +5 −9
net/core/flow_dissector.c+5 −9 modifieddiff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index c3d64e2d59295..86eb489ee76e0 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -1229,16 +1229,13 @@ proto_again: break; } - /* least significant bit of the most significant octet - * indicates if protocol field was compressed + /* PFC (compressed 1-byte protocol) frames are not processed. + * A compressed protocol field has the least significant bit of + * the most significant octet set, which will fail the following + * ppp_proto_is_valid(), returning FLOW_DISSECT_RET_OUT_BAD. */ ppp_proto = ntohs(hdr->proto); - if (ppp_proto & 0x0100) { - ppp_proto = ppp_proto >> 8; - nhoff += PPPOE_SES_HLEN - 1; - } else { - nhoff += PPPOE_SES_HLEN; - } + nhoff += PPPOE_SES_HLEN; if (ppp_proto == PPP_IP) { proto = htons(ETH_P_IP); -- cgit 1.3-korg
d6c19b31a3c1flow_dissector: do not dissect PPPoE PFC frames
1 file changed · +5 −9
net/core/flow_dissector.c+5 −9 modifieddiff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index 1b61bb25ba0e5..2a98f5fa74eb0 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -1374,16 +1374,13 @@ proto_again: break; } - /* least significant bit of the most significant octet - * indicates if protocol field was compressed + /* PFC (compressed 1-byte protocol) frames are not processed. + * A compressed protocol field has the least significant bit of + * the most significant octet set, which will fail the following + * ppp_proto_is_valid(), returning FLOW_DISSECT_RET_OUT_BAD. */ ppp_proto = ntohs(hdr->proto); - if (ppp_proto & 0x0100) { - ppp_proto = ppp_proto >> 8; - nhoff += PPPOE_SES_HLEN - 1; - } else { - nhoff += PPPOE_SES_HLEN; - } + nhoff += PPPOE_SES_HLEN; if (ppp_proto == PPP_IP) { proto = htons(ETH_P_IP); -- cgit 1.3-korg
db104b0d8a78flow_dissector: do not dissect PPPoE PFC frames
1 file changed · +5 −9
net/core/flow_dissector.c+5 −9 modifieddiff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index aafa754b6cbab..9432e5362b44f 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -1350,16 +1350,13 @@ proto_again: break; } - /* least significant bit of the most significant octet - * indicates if protocol field was compressed + /* PFC (compressed 1-byte protocol) frames are not processed. + * A compressed protocol field has the least significant bit of + * the most significant octet set, which will fail the following + * ppp_proto_is_valid(), returning FLOW_DISSECT_RET_OUT_BAD. */ ppp_proto = ntohs(hdr->proto); - if (ppp_proto & 0x0100) { - ppp_proto = ppp_proto >> 8; - nhoff += PPPOE_SES_HLEN - 1; - } else { - nhoff += PPPOE_SES_HLEN; - } + nhoff += PPPOE_SES_HLEN; if (ppp_proto == PPP_IP) { proto = htons(ETH_P_IP); -- cgit 1.3-korg
7c93f353eab4flow_dissector: do not dissect PPPoE PFC frames
1 file changed · +5 −9
net/core/flow_dissector.c+5 −9 modifieddiff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index 1b61bb25ba0e5..2a98f5fa74eb0 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -1374,16 +1374,13 @@ proto_again: break; } - /* least significant bit of the most significant octet - * indicates if protocol field was compressed + /* PFC (compressed 1-byte protocol) frames are not processed. + * A compressed protocol field has the least significant bit of + * the most significant octet set, which will fail the following + * ppp_proto_is_valid(), returning FLOW_DISSECT_RET_OUT_BAD. */ ppp_proto = ntohs(hdr->proto); - if (ppp_proto & 0x0100) { - ppp_proto = ppp_proto >> 8; - nhoff += PPPOE_SES_HLEN - 1; - } else { - nhoff += PPPOE_SES_HLEN; - } + nhoff += PPPOE_SES_HLEN; if (ppp_proto == PPP_IP) { proto = htons(ETH_P_IP); -- cgit 1.3-korg
6044392d9cacflow_dissector: do not dissect PPPoE PFC frames
1 file changed · +5 −9
net/core/flow_dissector.c+5 −9 modifieddiff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index 9cd8de6bebb54..8be2ef8088be2 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -1374,16 +1374,13 @@ proto_again: break; } - /* least significant bit of the most significant octet - * indicates if protocol field was compressed + /* PFC (compressed 1-byte protocol) frames are not processed. + * A compressed protocol field has the least significant bit of + * the most significant octet set, which will fail the following + * ppp_proto_is_valid(), returning FLOW_DISSECT_RET_OUT_BAD. */ ppp_proto = ntohs(hdr->proto); - if (ppp_proto & 0x0100) { - ppp_proto = ppp_proto >> 8; - nhoff += PPPOE_SES_HLEN - 1; - } else { - nhoff += PPPOE_SES_HLEN; - } + nhoff += PPPOE_SES_HLEN; if (ppp_proto == PPP_IP) { proto = htons(ETH_P_IP); -- cgit 1.3-korg
18ae9eacfc95flow_dissector: do not dissect PPPoE PFC frames
1 file changed · +5 −9
net/core/flow_dissector.c+5 −9 modifieddiff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index 5f50e182acd57..77c65b2968a37 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -1270,16 +1270,13 @@ proto_again: break; } - /* least significant bit of the most significant octet - * indicates if protocol field was compressed + /* PFC (compressed 1-byte protocol) frames are not processed. + * A compressed protocol field has the least significant bit of + * the most significant octet set, which will fail the following + * ppp_proto_is_valid(), returning FLOW_DISSECT_RET_OUT_BAD. */ ppp_proto = ntohs(hdr->proto); - if (ppp_proto & 0x0100) { - ppp_proto = ppp_proto >> 8; - nhoff += PPPOE_SES_HLEN - 1; - } else { - nhoff += PPPOE_SES_HLEN; - } + nhoff += PPPOE_SES_HLEN; if (ppp_proto == PPP_IP) { proto = htons(ETH_P_IP); -- cgit 1.3-korg
0d00b9015069flow_dissector: do not dissect PPPoE PFC frames
1 file changed · +5 −9
net/core/flow_dissector.c+5 −9 modifieddiff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index 1b61bb25ba0e5..2a98f5fa74eb0 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -1374,16 +1374,13 @@ proto_again: break; } - /* least significant bit of the most significant octet - * indicates if protocol field was compressed + /* PFC (compressed 1-byte protocol) frames are not processed. + * A compressed protocol field has the least significant bit of + * the most significant octet set, which will fail the following + * ppp_proto_is_valid(), returning FLOW_DISSECT_RET_OUT_BAD. */ ppp_proto = ntohs(hdr->proto); - if (ppp_proto & 0x0100) { - ppp_proto = ppp_proto >> 8; - nhoff += PPPOE_SES_HLEN - 1; - } else { - nhoff += PPPOE_SES_HLEN; - } + nhoff += PPPOE_SES_HLEN; if (ppp_proto == PPP_IP) { proto = htons(ETH_P_IP); -- cgit 1.3-korg
Vulnerability mechanics
Root cause
"The flow dissector incorrectly handled PPPoE frames with Protocol Field Compression (PFC) enabled, leading to memory misalignment."
Attack vector
An attacker can trigger this vulnerability by sending a PPPoE PFC frame to a network interface on a MIPS board with RPS enabled. This can occur even if no active PPPoE session is established on that interface. The malformed frame causes an unaligned access exception during packet dissection.
Affected code
The vulnerability resides in the `net/core/flow_dissector.c` file, specifically within the logic that handles PPPoE frames. The code previously attempted to decompress the protocol field, leading to incorrect offset calculations for the PPP payload.
What the fix does
The patch modifies the `flow_dissector.c` file to prevent the dissector from processing PPPoE PFC frames. It removes the logic that attempted to handle compressed protocol fields and instead ensures that such frames are not dissected, thus avoiding the memory misalignment and subsequent exception. This aligns with RFC 2516 which discourages PFC for PPPoE [patch_id=5239651].
Preconditions
- configRPS (Receive Packet Steering) must be enabled on the target system.
- networkThe attacker must be able to send network traffic to the affected interface.
Generated on Jun 8, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
8- git.kernel.org/stable/c/0d00b9015069712944934bab09eaa6c542143049nvd
- git.kernel.org/stable/c/18ae9eacfc95cc715c0606b2c86e8aa8a86cf3e3nvd
- git.kernel.org/stable/c/6044392d9cace3a3672b02c8bc7d38b502e51734nvd
- git.kernel.org/stable/c/7c93f353eab4ea911e394630f07d72e040a729d8nvd
- git.kernel.org/stable/c/abc5bc84e0f2edc7ea2d437afa6ef3fe1fc43200nvd
- git.kernel.org/stable/c/d6c19b31a3c1d519fabdcf0aa239e6b6109b9473nvd
- git.kernel.org/stable/c/db104b0d8a7856397c0469d83a4289adf7c54863nvd
- git.kernel.org/stable/c/e7c811ca372d53c2be7d01a1614e71fae1054836nvd
News mentions
2- Google Android SDK: 10 Linux Kernel Vulnerabilities Disclosed TogetherVypr Intelligence · Jun 8, 2026
- Linux Kernel: 25 Vulnerabilities Disclosed in Single Batch on June 8, 2026Vypr Intelligence · Jun 8, 2026