diff --git a/include/net/sock.h b/include/net/sock.h index 253202dcc5e61afda37e0aff7095f11ec8e3f82b..261195598df394701e099f82c0ea5bfae35b196a 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -2197,6 +2197,15 @@ static inline void skb_set_owner_r(struct sk_buff *skb, struct sock *sk) sk_mem_charge(sk, skb->truesize); } +static inline void skb_set_owner_sk_safe(struct sk_buff *skb, struct sock *sk) +{ + if (sk && refcount_inc_not_zero(&sk->sk_refcnt)) { + skb_orphan(skb); + skb->destructor = sock_efree; + skb->sk = sk; + } +} + void sk_reset_timer(struct sock *sk, struct timer_list *timer, unsigned long expires); diff --git a/net/core/sock.c b/net/core/sock.c index 727ea1cc633ca50fdf423c5ddb985c0ae65f71cf..c75c1e723a840f24ba650db605c0e08a211786f0 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -2099,16 +2099,10 @@ void skb_orphan_partial(struct sk_buff *skb) if (skb_is_tcp_pure_ack(skb)) return; - if (can_skb_orphan_partial(skb)) { - struct sock *sk = skb->sk; - - if (refcount_inc_not_zero(&sk->sk_refcnt)) { - WARN_ON(refcount_sub_and_test(skb->truesize, &sk->sk_wmem_alloc)); - skb->destructor = sock_efree; - } - } else { + if (can_skb_orphan_partial(skb)) + skb_set_owner_sk_safe(skb, skb->sk); + else skb_orphan(skb); - } } EXPORT_SYMBOL(skb_orphan_partial);