net: Fix skb_set_peeked use-after-free bug
The commit738ac1ebb9
("net: Clone skb before setting peeked flag") introduced a use-after-free bug in skb_recv_datagram. This is because skb_set_peeked may create a new skb and free the existing one. As it stands the caller will continue to use the old freed skb. This patch fixes it by making skb_set_peeked return the new skb (or the old one if unchanged). Fixes:738ac1ebb9
("net: Clone skb before setting peeked flag") Reported-by: Brenden Blanco <bblanco@plumgrid.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Tested-by: Brenden Blanco <bblanco@plumgrid.com> Reviewed-by: Konstantin Khlebnikov <khlebnikov@yandex-team.ru> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
14d2b7c1a9
commit
a0a2a66024
@ -131,12 +131,12 @@ static int wait_for_more_packets(struct sock *sk, int *err, long *timeo_p,
|
||||
goto out;
|
||||
}
|
||||
|
||||
static int skb_set_peeked(struct sk_buff *skb)
|
||||
static struct sk_buff *skb_set_peeked(struct sk_buff *skb)
|
||||
{
|
||||
struct sk_buff *nskb;
|
||||
|
||||
if (skb->peeked)
|
||||
return 0;
|
||||
return skb;
|
||||
|
||||
/* We have to unshare an skb before modifying it. */
|
||||
if (!skb_shared(skb))
|
||||
@ -144,7 +144,7 @@ static int skb_set_peeked(struct sk_buff *skb)
|
||||
|
||||
nskb = skb_clone(skb, GFP_ATOMIC);
|
||||
if (!nskb)
|
||||
return -ENOMEM;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
skb->prev->next = nskb;
|
||||
skb->next->prev = nskb;
|
||||
@ -157,7 +157,7 @@ static int skb_set_peeked(struct sk_buff *skb)
|
||||
done:
|
||||
skb->peeked = 1;
|
||||
|
||||
return 0;
|
||||
return skb;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -229,8 +229,9 @@ struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned int flags,
|
||||
continue;
|
||||
}
|
||||
|
||||
error = skb_set_peeked(skb);
|
||||
if (error)
|
||||
skb = skb_set_peeked(skb);
|
||||
error = PTR_ERR(skb);
|
||||
if (IS_ERR(skb))
|
||||
goto unlock_err;
|
||||
|
||||
atomic_inc(&skb->users);
|
||||
|
Loading…
Reference in New Issue
Block a user