From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A2673C433EF for ; Mon, 15 Nov 2021 17:51:26 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8D0F26340E for ; Mon, 15 Nov 2021 17:51:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238981AbhKORyT (ORCPT ); Mon, 15 Nov 2021 12:54:19 -0500 Received: from mail.kernel.org ([198.145.29.99]:50934 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237776AbhKORYD (ORCPT ); Mon, 15 Nov 2021 12:24:03 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 71B9A63282; Mon, 15 Nov 2021 17:17:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1636996676; bh=0dxWu/VuRqyfzH7wNde602N0vf7ElPbN+0WzjLy/mu0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ZskZTT2r8S6NdIuPTrJ+p+Viv2QqoR5wZYu8hz+VnW1+i5S72FgtNtEICVWY7KMtc PtzN5nWxxmwlDIu0rGf2Xl1nCpqEwj6BYdDftzNS28ff3KMrdSr3PPxXeoSAJWng+Q FMhgO6l5G54I4JAafZ8Z7qDE2J4sBq3pTXfwREo4= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Jakub Kicinski , Eric Dumazet , "David S. Miller" , Sasha Levin Subject: [PATCH 5.4 226/355] net: stream: dont purge sk_error_queue in sk_stream_kill_queues() Date: Mon, 15 Nov 2021 18:02:30 +0100 Message-Id: <20211115165321.068760530@linuxfoundation.org> X-Mailer: git-send-email 2.33.1 In-Reply-To: <20211115165313.549179499@linuxfoundation.org> References: <20211115165313.549179499@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Jakub Kicinski [ Upstream commit 24bcbe1cc69fa52dc4f7b5b2456678ed464724d8 ] sk_stream_kill_queues() can be called on close when there are still outstanding skbs to transmit. Those skbs may try to queue notifications to the error queue (e.g. timestamps). If sk_stream_kill_queues() purges the queue without taking its lock the queue may get corrupted, and skbs leaked. This shows up as a warning about an rmem leak: WARNING: CPU: 24 PID: 0 at net/ipv4/af_inet.c:154 inet_sock_destruct+0x... The leak is always a multiple of 0x300 bytes (the value is in %rax on my builds, so RAX: 0000000000000300). 0x300 is truesize of an empty sk_buff. Indeed if we dump the socket state at the time of the warning the sk_error_queue is often (but not always) corrupted. The ->next pointer points back at the list head, but not the ->prev pointer. Indeed we can find the leaked skb by scanning the kernel memory for something that looks like an skb with ->sk = socket in question, and ->truesize = 0x300. The contents of ->cb[] of the skb confirms the suspicion that it is indeed a timestamp notification (as generated in __skb_complete_tx_timestamp()). Removing purging of sk_error_queue should be okay, since inet_sock_destruct() does it again once all socket refs are gone. Eric suggests this may cause sockets that go thru disconnect() to maintain notifications from the previous incarnations of the socket, but that should be okay since the race was there anyway, and disconnect() is not exactly dependable. Thanks to Jonathan Lemon and Omar Sandoval for help at various stages of tracing the issue. Fixes: cb9eff097831 ("net: new user space API for time stamping of incoming and outgoing packets") Signed-off-by: Jakub Kicinski Reviewed-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Sasha Levin --- net/core/stream.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/net/core/stream.c b/net/core/stream.c index 4f1d4aa5fb38d..a166a32b411fa 100644 --- a/net/core/stream.c +++ b/net/core/stream.c @@ -195,9 +195,6 @@ void sk_stream_kill_queues(struct sock *sk) /* First the read buffer. */ __skb_queue_purge(&sk->sk_receive_queue); - /* Next, the error queue. */ - __skb_queue_purge(&sk->sk_error_queue); - /* Next, the write queue. */ WARN_ON(!skb_queue_empty(&sk->sk_write_queue)); -- 2.33.0