> Your patch does solve the problem, thanks!
> 

Thanks for testing.

Here is the official patch I submit for review then.

[PATCH] ipsec: be careful of non existing mac headers

Nicollo Belli reported ipsec crashes in case we handle a frame without
mac header (atm in his case)

Before copying mac header, better make sure it is present.

Bugzilla reference:  https://bugzilla.kernel.org/show_bug.cgi?id=42809

Reported-by: Niccolò Belli <darkba...@linuxsystems.it>
Tested-by: Niccolò Belli <darkba...@linuxsystems.it>
Signed-off-by: Eric Dumazet <eric.duma...@gmail.com>
---
 net/ipv4/xfrm4_mode_beet.c   |    9 +++++----
 net/ipv4/xfrm4_mode_tunnel.c |   10 ++++++----
 net/ipv6/xfrm6_mode_beet.c   |    9 +++++----
 net/ipv6/xfrm6_mode_tunnel.c |   10 ++++++----
 4 files changed, 22 insertions(+), 16 deletions(-)

diff --git a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c
index 6341818..d3451f6 100644
--- a/net/ipv4/xfrm4_mode_beet.c
+++ b/net/ipv4/xfrm4_mode_beet.c
@@ -111,10 +111,11 @@ static int xfrm4_beet_input(struct xfrm_state *x, struct 
sk_buff *skb)
        skb_push(skb, sizeof(*iph));
        skb_reset_network_header(skb);
 
-       memmove(skb->data - skb->mac_len, skb_mac_header(skb),
-               skb->mac_len);
-       skb_set_mac_header(skb, -skb->mac_len);
-
+       if (skb_mac_header_was_set(skb)) {
+               memmove(skb->data - skb->mac_len, skb_mac_header(skb),
+                       skb->mac_len);
+               skb_set_mac_header(skb, -skb->mac_len);
+       }
        xfrm4_beet_make_header(skb);
 
        iph = ip_hdr(skb);
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
index 534972e..a646f30 100644
--- a/net/ipv4/xfrm4_mode_tunnel.c
+++ b/net/ipv4/xfrm4_mode_tunnel.c
@@ -66,7 +66,6 @@ static int xfrm4_mode_tunnel_output(struct xfrm_state *x, 
struct sk_buff *skb)
 
 static int xfrm4_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
 {
-       const unsigned char *old_mac;
        int err = -EINVAL;
 
        if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPIP)
@@ -84,9 +83,12 @@ static int xfrm4_mode_tunnel_input(struct xfrm_state *x, 
struct sk_buff *skb)
        if (!(x->props.flags & XFRM_STATE_NOECN))
                ipip_ecn_decapsulate(skb);
 
-       old_mac = skb_mac_header(skb);
-       skb_set_mac_header(skb, -skb->mac_len);
-       memmove(skb_mac_header(skb), old_mac, skb->mac_len);
+       if (skb_mac_header_was_set(skb)) {
+               const unsigned char *old_mac = skb_mac_header(skb);
+
+               skb_set_mac_header(skb, -skb->mac_len);
+               memmove(skb_mac_header(skb), old_mac, skb->mac_len);
+       }
        skb_reset_network_header(skb);
        err = 0;
 
diff --git a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c
index a81ce94..74c4b92 100644
--- a/net/ipv6/xfrm6_mode_beet.c
+++ b/net/ipv6/xfrm6_mode_beet.c
@@ -80,7 +80,6 @@ static int xfrm6_beet_output(struct xfrm_state *x, struct 
sk_buff *skb)
 static int xfrm6_beet_input(struct xfrm_state *x, struct sk_buff *skb)
 {
        struct ipv6hdr *ip6h;
-       const unsigned char *old_mac;
        int size = sizeof(struct ipv6hdr);
        int err;
 
@@ -91,10 +90,12 @@ static int xfrm6_beet_input(struct xfrm_state *x, struct 
sk_buff *skb)
        __skb_push(skb, size);
        skb_reset_network_header(skb);
 
-       old_mac = skb_mac_header(skb);
-       skb_set_mac_header(skb, -skb->mac_len);
-       memmove(skb_mac_header(skb), old_mac, skb->mac_len);
+       if (skb_mac_header_was_set(skb)) {
+               const unsigned char *old_mac = skb_mac_header(skb);
 
+               skb_set_mac_header(skb, -skb->mac_len);
+               memmove(skb_mac_header(skb), old_mac, skb->mac_len);
+       }
        xfrm6_beet_make_header(skb);
 
        ip6h = ipv6_hdr(skb);
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c
index 261e6e6..edb7091 100644
--- a/net/ipv6/xfrm6_mode_tunnel.c
+++ b/net/ipv6/xfrm6_mode_tunnel.c
@@ -63,7 +63,6 @@ static int xfrm6_mode_tunnel_output(struct xfrm_state *x, 
struct sk_buff *skb)
 static int xfrm6_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
 {
        int err = -EINVAL;
-       const unsigned char *old_mac;
 
        if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPV6)
                goto out;
@@ -80,9 +79,12 @@ static int xfrm6_mode_tunnel_input(struct xfrm_state *x, 
struct sk_buff *skb)
        if (!(x->props.flags & XFRM_STATE_NOECN))
                ipip6_ecn_decapsulate(skb);
 
-       old_mac = skb_mac_header(skb);
-       skb_set_mac_header(skb, -skb->mac_len);
-       memmove(skb_mac_header(skb), old_mac, skb->mac_len);
+       if (skb_mac_header_was_set(skb)) {
+               const unsigned char *old_mac = skb_mac_header(skb);
+
+               skb_set_mac_header(skb, -skb->mac_len);
+               memmove(skb_mac_header(skb), old_mac, skb->mac_len);
+       }
        skb_reset_network_header(skb);
        err = 0;
 





-- 
To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org

Reply via email to