From: Youngmin Nam <youngmin.nam@samsung.com>
To: Neal Cardwell <ncardwell@google.com>
Cc: Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>,
davem@davemloft.net, dsahern@kernel.org, pabeni@redhat.com,
horms@kernel.org, guo88.liu@samsung.com, yiwang.cai@samsung.com,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
joonki.min@samsung.com, hajun.sung@samsung.com,
d7271.choe@samsung.com, sw.ju@samsung.com,
"Dujeong.lee" <dujeong.lee@samsung.com>,
Yuchung Cheng <ycheng@google.com>, Kevin Yang <yyd@google.com>,
Xueming Feng <kuro@kuroa.me>,
Youngmin Nam <youngmin.nam@samsung.com>,
cmllamas@google.com, willdeacon@google.com, maennich@google.com
Subject: Re: [PATCH] tcp: check socket state before calling WARN_ON
Date: Fri, 14 Mar 2025 11:49:47 +0900 [thread overview]
Message-ID: <Z9OZS/hc+v5og6/U@perf> (raw)
In-Reply-To: <Z8KcXQhdRId1S6w8@perf>
[-- Attachment #1: Type: text/plain, Size: 5823 bytes --]
On Sat, Mar 01, 2025 at 02:37:23PM +0900, Youngmin Nam wrote:
> On Tue, Feb 25, 2025 at 12:24:47PM -0500, Neal Cardwell wrote:
> > On Mon, Feb 24, 2025 at 4:13 PM Neal Cardwell <ncardwell@google.com> wrote:
> > >
> > > On Mon, Feb 3, 2025 at 12:17 AM Youngmin Nam <youngmin.nam@samsung.com> wrote:
> > > >
> > > > > Hi Neal,
> > > > > Thank you for looking into this issue.
> > > > > When we first encountered this issue, we also suspected that tcp_write_queue_purge() was being called.
> > > > > We can provide any information you would like to inspect.
> > >
> > > Thanks again for raising this issue, and providing all that data!
> > >
> > > I've come up with a reproducer for this issue, and an explanation for
> > > why this has only been seen on Android so far, and a theory about a
> > > related socket leak issue, and a proposed fix for the WARN and the
> > > socket leak.
> > >
> > > Here is the scenario:
> > >
> > > + user process A has a socket in TCP_ESTABLISHED
> > >
> > > + user process A calls close(fd)
> > >
> > > + socket calls __tcp_close() and tcp_close_state() decides to enter
> > > TCP_FIN_WAIT1 and send a FIN
> > >
> > > + FIN is lost and retransmitted, making the state:
> > > ---
> > > tp->packets_out = 1
> > > tp->sacked_out = 0
> > > tp->lost_out = 1
> > > tp->retrans_out = 1
> > > ---
> > >
> > > + someone invokes "ss" to --kill the socket using the functionality in
> > > (1e64e298b8 "net: diag: Support destroying TCP sockets")
> > >
> > > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c1e64e298b8cad309091b95d8436a0255c84f54a
> > >
> > > (note: this was added for Android, so would not be surprising to have
> > > this inet_diag --kill run on Android)
> > >
> > > + the ss --kill causes a call to tcp_abort()
> > >
> > > + tcp_abort() calls tcp_write_queue_purge()
> > >
> > > + tcp_write_queue_purge() sets packets_out=0 but leaves lost_out=1,
> > > retrans_out=1
> > >
> > > + tcp_sock still exists in TCP_FIN_WAIT1 but now with an inconsistent state
> > >
> > > + ACK arrives and causes a WARN_ON from tcp_verify_left_out():
> > >
> > > #define tcp_verify_left_out(tp) WARN_ON(tcp_left_out(tp) > tp->packets_out)
> > >
> > > because the state has:
> > >
> > > ---
> > > tcp_left_out(tp) = sacked_out + lost_out = 1
> > > tp->packets_out = 0
> > > ---
> > >
> > > because the state is:
> > >
> > > ---
> > > tp->packets_out = 0
> > > tp->sacked_out = 0
> > > tp->lost_out = 1
> > > tp->retrans_out = 1
> > > ---
> > >
> > > I guess perhaps one fix would be to just have tcp_write_queue_purge()
> > > zero out those other fields:
> > >
> > > ---
> > > tp->sacked_out = 0
> > > tp->lost_out = 0
> > > tp->retrans_out = 0
> > > ---
> > >
> > > However, there is a related and worse problem. Because this killed
> > > socket has tp->packets_out, the next time the RTO timer fires,
> > > tcp_retransmit_timer() notices !tp->packets_out is true, so it short
> > > circuits and returns without setting another RTO timer or checking to
> > > see if the socket should be deleted. So the tcp_sock is now sitting in
> > > memory with no timer set to delete it. So we could leak a socket this
> > > way. So AFAICT to fix this socket leak problem, perhaps we want a
> > > patch like the following (not tested yet), so that we delete all
> > > killed sockets immediately, whether they are SOCK_DEAD (orphans for
> > > which the user already called close() or not) :
> > >
> > > diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
> > > index 28cf19317b6c2..a266078b8ec8c 100644
> > > --- a/net/ipv4/tcp.c
> > > +++ b/net/ipv4/tcp.c
> > > @@ -5563,15 +5563,12 @@ int tcp_abort(struct sock *sk, int err)
> > > local_bh_disable();
> > > bh_lock_sock(sk);
> > >
> > > - if (!sock_flag(sk, SOCK_DEAD)) {
> > > - if (tcp_need_reset(sk->sk_state))
> > > - tcp_send_active_reset(sk, GFP_ATOMIC);
> > > - tcp_done_with_error(sk, err);
> > > - }
> > > + if (tcp_need_reset(sk->sk_state))
> > > + tcp_send_active_reset(sk, GFP_ATOMIC);
> > > + tcp_done_with_error(sk, err);
> > >
> > > bh_unlock_sock(sk);
> > > local_bh_enable();
> > > - tcp_write_queue_purge(sk);
> > > release_sock(sk);
> > > return 0;
> > > }
> > > ---
> >
> > Actually, it seems like a similar fix was already merged into Linux v6.11:
> >
> > bac76cf89816b tcp: fix forever orphan socket caused by tcp_abort
> >
> > Details below.
> >
> > Youngmin, does your kernel have this bac76cf89816b fix? If not, can
> > you please cherry-pick this fix and retest?
> >
> > Thanks!
> > neal
>
> Hi Neal.
>
> Thank you for your effort in debugging this issue with me.
> I also appreciate your detailed explanation and for finding the patch related to the issue.
>
> Our kernel(an Android kernel based on 6.6 LTS) does not have the patch you mentioned.(bac76cf89816b)
>
> I'll let you know the test results after applying the patch.
>
> Thank you.
>
Hi Neal.
There were confilcts when I cherry-picked the patch
"bac76cf89816b tcp: fix forever orphan socket caused by tcp_abort"
and it also has a dependency.
I believe we need a total of two patches,
which exist in the latest upstream for 6.6 LTS and earlier LTS trees.
5ce4645c23cf tcp: fix races in tcp_abort()
bac76cf89816 tcp: fix forever orphan socket caused by tcp_abort
So, I uploaded CLs for this to android kernel gerrit.
https://android-review.googlesource.com/c/kernel/common/+/3530435 BACKPORT: tcp: fix races in tcp_abort()
https://android-review.googlesource.com/c/kernel/common/+/3530436 BACKPORT: tcp: fix forever orphan socket caused by tcp_abort
After applying these patches, we conducted a total of three rounds of testing with 200 devices,
and all tests passed.
Thanks.
[-- Attachment #2: Type: text/plain, Size: 0 bytes --]
next prev parent reply other threads:[~2025-03-14 2:45 UTC|newest]
Thread overview: 43+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <CGME20241203081005epcas2p247b3d05bc767b1a50ba85c4433657295@epcas2p2.samsung.com>
2024-12-03 8:12 ` [PATCH] tcp: check socket state before calling WARN_ON Youngmin Nam
2024-12-03 11:07 ` Eric Dumazet
2024-12-03 15:34 ` Neal Cardwell
2024-12-04 2:18 ` Jakub Kicinski
2024-12-04 3:39 ` Youngmin Nam
2024-12-04 7:13 ` Eric Dumazet
2024-12-04 7:48 ` Dujeong.lee
2024-12-04 14:21 ` Neal Cardwell
2024-12-05 12:31 ` Dujeong.lee
2025-01-17 5:08 ` Youngmin Nam
2025-01-17 15:18 ` Neal Cardwell
2025-01-20 0:18 ` Youngmin Nam
2025-02-03 5:21 ` Youngmin Nam
2025-02-24 21:13 ` Neal Cardwell
2025-02-25 17:24 ` Neal Cardwell
2025-02-25 18:28 ` Yuchung Cheng
2025-02-25 18:43 ` Eric Dumazet
2025-03-01 5:37 ` Youngmin Nam
2025-03-14 2:49 ` Youngmin Nam [this message]
2024-12-06 5:53 ` Youngmin Nam
2024-12-06 8:35 ` Eric Dumazet
2024-12-06 9:01 ` Youngmin Nam
2024-12-06 9:08 ` Eric Dumazet
2024-12-06 15:34 ` Neal Cardwell
2024-12-09 1:52 ` Youngmin Nam
2024-12-09 1:32 ` Youngmin Nam
2024-12-09 10:16 ` Dujeong.lee
2024-12-09 10:20 ` Eric Dumazet
2024-12-10 3:38 ` Dujeong.lee
2024-12-10 7:10 ` Dujeong.lee
2024-12-18 10:18 ` Dujeong.lee
2024-12-18 10:27 ` Eric Dumazet
2024-12-30 0:23 ` Dujeong.lee
2024-12-30 9:33 ` Eric Dumazet
2025-01-02 0:22 ` Dujeong.lee
2025-01-02 8:16 ` Eric Dumazet
2025-01-03 4:16 ` Dujeong.lee
2024-12-04 3:26 ` Youngmin Nam
2024-12-04 8:55 ` Eric Dumazet
2024-12-04 3:08 ` Youngmin Nam
2024-12-04 9:03 ` Eric Dumazet
2024-12-05 2:45 ` Youngmin Nam
2024-12-13 7:14 ` Youngmin Nam
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Z9OZS/hc+v5og6/U@perf \
--to=youngmin.nam@samsung.com \
--cc=cmllamas@google.com \
--cc=d7271.choe@samsung.com \
--cc=davem@davemloft.net \
--cc=dsahern@kernel.org \
--cc=dujeong.lee@samsung.com \
--cc=edumazet@google.com \
--cc=guo88.liu@samsung.com \
--cc=hajun.sung@samsung.com \
--cc=horms@kernel.org \
--cc=joonki.min@samsung.com \
--cc=kuba@kernel.org \
--cc=kuro@kuroa.me \
--cc=linux-kernel@vger.kernel.org \
--cc=maennich@google.com \
--cc=ncardwell@google.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=sw.ju@samsung.com \
--cc=willdeacon@google.com \
--cc=ycheng@google.com \
--cc=yiwang.cai@samsung.com \
--cc=yyd@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.