From: Jakub Sitnicki <jakub@cloudflare.com>
To: "Alexei Starovoitov" <alexei.starovoitov@gmail.com>,
"Dudu Lu" <phx0fer@gmail.com>
Cc: <john.fastabend@gmail.com>, <jiayuan.chen@linux.dev>,
<netdev@vger.kernel.org>, <bpf@vger.kernel.org>
Subject: Re: [PATCH bpf v2] bpf, sockmap: annotate the psock teardown data races
Date: Fri, 23 Oct 2026 20:49:42 +0200 [thread overview]
Message-ID: <871p9g6ym1.fsf@cloudflare.com> (raw)
In-Reply-To: <DMBHB0TQOV1L.38MECMYFGUS5B@gmail.com> (Alexei Starovoitov's message of "Thu, 22 Oct 2026 15:40:17 +0000")
On Thu, Oct 22, 2026 at 03:40 PM GMT, Alexei Starovoitov wrote:
> On Wed, Oct 21, 2026 at 10:48 PM Dudu Lu <phx0fer@gmail.com> wrote:
>> Annotate every one of these accesses with READ_ONCE()/WRITE_ONCE(),
>> matching the existing convention for the same fields: sk->sk_data_ready
>
> This makes KCSAN quiet and leaves the race where it is.
>
> sock_map_link() runs under the sock lock. sock_map_delete_elem() doesn't
> take it. sk_callback_lock is the only lock they share and sock_map_link()
> takes it after psock_set_prog() and sock_map_init_proto().
> So two tcp_bpf_update_proto(sk, psock, false) can run in parallel:
> cpu0: sock_map_link() for a map with msg_parser sees
> psock->progs.stream_verdict and picks TCP_BPF_TXRX
> cpu1: sock_map_del_link() stops the verdict and stores TCP_BPF_TX
> cpu0: stores TCP_BPF_TXRX
Right, so:
- map_update_elem syscall vs close(fd) - OK (lock_sock protected),
- map_update_elem syscall vs map_delete_elem syscall - RACY,
- map_update_elem syscall vs TCP RST (destroy) - RACY,
- map_update_elem from BPF vs close(fd) - RACY.
> The socket is left with tcp_bpf_recvmsg_parser() and no verdict prog.
> That's what commit c0d95d3380ee fixed.
> Take the lock earlier. Then psock_update_sk_prot needs no annotation.
>
> All accesses to saved_data_ready are under sk_callback_lock except the
> three reads in sock_map_del_link(). Move that check under the lock instead
> of annotating it. No need to touch skmsg.c and skmsg.h.
>
> Only the two lockless reads of sk->sk_prot need READ_ONCE().
>
> Something like this (compile tested only):
>
> diff --git a/net/core/sock_map.c b/net/core/sock_map.c
> index 38df842..20fb605 100644
> --- a/net/core/sock_map.c
> +++ b/net/core/sock_map.c
> @@ -152,11 +152,11 @@ static void sock_map_del_link(struct sock *sk,
> struct bpf_map *map = link->map;
> struct sk_psock_progs *progs = sock_map_progs(map);
>
> - if (psock->saved_data_ready && progs->stream_parser)
> + if (progs->stream_parser)
> strp_stop = true;
> - if (psock->saved_data_ready && progs->stream_verdict)
> + if (progs->stream_verdict)
> verdict_stop = true;
> - if (psock->saved_data_ready && progs->skb_verdict)
> + if (progs->skb_verdict)
> verdict_stop = true;
> list_del(&link->list);
> sk_psock_free_link(link);
> @@ -164,8 +164,11 @@ static void sock_map_del_link(struct sock *sk,
> }
> }
> spin_unlock_bh(&psock->link_lock);
> - if (strp_stop || verdict_stop) {
> - write_lock_bh(&sk->sk_callback_lock);
> + if (!strp_stop && !verdict_stop)
> + return;
> +
> + write_lock_bh(&sk->sk_callback_lock);
> + if (psock->saved_data_ready) {
> if (strp_stop)
> sk_psock_stop_strp(sk, psock);
> if (verdict_stop)
> @@ -173,8 +176,8 @@ static void sock_map_del_link(struct sock *sk,
>
> if (psock->psock_update_sk_prot)
> psock->psock_update_sk_prot(sk, psock, false);
> - write_unlock_bh(&sk->sk_callback_lock);
> }
> + write_unlock_bh(&sk->sk_callback_lock);
> }
>
> static void sock_map_unref(struct sock *sk, void *link_raw)
> @@ -202,7 +205,7 @@ static struct sk_psock *sock_map_psock_get_checked(struct sock *sk)
> rcu_read_lock();
> psock = sk_psock(sk);
> if (psock) {
> - if (sk->sk_prot->close != sock_map_close) {
> + if (READ_ONCE(sk->sk_prot)->close != sock_map_close) {
> psock = ERR_PTR(-EBUSY);
> goto out;
> }
> @@ -284,6 +287,7 @@ static int sock_map_link(struct bpf_map *map, struct sock *sk)
> }
> }
>
> + write_lock_bh(&sk->sk_callback_lock);
> if (msg_parser)
> psock_set_prog(&psock->progs.msg_parser, msg_parser);
> if (stream_parser)
> @@ -298,11 +302,11 @@ static int sock_map_link(struct bpf_map *map, struct sock *sk)
> */
> ret = sock_map_init_proto(sk, psock);
> if (ret < 0) {
> + write_unlock_bh(&sk->sk_callback_lock);
> sk_psock_put(sk, psock);
> goto out;
> }
>
> - write_lock_bh(&sk->sk_callback_lock);
> if (stream_parser && stream_verdict && !psock->saved_data_ready) {
> if (sk_is_tcp(sk))
> ret = sk_psock_init_strp(sk, psock);
> @@ -536,7 +540,7 @@ static bool sock_map_redirect_allowed(const struct sock *sk)
>
> static bool sock_map_sk_is_suitable(const struct sock *sk)
> {
> - return !!sk->sk_prot->psock_update_sk_prot;
> + return !!READ_ONCE(sk->sk_prot)->psock_update_sk_prot;
> }
>
> static bool sock_map_sk_state_allowed(const struct sock *sk)
Code LGTM
next prev parent reply other threads:[~2026-10-23 18:49 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-21 15:56 [PATCH bpf] bpf, sockmap: use READ_ONCE/WRITE_ONCE for saved_data_ready in the verdict path Dudu Lu
2026-10-21 16:10 ` sashiko-bot
2026-10-21 16:37 ` bot+bpf-ci
2026-10-21 16:45 ` Alexei Starovoitov
2026-10-21 20:30 ` Jakub Sitnicki
2026-10-22 3:37 ` Jiayuan Chen
2026-10-22 5:48 ` [PATCH bpf v2] bpf, sockmap: annotate the psock teardown data races Dudu Lu
2026-10-22 15:40 ` Alexei Starovoitov
2026-10-23 18:49 ` Jakub Sitnicki [this message]
2026-10-23 18:53 ` Alexei Starovoitov
2026-10-26 12:33 ` Jakub Sitnicki
2026-10-27 5:10 ` phx
2026-10-27 16:33 ` Jakub Sitnicki
2026-10-27 16:46 ` Alexei Starovoitov
2026-10-27 17:34 ` Jakub Sitnicki
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=871p9g6ym1.fsf@cloudflare.com \
--to=jakub@cloudflare.com \
--cc=alexei.starovoitov@gmail.com \
--cc=bpf@vger.kernel.org \
--cc=jiayuan.chen@linux.dev \
--cc=john.fastabend@gmail.com \
--cc=netdev@vger.kernel.org \
--cc=phx0fer@gmail.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.