psp_dev_rcv() documents that it does not support optional PSP fields but never enforces it. The helper unconditionally strips a fixed PSP_ENCAP_HLEN, so a frame whose PSP header carries options is silently mis-decapsulated: option bytes spill into the inner packet head and parsing fails downstream on a corrupted skb instead of being rejected early. Validate hdrlen, crypt_offset and PSPHDR_VERFL_VIRT, and hoist the psph read above skb_ext_add() so rejected packets do not pick up an SKB_EXT_PSP extension only to drop it. Both in-tree callers gate on hardware-validated, opt-less PSP, so this is hardening rather than a reachable corruption path. Fixes: 0eddb8023cee ("psp: provide decapsulation and receive helper for drivers") Cc: stable@vger.kernel.org Signed-off-by: David Carlier --- net/psp/psp_main.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/net/psp/psp_main.c b/net/psp/psp_main.c index 524978dfb8fd..53d7e14c054a 100644 --- a/net/psp/psp_main.c +++ b/net/psp/psp_main.c @@ -321,12 +321,20 @@ int psp_dev_rcv(struct sk_buff *skb, u16 dev_id, u8 generation, bool strip_icv) if (unlikely(uh->dest != htons(PSP_DEFAULT_UDP_PORT))) return -EINVAL; + psph = (struct psphdr *)(skb->data + l2_hlen + l3_hlen + + sizeof(struct udphdr)); + + /* Fixed-length decap; reject optional fields rather than mis-decapsulate. */ + + if (unlikely(psph->hdrlen != PSP_HDRLEN_NOOPT || + psph->crypt_offset || + (psph->verfl & PSPHDR_VERFL_VIRT))) + return -EINVAL; + pse = skb_ext_add(skb, SKB_EXT_PSP); if (!pse) return -EINVAL; - psph = (struct psphdr *)(skb->data + l2_hlen + l3_hlen + - sizeof(struct udphdr)); pse->spi = psph->spi; pse->dev_id = dev_id; pse->generation = generation; -- 2.53.0