Commit 03606895 authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller

ipsec: be careful of non existing mac headers

Niccolo 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=42809Reported-by: default avatarNiccolò Belli <darkbasic@linuxsystems.it>
Tested-by: default avatarNiccolò Belli <darkbasic@linuxsystems.it>
Signed-off-by: default avatarEric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 4a2258dd
...@@ -1465,6 +1465,16 @@ static inline void skb_set_mac_header(struct sk_buff *skb, const int offset) ...@@ -1465,6 +1465,16 @@ static inline void skb_set_mac_header(struct sk_buff *skb, const int offset)
} }
#endif /* NET_SKBUFF_DATA_USES_OFFSET */ #endif /* NET_SKBUFF_DATA_USES_OFFSET */
static inline void skb_mac_header_rebuild(struct sk_buff *skb)
{
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);
}
}
static inline int skb_checksum_start_offset(const struct sk_buff *skb) static inline int skb_checksum_start_offset(const struct sk_buff *skb)
{ {
return skb->csum_start - skb_headroom(skb); return skb->csum_start - skb_headroom(skb);
......
...@@ -110,10 +110,7 @@ static int xfrm4_beet_input(struct xfrm_state *x, struct sk_buff *skb) ...@@ -110,10 +110,7 @@ static int xfrm4_beet_input(struct xfrm_state *x, struct sk_buff *skb)
skb_push(skb, sizeof(*iph)); skb_push(skb, sizeof(*iph));
skb_reset_network_header(skb); skb_reset_network_header(skb);
skb_mac_header_rebuild(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); xfrm4_beet_make_header(skb);
......
...@@ -66,7 +66,6 @@ static int xfrm4_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) ...@@ -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) static int xfrm4_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
{ {
const unsigned char *old_mac;
int err = -EINVAL; int err = -EINVAL;
if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPIP) if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPIP)
...@@ -84,10 +83,9 @@ static int xfrm4_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) ...@@ -84,10 +83,9 @@ static int xfrm4_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
if (!(x->props.flags & XFRM_STATE_NOECN)) if (!(x->props.flags & XFRM_STATE_NOECN))
ipip_ecn_decapsulate(skb); 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);
skb_reset_network_header(skb); skb_reset_network_header(skb);
skb_mac_header_rebuild(skb);
err = 0; err = 0;
out: out:
......
...@@ -80,7 +80,6 @@ static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb) ...@@ -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) static int xfrm6_beet_input(struct xfrm_state *x, struct sk_buff *skb)
{ {
struct ipv6hdr *ip6h; struct ipv6hdr *ip6h;
const unsigned char *old_mac;
int size = sizeof(struct ipv6hdr); int size = sizeof(struct ipv6hdr);
int err; int err;
...@@ -90,10 +89,7 @@ static int xfrm6_beet_input(struct xfrm_state *x, struct sk_buff *skb) ...@@ -90,10 +89,7 @@ static int xfrm6_beet_input(struct xfrm_state *x, struct sk_buff *skb)
__skb_push(skb, size); __skb_push(skb, size);
skb_reset_network_header(skb); skb_reset_network_header(skb);
skb_mac_header_rebuild(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);
xfrm6_beet_make_header(skb); xfrm6_beet_make_header(skb);
......
...@@ -63,7 +63,6 @@ static int xfrm6_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) ...@@ -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) static int xfrm6_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
{ {
int err = -EINVAL; int err = -EINVAL;
const unsigned char *old_mac;
if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPV6) if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPV6)
goto out; goto out;
...@@ -80,10 +79,9 @@ static int xfrm6_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) ...@@ -80,10 +79,9 @@ static int xfrm6_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
if (!(x->props.flags & XFRM_STATE_NOECN)) if (!(x->props.flags & XFRM_STATE_NOECN))
ipip6_ecn_decapsulate(skb); 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);
skb_reset_network_header(skb); skb_reset_network_header(skb);
skb_mac_header_rebuild(skb);
err = 0; err = 0;
out: out:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment