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>
This commit is contained in:
Родитель
4a2258dddd
Коммит
03606895cd
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,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:
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,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:
|
||||
|
|
Загрузка…
Ссылка в новой задаче