Skip to content

Commit

Permalink
ipsec: be careful of non existing mac headers
Browse files Browse the repository at this point in the history
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=42809

Reported-by: Niccolò Belli <darkbasic@linuxsystems.it>
Tested-by: Niccolò Belli <darkbasic@linuxsystems.it>
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Eric Dumazet authored and David S. Miller committed Feb 23, 2012
1 parent 4a2258d commit 0360689
Show file tree
Hide file tree
Showing 5 changed files with 16 additions and 17 deletions.
10 changes: 10 additions & 0 deletions include/linux/skbuff.h
Original file line number Diff line number Diff line change
Expand Up @@ -1465,6 +1465,16 @@ static inline void skb_set_mac_header(struct sk_buff *skb, const int 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)
{
return skb->csum_start - skb_headroom(skb);
Expand Down
5 changes: 1 addition & 4 deletions net/ipv4/xfrm4_mode_beet.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,7 @@ 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);
skb_mac_header_rebuild(skb);

xfrm4_beet_make_header(skb);

Expand Down
6 changes: 2 additions & 4 deletions net/ipv4/xfrm4_mode_tunnel.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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))
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_mac_header_rebuild(skb);

err = 0;

out:
Expand Down
6 changes: 1 addition & 5 deletions net/ipv6/xfrm6_mode_beet.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -90,10 +89,7 @@ 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);
skb_mac_header_rebuild(skb);

xfrm6_beet_make_header(skb);

Expand Down
6 changes: 2 additions & 4 deletions net/ipv6/xfrm6_mode_tunnel.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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))
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_mac_header_rebuild(skb);

err = 0;

out:
Expand Down

0 comments on commit 0360689

Please sign in to comment.