summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 f069117c867a..524978dfb8fd 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);
}