net: convert sk_buff.users from atomic_t to refcount_t
refcount_t type and corresponding API should be used instead of atomic_t when the variable is used as a reference counter. This allows to avoid accidental refcounter overflows that might lead to use-after-free situations. Signed-off-by: Elena Reshetova <elena.reshetova@intel.com> Signed-off-by: Hans Liljestrand <ishkamiel@gmail.com> Signed-off-by: Kees Cook <keescook@chromium.org> Signed-off-by: David Windsor <dwindsor@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
53869cebce
commit
633547973f
@@ -1862,7 +1862,7 @@ static inline int deliver_skb(struct sk_buff *skb,
|
||||
{
|
||||
if (unlikely(skb_orphan_frags(skb, GFP_ATOMIC)))
|
||||
return -ENOMEM;
|
||||
atomic_inc(&skb->users);
|
||||
refcount_inc(&skb->users);
|
||||
return pt_prev->func(skb, skb->dev, pt_prev, orig_dev);
|
||||
}
|
||||
|
||||
@@ -2484,10 +2484,10 @@ void __dev_kfree_skb_irq(struct sk_buff *skb, enum skb_free_reason reason)
|
||||
if (unlikely(!skb))
|
||||
return;
|
||||
|
||||
if (likely(atomic_read(&skb->users) == 1)) {
|
||||
if (likely(refcount_read(&skb->users) == 1)) {
|
||||
smp_rmb();
|
||||
atomic_set(&skb->users, 0);
|
||||
} else if (likely(!atomic_dec_and_test(&skb->users))) {
|
||||
refcount_set(&skb->users, 0);
|
||||
} else if (likely(!refcount_dec_and_test(&skb->users))) {
|
||||
return;
|
||||
}
|
||||
get_kfree_skb_cb(skb)->reason = reason;
|
||||
@@ -3955,7 +3955,7 @@ static __latent_entropy void net_tx_action(struct softirq_action *h)
|
||||
|
||||
clist = clist->next;
|
||||
|
||||
WARN_ON(atomic_read(&skb->users));
|
||||
WARN_ON(refcount_read(&skb->users));
|
||||
if (likely(get_kfree_skb_cb(skb)->reason == SKB_REASON_CONSUMED))
|
||||
trace_consume_skb(skb);
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user