esp: Fix locking on page fragment allocation
authorSteffen Klassert <steffen.klassert@secunet.com>
Fri, 25 Aug 2017 05:16:07 +0000 (07:16 +0200)
committerSteffen Klassert <steffen.klassert@secunet.com>
Fri, 25 Aug 2017 07:26:12 +0000 (09:26 +0200)
We allocate the page fragment for the ESP trailer inside
a spinlock, but consume it outside of the lock. This
is racy as some other cou could get the same page fragment
then. Fix this by consuming the page fragment inside the
lock too.

Fixes: cac2661c53f3 ("esp4: Avoid skb_cow_data whenever possible")
Fixes: 03e2a30f6a27 ("esp6: Avoid skb_cow_data whenever possible")
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
net/ipv4/esp4.c
net/ipv6/esp6.c

index dbb31a942dfa1bef204cc1459dbf1727923e089e..a8ddb95e7f0617838be13e8ed1d5c45a615e253f 100644 (file)
@@ -292,8 +292,6 @@ int esp_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *
 
                        kunmap_atomic(vaddr);
 
-                       spin_unlock_bh(&x->lock);
-
                        nfrags = skb_shinfo(skb)->nr_frags;
 
                        __skb_fill_page_desc(skb, nfrags, page, pfrag->offset,
@@ -301,6 +299,9 @@ int esp_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *
                        skb_shinfo(skb)->nr_frags = ++nfrags;
 
                        pfrag->offset = pfrag->offset + allocsize;
+
+                       spin_unlock_bh(&x->lock);
+
                        nfrags++;
 
                        skb->len += tailen;
index 392def1fcf21e676780d1218ab7049461dbcdf88..4e3fdc8889430ccab861f3eb5e027f297ec1c5ef 100644 (file)
@@ -260,8 +260,6 @@ int esp6_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info
 
                        kunmap_atomic(vaddr);
 
-                       spin_unlock_bh(&x->lock);
-
                        nfrags = skb_shinfo(skb)->nr_frags;
 
                        __skb_fill_page_desc(skb, nfrags, page, pfrag->offset,
@@ -269,6 +267,9 @@ int esp6_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info
                        skb_shinfo(skb)->nr_frags = ++nfrags;
 
                        pfrag->offset = pfrag->offset + allocsize;
+
+                       spin_unlock_bh(&x->lock);
+
                        nfrags++;
 
                        skb->len += tailen;