diff options
| author | Jakub Kicinski <kuba@kernel.org> | 2026-04-30 02:55:57 +0300 |
|---|---|---|
| committer | Jakub Kicinski <kuba@kernel.org> | 2026-04-30 02:55:59 +0300 |
| commit | 776059b70231bd235493d68ae77d12df65d8dfe7 (patch) | |
| tree | ee106e2fc0878e69a01d518440fb465570f281e1 | |
| parent | 1656f1788342a05eb9c8fc30ebfb1f9f674fcce7 (diff) | |
| parent | c2b22277ad897d21341f502f87fccd905ff4e207 (diff) | |
| download | linux-776059b70231bd235493d68ae77d12df65d8dfe7.tar.xz | |
Merge branch 'net-psp-add-more-validation'
Jakub Kicinski says:
====================
net: psp: add more validation
Address some AI code-scan issues with the PSP code.
I don't think any of these are real bugs, but they may
become bugs in the future. The two real bugs discovered
were posted separately for net. AI reports 3 more which
seem plain wrong (rx SPI "leak" on error etc.).
====================
Link: https://patch.msgid.link/20260428205352.1247325-1-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
| -rw-r--r-- | net/psp/psp_main.c | 21 |
1 files changed, 18 insertions, 3 deletions
diff --git a/net/psp/psp_main.c b/net/psp/psp_main.c index 9508b6c38003..524978dfb8fd 100644 --- a/net/psp/psp_main.c +++ b/net/psp/psp_main.c @@ -90,6 +90,10 @@ psp_dev_create(struct net_device *netdev, mutex_lock(&psd->lock); mutex_unlock(&psp_devs_lock); + /* notify before netdev assignment + * There's no strong reason for it, but thinking is to avoid creating + * implicit expectations about the PSP dev <> netdev relationship. + */ psp_nl_notify_dev(psd, PSP_CMD_DEV_ADD_NTF); rcu_assign_pointer(netdev->psp_dev, psd); @@ -228,6 +232,10 @@ bool psp_dev_encapsulate(struct net *net, struct sk_buff *skb, __be32 spi, u32 ethr_len = skb_mac_header_len(skb); u32 bufflen = ethr_len + network_len; + if (skb->protocol != htons(ETH_P_IP) && + skb->protocol != htons(ETH_P_IPV6)) + return false; + if (skb_cow_head(skb, PSP_ENCAP_HLEN)) return false; @@ -243,11 +251,9 @@ bool psp_dev_encapsulate(struct net *net, struct sk_buff *skb, __be32 spi, ip_hdr(skb)->check = 0; ip_hdr(skb)->check = ip_fast_csum((u8 *)ip_hdr(skb), ip_hdr(skb)->ihl); - } else if (skb->protocol == htons(ETH_P_IPV6)) { + } else { ipv6_hdr(skb)->nexthdr = IPPROTO_UDP; be16_add_cpu(&ipv6_hdr(skb)->payload_len, PSP_ENCAP_HLEN); - } else { - return false; } skb_set_inner_ipproto(skb, IPPROTO_TCP); @@ -294,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) && @@ -329,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; @@ -336,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); } |
