From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-by2nam01on0132.outbound.protection.outlook.com ([104.47.34.132]:19853 "EHLO NAM01-BY2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1753890AbeARVAY (ORCPT ); Thu, 18 Jan 2018 16:00:24 -0500 From: Sasha Levin To: "stable@vger.kernel.org" , "stable-commits@vger.kernel.org" CC: Eric Dumazet , "David S . Miller" , Sasha Levin Subject: [added to the 4.1 stable tree] net: fix socket refcounting in skb_complete_wifi_ack() Date: Thu, 18 Jan 2018 20:59:45 +0000 Message-ID: <20180118205908.3220-41-alexander.levin@microsoft.com> References: <20180118205908.3220-1-alexander.levin@microsoft.com> In-Reply-To: <20180118205908.3220-1-alexander.levin@microsoft.com> Content-Language: en-US Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Sender: stable-owner@vger.kernel.org List-ID: From: Eric Dumazet This patch has been added to the stable tree. If you have any objections, please let us know. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D [ Upstream commit dd4f10722aeb10f4f582948839f066bebe44e5fb ] TX skbs do not necessarily hold a reference on skb->sk->sk_refcnt By the time TX completion happens, sk_refcnt might be already 0. sock_hold()/sock_put() would then corrupt critical state, like sk_wmem_alloc. Fixes: bf7fa551e0ce ("mac80211: Resolve sk_refcnt/sk_wmem_alloc issue in wi= fi ack path") Signed-off-by: Eric Dumazet Cc: Alexander Duyck Cc: Johannes Berg Cc: Soheil Hassas Yeganeh Cc: Willem de Bruijn Acked-by: Soheil Hassas Yeganeh Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- net/core/skbuff.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 2894bb5b7e0a..6642accc628a 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -3753,7 +3753,7 @@ void skb_complete_wifi_ack(struct sk_buff *skb, bool = acked) { struct sock *sk =3D skb->sk; struct sock_exterr_skb *serr; - int err; + int err =3D 1; =20 skb->wifi_acked_valid =3D 1; skb->wifi_acked =3D acked; @@ -3763,14 +3763,15 @@ void skb_complete_wifi_ack(struct sk_buff *skb, boo= l acked) serr->ee.ee_errno =3D ENOMSG; serr->ee.ee_origin =3D SO_EE_ORIGIN_TXSTATUS; =20 - /* take a reference to prevent skb_orphan() from freeing the socket */ - sock_hold(sk); - - err =3D sock_queue_err_skb(sk, skb); + /* Take a reference to prevent skb_orphan() from freeing the socket, + * but only if the socket refcount is not zero. + */ + if (likely(atomic_inc_not_zero(&sk->sk_refcnt))) { + err =3D sock_queue_err_skb(sk, skb); + sock_put(sk); + } if (err) kfree_skb(skb); - - sock_put(sk); } EXPORT_SYMBOL_GPL(skb_complete_wifi_ack); =20 --=20 2.11.0