diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2012-02-23 05:55:02 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-02-23 16:50:45 -0500 |
commit | 03606895cd98c0a628b17324fd7b5ff15db7e3cd (patch) | |
tree | 26aab95243f23a5d0cff45ee0d6afd1608afe5df /net | |
parent | 4a2258ddddefeef3291c0fc66437c73d84261a1e (diff) |
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=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>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/xfrm4_mode_beet.c | 5 | ||||
-rw-r--r-- | net/ipv4/xfrm4_mode_tunnel.c | 6 | ||||
-rw-r--r-- | net/ipv6/xfrm6_mode_beet.c | 6 | ||||
-rw-r--r-- | net/ipv6/xfrm6_mode_tunnel.c | 6 |
4 files changed, 6 insertions, 17 deletions
diff --git a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c index 63418185f524..e3db3f915114 100644 --- a/net/ipv4/xfrm4_mode_beet.c +++ b/net/ipv4/xfrm4_mode_beet.c | |||
@@ -110,10 +110,7 @@ static int xfrm4_beet_input(struct xfrm_state *x, struct sk_buff *skb) | |||
110 | 110 | ||
111 | skb_push(skb, sizeof(*iph)); | 111 | skb_push(skb, sizeof(*iph)); |
112 | skb_reset_network_header(skb); | 112 | skb_reset_network_header(skb); |
113 | 113 | skb_mac_header_rebuild(skb); | |
114 | memmove(skb->data - skb->mac_len, skb_mac_header(skb), | ||
115 | skb->mac_len); | ||
116 | skb_set_mac_header(skb, -skb->mac_len); | ||
117 | 114 | ||
118 | xfrm4_beet_make_header(skb); | 115 | xfrm4_beet_make_header(skb); |
119 | 116 | ||
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c index 534972e114ac..ed4bf11ef9f4 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) | |||
66 | 66 | ||
67 | static int xfrm4_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) | 67 | static int xfrm4_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) |
68 | { | 68 | { |
69 | const unsigned char *old_mac; | ||
70 | int err = -EINVAL; | 69 | int err = -EINVAL; |
71 | 70 | ||
72 | if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPIP) | 71 | 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 | if (!(x->props.flags & XFRM_STATE_NOECN)) | 83 | if (!(x->props.flags & XFRM_STATE_NOECN)) |
85 | ipip_ecn_decapsulate(skb); | 84 | ipip_ecn_decapsulate(skb); |
86 | 85 | ||
87 | old_mac = skb_mac_header(skb); | ||
88 | skb_set_mac_header(skb, -skb->mac_len); | ||
89 | memmove(skb_mac_header(skb), old_mac, skb->mac_len); | ||
90 | skb_reset_network_header(skb); | 86 | skb_reset_network_header(skb); |
87 | skb_mac_header_rebuild(skb); | ||
88 | |||
91 | err = 0; | 89 | err = 0; |
92 | 90 | ||
93 | out: | 91 | out: |
diff --git a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c index a81ce9450750..9949a356d62c 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) | |||
80 | static int xfrm6_beet_input(struct xfrm_state *x, struct sk_buff *skb) | 80 | static int xfrm6_beet_input(struct xfrm_state *x, struct sk_buff *skb) |
81 | { | 81 | { |
82 | struct ipv6hdr *ip6h; | 82 | struct ipv6hdr *ip6h; |
83 | const unsigned char *old_mac; | ||
84 | int size = sizeof(struct ipv6hdr); | 83 | int size = sizeof(struct ipv6hdr); |
85 | int err; | 84 | int err; |
86 | 85 | ||
@@ -90,10 +89,7 @@ static int xfrm6_beet_input(struct xfrm_state *x, struct sk_buff *skb) | |||
90 | 89 | ||
91 | __skb_push(skb, size); | 90 | __skb_push(skb, size); |
92 | skb_reset_network_header(skb); | 91 | skb_reset_network_header(skb); |
93 | 92 | skb_mac_header_rebuild(skb); | |
94 | old_mac = skb_mac_header(skb); | ||
95 | skb_set_mac_header(skb, -skb->mac_len); | ||
96 | memmove(skb_mac_header(skb), old_mac, skb->mac_len); | ||
97 | 93 | ||
98 | xfrm6_beet_make_header(skb); | 94 | xfrm6_beet_make_header(skb); |
99 | 95 | ||
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c index 261e6e6f487e..9f2095b19ad0 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) | |||
63 | static int xfrm6_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) | 63 | static int xfrm6_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) |
64 | { | 64 | { |
65 | int err = -EINVAL; | 65 | int err = -EINVAL; |
66 | const unsigned char *old_mac; | ||
67 | 66 | ||
68 | if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPV6) | 67 | if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPV6) |
69 | goto out; | 68 | goto out; |
@@ -80,10 +79,9 @@ static int xfrm6_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) | |||
80 | if (!(x->props.flags & XFRM_STATE_NOECN)) | 79 | if (!(x->props.flags & XFRM_STATE_NOECN)) |
81 | ipip6_ecn_decapsulate(skb); | 80 | ipip6_ecn_decapsulate(skb); |
82 | 81 | ||
83 | old_mac = skb_mac_header(skb); | ||
84 | skb_set_mac_header(skb, -skb->mac_len); | ||
85 | memmove(skb_mac_header(skb), old_mac, skb->mac_len); | ||
86 | skb_reset_network_header(skb); | 82 | skb_reset_network_header(skb); |
83 | skb_mac_header_rebuild(skb); | ||
84 | |||
87 | err = 0; | 85 | err = 0; |
88 | 86 | ||
89 | out: | 87 | out: |