Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932884AbdDPK6T (ORCPT ); Sun, 16 Apr 2017 06:58:19 -0400 Received: from mail.linuxfoundation.org ([140.211.169.12]:60152 "EHLO mail.linuxfoundation.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932864AbdDPK6M (ORCPT ); Sun, 16 Apr 2017 06:58:12 -0400 From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Eric Dumazet , Alexander Duyck , Johannes Berg , Soheil Hassas Yeganeh , Willem de Bruijn , "David S. Miller" Subject: [PATCH 3.18 142/145] net: fix socket refcounting in skb_complete_tx_timestamp() Date: Sun, 16 Apr 2017 12:50:35 +0200 Message-Id: <20170416080208.064538151@linuxfoundation.org> X-Mailer: git-send-email 2.12.2 In-Reply-To: <20170416080200.205458595@linuxfoundation.org> References: <20170416080200.205458595@linuxfoundation.org> User-Agent: quilt/0.65 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 1740 Lines: 53 3.18-stable review patch. If anyone has any objections, please let me know. ------------------ From: Eric Dumazet commit 9ac25fc063751379cb77434fef9f3b088cd3e2f7 upstream. 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 and lead to leaks or use after free. Fixes: 62bccb8cdb69 ("net-timestamp: Make the clone operation stand-alone from phy timestamping") 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: Greg Kroah-Hartman --- net/core/skbuff.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -3617,13 +3617,14 @@ void skb_complete_tx_timestamp(struct sk { struct sock *sk = skb->sk; - /* take a reference to prevent skb_orphan() from freeing the socket */ - sock_hold(sk); - - *skb_hwtstamps(skb) = *hwtstamps; - __skb_complete_tx_timestamp(skb, sk, SCM_TSTAMP_SND); - - sock_put(sk); + /* 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))) { + *skb_hwtstamps(skb) = *hwtstamps; + __skb_complete_tx_timestamp(skb, sk, SCM_TSTAMP_SND); + sock_put(sk); + } } EXPORT_SYMBOL_GPL(skb_complete_tx_timestamp);