]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/5.0.19/esp4-add-length-check-for-udp-encapsulation.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 5.0.19 / esp4-add-length-check-for-udp-encapsulation.patch
CommitLineData
e6832405
SL
1From 60da21ec12c68ca002b06d936fb35ce1b2c4e3be Mon Sep 17 00:00:00 2001
2From: Sabrina Dubroca <sd@queasysnail.net>
3Date: Mon, 25 Mar 2019 14:30:00 +0100
4Subject: esp4: add length check for UDP encapsulation
5
6[ Upstream commit 8dfb4eba4100e7cdd161a8baef2d8d61b7a7e62e ]
7
8esp_output_udp_encap can produce a length that doesn't fit in the 16
9bits of a UDP header's length field. In that case, we'll send a
10fragmented packet whose length is larger than IP_MAX_MTU (resulting in
11"Oversized IP packet" warnings on receive) and with a bogus UDP
12length.
13
14To prevent this, add a length check to esp_output_udp_encap and return
15 -EMSGSIZE on failure.
16
17This seems to be older than git history.
18
19Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
20Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
21Signed-off-by: Sasha Levin <sashal@kernel.org>
22---
23 net/ipv4/esp4.c | 20 +++++++++++++++-----
24 1 file changed, 15 insertions(+), 5 deletions(-)
25
26diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
27index 10e809b296ec8..fb065a8937ea2 100644
28--- a/net/ipv4/esp4.c
29+++ b/net/ipv4/esp4.c
30@@ -226,7 +226,7 @@ static void esp_output_fill_trailer(u8 *tail, int tfclen, int plen, __u8 proto)
31 tail[plen - 1] = proto;
32 }
33
34-static void esp_output_udp_encap(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *esp)
35+static int esp_output_udp_encap(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *esp)
36 {
37 int encap_type;
38 struct udphdr *uh;
39@@ -234,6 +234,7 @@ static void esp_output_udp_encap(struct xfrm_state *x, struct sk_buff *skb, stru
40 __be16 sport, dport;
41 struct xfrm_encap_tmpl *encap = x->encap;
42 struct ip_esp_hdr *esph = esp->esph;
43+ unsigned int len;
44
45 spin_lock_bh(&x->lock);
46 sport = encap->encap_sport;
47@@ -241,11 +242,14 @@ static void esp_output_udp_encap(struct xfrm_state *x, struct sk_buff *skb, stru
48 encap_type = encap->encap_type;
49 spin_unlock_bh(&x->lock);
50
51+ len = skb->len + esp->tailen - skb_transport_offset(skb);
52+ if (len + sizeof(struct iphdr) >= IP_MAX_MTU)
53+ return -EMSGSIZE;
54+
55 uh = (struct udphdr *)esph;
56 uh->source = sport;
57 uh->dest = dport;
58- uh->len = htons(skb->len + esp->tailen
59- - skb_transport_offset(skb));
60+ uh->len = htons(len);
61 uh->check = 0;
62
63 switch (encap_type) {
64@@ -262,6 +266,8 @@ static void esp_output_udp_encap(struct xfrm_state *x, struct sk_buff *skb, stru
65
66 *skb_mac_header(skb) = IPPROTO_UDP;
67 esp->esph = esph;
68+
69+ return 0;
70 }
71
72 int esp_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *esp)
73@@ -275,8 +281,12 @@ int esp_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *
74 int tailen = esp->tailen;
75
76 /* this is non-NULL only with UDP Encapsulation */
77- if (x->encap)
78- esp_output_udp_encap(x, skb, esp);
79+ if (x->encap) {
80+ int err = esp_output_udp_encap(x, skb, esp);
81+
82+ if (err < 0)
83+ return err;
84+ }
85
86 if (!skb_cloned(skb)) {
87 if (tailen <= skb_tailroom(skb)) {
88--
892.20.1
90