aboutsummaryrefslogtreecommitdiffstats
diff options
authorJakub Kicinski <kuba@kernel.org>2026-04-28 13:53:52 -0700
committerJakub Kicinski <kuba@kernel.org>2026-04-29 16:55:55 -0700
commitc2b22277ad897d21341f502f87fccd905ff4e207 (patch)
treeee106e2fc0878e69a01d518440fb465570f281e1
parent5637fcb11c9128283db598ff398924d910c73143 (diff)
downloadlinux-next-c2b22277ad897d21341f502f87fccd905ff4e207.tar.gz
psp: validate IPv4 header fields in psp_dev_rcv()
psp_dev_rcv() is called from the NIC driver's RX completion path before the frame reaches ip_rcv_core(), so the IP header has not been validated in SW, yet. We expect that the device has done all this validation, but let's also add the SW checks, to avoid surprises. Reviewed-by: Eric Dumazet <edumazet@google.com> Reviewed-by: Willem de Bruijn <willemb@google.com> Link: https://patch.msgid.link/20260428205352.1247325-4-kuba@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-rw-r--r--net/psp/psp_main.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/net/psp/psp_main.c b/net/psp/psp_main.c
index f069117c867ae..524978dfb8fd1 100644
--- a/net/psp/psp_main.c
+++ b/net/psp/psp_main.c
@@ -300,6 +300,9 @@ int psp_dev_rcv(struct sk_buff *skb, u16 dev_id, u8 generation, bool strip_icv)
if (proto == htons(ETH_P_IP)) {
struct iphdr *iph = (struct iphdr *)(skb->data + l2_hlen);
+ if (unlikely(iph->ihl < 5))
+ return -EINVAL;
+
is_udp = iph->protocol == IPPROTO_UDP;
l3_hlen = iph->ihl * 4;
if (l3_hlen != sizeof(struct iphdr) &&
@@ -335,6 +338,9 @@ int psp_dev_rcv(struct sk_buff *skb, u16 dev_id, u8 generation, bool strip_icv)
if (proto == htons(ETH_P_IP)) {
struct iphdr *iph = (struct iphdr *)(skb->data + l2_hlen);
+ if (unlikely(ntohs(iph->tot_len) < l3_hlen + encap))
+ return -EINVAL;
+
iph->protocol = psph->nexthdr;
iph->tot_len = htons(ntohs(iph->tot_len) - encap);
iph->check = 0;
@@ -342,6 +348,9 @@ int psp_dev_rcv(struct sk_buff *skb, u16 dev_id, u8 generation, bool strip_icv)
} else {
struct ipv6hdr *ipv6h = (struct ipv6hdr *)(skb->data + l2_hlen);
+ if (unlikely(ntohs(ipv6h->payload_len) < encap))
+ return -EINVAL;
+
ipv6h->nexthdr = psph->nexthdr;
ipv6h->payload_len = htons(ntohs(ipv6h->payload_len) - encap);
}