* [PATCH ipsec] esp4: add length check for UDP encapsulation
@ 2019-03-25 13:30 Sabrina Dubroca
2019-03-27 8:24 ` Steffen Klassert
0 siblings, 1 reply; 2+ messages in thread
From: Sabrina Dubroca @ 2019-03-25 13:30 UTC (permalink / raw)
To: netdev; +Cc: Steffen Klassert, Sabrina Dubroca
esp_output_udp_encap can produce a length that doesn't fit in the 16
bits of a UDP header's length field. In that case, we'll send a
fragmented packet whose length is larger than IP_MAX_MTU (resulting in
"Oversized IP packet" warnings on receive) and with a bogus UDP
length.
To prevent this, add a length check to esp_output_udp_encap and return
-EMSGSIZE on failure.
This seems to be older than git history.
Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
---
net/ipv4/esp4.c | 20 +++++++++++++++-----
1 file changed, 15 insertions(+), 5 deletions(-)
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 10e809b296ec..fb065a8937ea 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -226,7 +226,7 @@ static void esp_output_fill_trailer(u8 *tail, int tfclen, int plen, __u8 proto)
tail[plen - 1] = proto;
}
-static void esp_output_udp_encap(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *esp)
+static int esp_output_udp_encap(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *esp)
{
int encap_type;
struct udphdr *uh;
@@ -234,6 +234,7 @@ static void esp_output_udp_encap(struct xfrm_state *x, struct sk_buff *skb, stru
__be16 sport, dport;
struct xfrm_encap_tmpl *encap = x->encap;
struct ip_esp_hdr *esph = esp->esph;
+ unsigned int len;
spin_lock_bh(&x->lock);
sport = encap->encap_sport;
@@ -241,11 +242,14 @@ static void esp_output_udp_encap(struct xfrm_state *x, struct sk_buff *skb, stru
encap_type = encap->encap_type;
spin_unlock_bh(&x->lock);
+ len = skb->len + esp->tailen - skb_transport_offset(skb);
+ if (len + sizeof(struct iphdr) >= IP_MAX_MTU)
+ return -EMSGSIZE;
+
uh = (struct udphdr *)esph;
uh->source = sport;
uh->dest = dport;
- uh->len = htons(skb->len + esp->tailen
- - skb_transport_offset(skb));
+ uh->len = htons(len);
uh->check = 0;
switch (encap_type) {
@@ -262,6 +266,8 @@ static void esp_output_udp_encap(struct xfrm_state *x, struct sk_buff *skb, stru
*skb_mac_header(skb) = IPPROTO_UDP;
esp->esph = esph;
+
+ return 0;
}
int esp_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *esp)
@@ -275,8 +281,12 @@ int esp_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *
int tailen = esp->tailen;
/* this is non-NULL only with UDP Encapsulation */
- if (x->encap)
- esp_output_udp_encap(x, skb, esp);
+ if (x->encap) {
+ int err = esp_output_udp_encap(x, skb, esp);
+
+ if (err < 0)
+ return err;
+ }
if (!skb_cloned(skb)) {
if (tailen <= skb_tailroom(skb)) {
--
2.21.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH ipsec] esp4: add length check for UDP encapsulation
2019-03-25 13:30 [PATCH ipsec] esp4: add length check for UDP encapsulation Sabrina Dubroca
@ 2019-03-27 8:24 ` Steffen Klassert
0 siblings, 0 replies; 2+ messages in thread
From: Steffen Klassert @ 2019-03-27 8:24 UTC (permalink / raw)
To: Sabrina Dubroca; +Cc: netdev
On Mon, Mar 25, 2019 at 02:30:00PM +0100, Sabrina Dubroca wrote:
> esp_output_udp_encap can produce a length that doesn't fit in the 16
> bits of a UDP header's length field. In that case, we'll send a
> fragmented packet whose length is larger than IP_MAX_MTU (resulting in
> "Oversized IP packet" warnings on receive) and with a bogus UDP
> length.
>
> To prevent this, add a length check to esp_output_udp_encap and return
> -EMSGSIZE on failure.
>
> This seems to be older than git history.
>
> Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
Applied, thanks a lot Sabrina!
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2019-03-27 8:24 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-03-25 13:30 [PATCH ipsec] esp4: add length check for UDP encapsulation Sabrina Dubroca
2019-03-27 8:24 ` Steffen Klassert
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.