From: Jakub Sitnicki <jakub@cloudflare.com>
To: Jiayuan Chen <jiayuan.chen@linux.dev>
Cc: bpf@vger.kernel.org, John Fastabend <john.fastabend@gmail.com>,
"David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>,
Paolo Abeni <pabeni@redhat.com>, Simon Horman <horms@kernel.org>,
Neal Cardwell <ncardwell@google.com>,
Kuniyuki Iwashima <kuniyu@google.com>,
David Ahern <dsahern@kernel.org>,
Alexei Starovoitov <ast@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
Andrii Nakryiko <andrii@kernel.org>,
Martin KaFai Lau <martin.lau@linux.dev>,
Eduard Zingerman <eddyz87@gmail.com>, Song Liu <song@kernel.org>,
Yonghong Song <yonghong.song@linux.dev>,
KP Singh <kpsingh@kernel.org>,
Stanislav Fomichev <sdf@fomichev.me>,
Hao Luo <haoluo@google.com>, Jiri Olsa <jolsa@kernel.org>,
Shuah Khan <shuah@kernel.org>, Michal Luczaj <mhal@rbox.co>,
Stefano Garzarella <sgarzare@redhat.com>,
Cong Wang <cong.wang@bytedance.com>,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-kselftest@vger.kernel.org
Subject: Re: [PATCH bpf-next v1 1/3] bpf, sockmap: Fix incorrect copied_seq calculation
Date: Wed, 19 Nov 2025 20:53:34 +0100 [thread overview]
Message-ID: <87zf8h6bpd.fsf@cloudflare.com> (raw)
In-Reply-To: <20251117110736.293040-2-jiayuan.chen@linux.dev> (Jiayuan Chen's message of "Mon, 17 Nov 2025 19:07:05 +0800")
On Mon, Nov 17, 2025 at 07:07 PM +08, Jiayuan Chen wrote:
> A socket using sockmap has its own independent receive queue: ingress_msg.
> This queue may contain data from its own protocol stack or from other
> sockets.
>
> The issue is that when reading from ingress_msg, we update tp->copied_seq
> by default. However, if the data is not from its own protocol stack,
> tcp->rcv_nxt is not increased. Later, if we convert this socket to a
> native socket, reading from this socket may fail because copied_seq might
> be significantly larger than rcv_nxt.
>
> This fix also addresses the syzkaller-reported bug referenced in the
> Closes tag.
>
> This patch marks the skmsg objects in ingress_msg. When reading, we update
> copied_seq only if the data is from its own protocol stack.
>
> FD1:read()
> -- FD1->copied_seq++
> | [read data]
> |
> [enqueue data] v
> [sockmap] -> ingress to self -> ingress_msg queue
> FD1 native stack ------> ^
> -- FD1->rcv_nxt++ -> redirect to other | [enqueue data]
> | |
> | ingress to FD1
> v ^
> ... | [sockmap]
> FD2 native stack
>
> Closes: https://syzkaller.appspot.com/bug?extid=06dbd397158ec0ea4983
> Fixes: 04919bed948dc ("tcp: Introduce tcp_read_skb()")
> Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
> ---
> include/linux/skmsg.h | 25 ++++++++++++++++++++++++-
> net/core/skmsg.c | 19 ++++++++++++++++---
> net/ipv4/tcp_bpf.c | 5 +++--
> 3 files changed, 43 insertions(+), 6 deletions(-)
>
> diff --git a/include/linux/skmsg.h b/include/linux/skmsg.h
> index 49847888c287..b7826cb2a388 100644
> --- a/include/linux/skmsg.h
> +++ b/include/linux/skmsg.h
> @@ -23,6 +23,17 @@ enum __sk_action {
> __SK_NONE,
> };
>
> +/* The BPF program sets BPF_F_INGRESS on sk_msg to indicate data needs to be
> + * redirected to the ingress queue of a specified socket. Since BPF_F_INGRESS is
> + * defined in UAPI so that we can't extend this enum for our internal flags. We
> + * define some internal flags here while inheriting BPF_F_INGRESS.
> + */
> +enum {
> + SK_MSG_F_INGRESS = BPF_F_INGRESS, /* (1ULL << 0) */
> + /* internal flag */
> + SK_MSG_F_INGRESS_SELF = (1ULL << 1)
> +};
> +
I'm wondering if we need additional state to track this.
Can we track sk_msg's construted from skb's that were not redirected by
setting `sk_msg.sk = sk` to indicate that the source socket is us in
sk_psock_skb_ingress_self()?
If not, then I'd just offset the internal flags like we do in
net/core/filter.c, BPF_F_REDIRECT_INTERNAL.
> struct sk_msg_sg {
> u32 start;
> u32 curr;
> @@ -141,8 +152,20 @@ int sk_msg_memcopy_from_iter(struct sock *sk, struct iov_iter *from,
> struct sk_msg *msg, u32 bytes);
> int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg,
> int len, int flags);
> +int __sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg,
> + int len, int flags, int *from_self_copied);
> bool sk_msg_is_readable(struct sock *sk);
>
> +static inline bool sk_msg_is_to_self(struct sk_msg *msg)
> +{
> + return msg->flags & SK_MSG_F_INGRESS_SELF;
> +}
> +
> +static inline void sk_msg_set_to_self(struct sk_msg *msg)
> +{
> + msg->flags |= SK_MSG_F_INGRESS_SELF;
> +}
> +
> static inline void sk_msg_check_to_free(struct sk_msg *msg, u32 i, u32 bytes)
> {
> WARN_ON(i == msg->sg.end && bytes);
> @@ -235,7 +258,7 @@ static inline struct page *sk_msg_page(struct sk_msg *msg, int which)
>
> static inline bool sk_msg_to_ingress(const struct sk_msg *msg)
> {
> - return msg->flags & BPF_F_INGRESS;
> + return msg->flags & SK_MSG_F_INGRESS;
> }
>
> static inline void sk_msg_compute_data_pointers(struct sk_msg *msg)
> diff --git a/net/core/skmsg.c b/net/core/skmsg.c
> index 2ac7731e1e0a..25d88c2082e9 100644
> --- a/net/core/skmsg.c
> +++ b/net/core/skmsg.c
> @@ -409,14 +409,14 @@ int sk_msg_memcopy_from_iter(struct sock *sk, struct iov_iter *from,
> }
> EXPORT_SYMBOL_GPL(sk_msg_memcopy_from_iter);
>
> -/* Receive sk_msg from psock->ingress_msg to @msg. */
> -int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg,
> - int len, int flags)
> +int __sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg,
> + int len, int flags, int *from_self_copied)
> {
> struct iov_iter *iter = &msg->msg_iter;
> int peek = flags & MSG_PEEK;
> struct sk_msg *msg_rx;
> int i, copied = 0;
> + bool to_self;
>
> msg_rx = sk_psock_peek_msg(psock);
> while (copied != len) {
> @@ -425,6 +425,7 @@ int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg,
> if (unlikely(!msg_rx))
> break;
>
> + to_self = sk_msg_is_to_self(msg_rx);
> i = msg_rx->sg.start;
> do {
> struct page *page;
> @@ -443,6 +444,9 @@ int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg,
> }
>
> copied += copy;
> + if (to_self && from_self_copied)
> + *from_self_copied += copy;
> +
> if (likely(!peek)) {
> sge->offset += copy;
> sge->length -= copy;
> @@ -487,6 +491,14 @@ int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg,
> out:
> return copied;
> }
> +EXPORT_SYMBOL_GPL(__sk_msg_recvmsg);
> +
> +/* Receive sk_msg from psock->ingress_msg to @msg. */
> +int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg,
> + int len, int flags)
> +{
> + return __sk_msg_recvmsg(sk, psock, msg, len, flags, NULL);
> +}
> EXPORT_SYMBOL_GPL(sk_msg_recvmsg);
>
> bool sk_msg_is_readable(struct sock *sk)
> @@ -616,6 +628,7 @@ static int sk_psock_skb_ingress_self(struct sk_psock *psock, struct sk_buff *skb
> if (unlikely(!msg))
> return -EAGAIN;
> skb_set_owner_r(skb, sk);
> + sk_msg_set_to_self(msg);
> err = sk_psock_skb_ingress_enqueue(skb, off, len, psock, sk, msg, take_ref);
> if (err < 0)
> kfree(msg);
> diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c
> index a268e1595b22..6332fc36ffe6 100644
> --- a/net/ipv4/tcp_bpf.c
> +++ b/net/ipv4/tcp_bpf.c
> @@ -226,6 +226,7 @@ static int tcp_bpf_recvmsg_parser(struct sock *sk,
> int peek = flags & MSG_PEEK;
> struct sk_psock *psock;
> struct tcp_sock *tcp;
> + int from_self_copied = 0;
> int copied = 0;
> u32 seq;
>
> @@ -262,7 +263,7 @@ static int tcp_bpf_recvmsg_parser(struct sock *sk,
> }
>
> msg_bytes_ready:
> - copied = sk_msg_recvmsg(sk, psock, msg, len, flags);
> + copied = __sk_msg_recvmsg(sk, psock, msg, len, flags, &from_self_copied);
> /* The typical case for EFAULT is the socket was gracefully
> * shutdown with a FIN pkt. So check here the other case is
> * some error on copy_page_to_iter which would be unexpected.
> @@ -277,7 +278,7 @@ static int tcp_bpf_recvmsg_parser(struct sock *sk,
> goto out;
> }
> }
> - seq += copied;
> + seq += from_self_copied;
> if (!copied) {
> long timeo;
> int data;
next prev parent reply other threads:[~2025-11-19 19:53 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-11-17 11:07 [PATCH bpf-next v1 0/3] bpf: Fix FIONREAD and copied_seq issues Jiayuan Chen
2025-11-17 11:07 ` [PATCH bpf-next v1 1/3] bpf, sockmap: Fix incorrect copied_seq calculation Jiayuan Chen
2025-11-19 19:53 ` Jakub Sitnicki [this message]
2025-11-20 2:49 ` Jiayuan Chen
2025-11-20 12:58 ` Jakub Sitnicki
2025-11-20 14:03 ` Jiayuan Chen
2025-11-17 11:07 ` [PATCH bpf-next v1 2/3] bpf, sockmap: Fix FIONREAD for sockmap Jiayuan Chen
2025-11-17 11:07 ` [PATCH bpf-next v1 3/3] bpf, selftest: Add tests for FIONREAD and copied_seq Jiayuan Chen
2025-11-21 19:12 ` [syzbot ci] Re: bpf: Fix FIONREAD and copied_seq issues syzbot ci
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=87zf8h6bpd.fsf@cloudflare.com \
--to=jakub@cloudflare.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=cong.wang@bytedance.com \
--cc=daniel@iogearbox.net \
--cc=davem@davemloft.net \
--cc=dsahern@kernel.org \
--cc=eddyz87@gmail.com \
--cc=edumazet@google.com \
--cc=haoluo@google.com \
--cc=horms@kernel.org \
--cc=jiayuan.chen@linux.dev \
--cc=john.fastabend@gmail.com \
--cc=jolsa@kernel.org \
--cc=kpsingh@kernel.org \
--cc=kuba@kernel.org \
--cc=kuniyu@google.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=martin.lau@linux.dev \
--cc=mhal@rbox.co \
--cc=ncardwell@google.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=sdf@fomichev.me \
--cc=sgarzare@redhat.com \
--cc=shuah@kernel.org \
--cc=song@kernel.org \
--cc=yonghong.song@linux.dev \
/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.