bpf: fix wrong copied_seq calculation and add tests
Subsystems (9)
v9 cover bpf: fix wrong copied_seq calculation and add tests
A previous commit described in this topic
http://lore.kernel.org/bpf/[email protected]
directly updated 'sk->copied_seq' in the tcp_eat_skb() function when the action of a BPF program was SK_REDIRECT. For other actions, like SK_PASS, the update logic for 'sk->copied_seq' was moved to tcp_bpf_recvmsg_parser() to ensure the accuracy of the 'fionread' feature.
That commit works for a single stream_verdict scenario, as it also modified 'sk_data_ready->sk_psock_verdict_data_ready->tcp_read_skb' to remove updating 'sk->copied_seq'.
However, for programs where both stream_parser and stream_verdict are active (strparser purpose), tcp_read_sock() was used instead of tcp_read_skb() (sk_data_ready->strp_data_ready->tcp_read_sock). tcp_read_sock() now still updates 'sk->copied_seq', leading to duplicated updates.
In summary, for strparser + SK_PASS, copied_seq is redundantly calculated in both tcp_read_sock() and tcp_bpf_recvmsg_parser().
The issue causes incorrect copied_seq calculations, which prevent correct data reads from the recv() interface in user-land.
Also we added test cases for bpf + strparser and separated them from sockmap_basic, as strparser has more encapsulation and parsing capabilities compared to sockmap.
---
V8 -> v9
https://lore.kernel.org/bpf/[email protected]/
Fixed some issues suggested by Jakub Sitnicki.
V7 -> V8
https://lore.kernel.org/bpf/[email protected]/
Avoid using add read_sock to psock. (Jakub Sitnicki)
Avoid using warpper function to check whether strparser is supported.
V3 -> V7:
https://lore.kernel.org/bpf/[email protected]/
https://lore.kernel.org/bpf/[email protected]/
Avoid introducing new proto_ops. (Jakub Sitnicki). Add more edge test cases for strparser + bpf. Fix patchwork fail of test cases code.
Fix psock fetch without rcu lock.
Move code of modifying to tcp_bpf.c.
V1 -> V3:
https://lore.kernel.org/bpf/[email protected]/
Fix patchwork fail by adding Fixes tag.
Save skb data offset for ENOMEM. (John Fastabend)
---
Jiayuan Chen (5):
strparser: add read_sock callback
bpf: fix wrong copied_seq calculation
bpf: disable non stream socket for strparser
selftests/bpf: fix invalid flag of recv()
selftests/bpf: add strparser test for bpf
Documentation/networking/strparser.rst | 9 +- include/linux/skmsg.h | 2 + include/net/strparser.h | 2 + include/net/tcp.h | 8 + net/core/skmsg.c | 7 + net/core/sock_map.c | 5 +- net/ipv4/tcp.c | 29 +- net/ipv4/tcp_bpf.c | 36 ++ net/strparser/strparser.c | 11 +- .../selftests/bpf/prog_tests/sockmap_basic.c | 59 +-- .../selftests/bpf/prog_tests/sockmap_strp.c | 454 ++++++++++++++++++ .../selftests/bpf/progs/test_sockmap_strp.c | 53 ++ 12 files changed, 610 insertions(+), 65 deletions(-) create mode 100644 tools/testing/selftests/bpf/prog_tests/sockmap_strp.c create mode 100644 tools/testing/selftests/bpf/progs/test_sockmap_strp.c
Signature · 1 line
2.43.5
PATCH v9 1/5 strparser: add read_sock callback
Added a new read_sock handler, allowing users to customize read operations instead of relying on the native socket's read_sock.
--- Documentation/networking/strparser.rst | 9 ++++++++- include/net/strparser.h | 2 ++ net/strparser/strparser.c | 11 +++++++++-- 3 files changed, 19 insertions(+), 3 deletions(-)
Documentation/networking/strparser.rst +8 -1
@@ -112,7 +112,7 @@ Functions Callbacks ========= -There are six callbacks: +There are seven callbacks: ::
@@ -182,6 +182,13 @@ There are six callbacks: the length of the message. skb->len - offset may be greater then full_len since strparser does not trim the skb. + :: + + int (*read_sock)(struct strparser *strp, read_descriptor_t *desc, + sk_read_actor_t recv_actor); + + The read_sock callback is used by strparser instead of + sock->ops->read_sock, if provided. :: int (*read_sock_done)(struct strparser *strp, int err);
include/net/strparser.h +2 -0
@@ -43,6 +43,8 @@ struct strparser;struct strp_callbacks {int (*parse_msg)(struct strparser *strp,struct sk_buff *skb);void (*rcv_msg)(struct strparser *strp,struct sk_buff *skb); +int (*read_sock)(struct strparser *strp,read_descriptor_t *desc, +sk_read_actor_t recv_actor);int (*read_sock_done)(struct strparser *strp,int err);void (*abort_parser)(struct strparser *strp,int err);void (*lock)(struct strparser *strp);
net/strparser/strparser.c +9 -2
@@ -347,7 +347,10 @@ static int strp_read_sock(struct strparser *strp)struct socket *sock = strp->sk->sk_socket;read_descriptor_t desc; -if (unlikely (!sock || !sock->ops || !sock->ops->read_sock)) +if (unlikely (!sock || !sock->ops)) +return -EBUSY ; + +if (unlikely (!strp->cb.read_sock && !sock->ops->read_sock))return -EBUSY ; desc.arg.data = strp;
@@ -355,7 +358,10 @@ static int strp_read_sock(struct strparser *strp) desc.count =1 ;/* give more than one skb per call */ /* sk should be locked here, so okay to do read_sock */ - sock->ops->read_sock (strp->sk, &desc, strp_recv); +if (strp->cb.read_sock) + strp->cb.read_sock (strp, &desc, strp_recv); +else + sock->ops->read_sock (strp->sk, &desc, strp_recv); desc.error = strp->cb.read_sock_done (strp, desc.error);
@@ -468,6 +474,7 @@ int strp_init(struct strparser *strp, struct sock *sk, strp->cb.unlock = cb->unlock ? : strp_sock_unlock; strp->cb.rcv_msg = cb->rcv_msg; strp->cb.parse_msg = cb->parse_msg; + strp->cb.read_sock = cb->read_sock; strp->cb.read_sock_done = cb->read_sock_done ? : default_read_sock_done; strp->cb.abort_parser = cb->abort_parser ? : strp_abort_strp;
Signature · 1 line
2.43.5
Re: [PATCH bpf v9 1/5] strparser: add read_sock callback
Quoted 5 lines · Jiayuan Chen
Added a new
read_sockhandler, allowing users to customize read operations instead of relying on the native socket'sread_sock.Signed-off-by Jiayuan Chen <[email protected]>---
PATCH v9 2/5 bpf: fix wrong copied_seq calculation
In reply to Jiayuan Chen'sk->copied_seq' was updated in the tcp_eat_skb() function when the action of a BPF program was SK_REDIRECT. For other actions, like SK_PASS, the update logic for 'sk->copied_seq' was moved to tcp_bpf_recvmsg_parser() to ensure the accuracy of the 'fionread' feature.
It works for a single stream_verdict scenario, as it also modified sk_data_ready->sk_psock_verdict_data_ready->tcp_read_skb to remove updating 'sk->copied_seq'.
However, for programs where both stream_parser and stream_verdict are active (strparser purpose), tcp_read_sock() was used instead of tcp_read_skb() (sk_data_ready->strp_data_ready->tcp_read_sock). tcp_read_sock() now still updates 'sk->copied_seq', leading to duplicate updates.
In summary, for strparser + SK_PASS, copied_seq is redundantly calculated in both tcp_read_sock() and tcp_bpf_recvmsg_parser().
The issue causes incorrect copied_seq calculations, which prevent correct data reads from the recv() interface in user-land.
We do not want to add new proto_ops to implement a new version of tcp_read_sock, as this would introduce code complexity [1].
We could have added noack and copied_seq to desc, and then called ops->read_sock. However, unfortunately, other modules didn’t fully initialize desc to zero. So, for now, we are directly calling tcp_read_sock_noack() in tcp_bpf.c.
[1]: https://lore.kernel.org/bpf/[email protected]
--- include/linux/skmsg.h | 2 ++ include/net/tcp.h | 8 ++++++++ net/core/skmsg.c | 7 +++++++ net/ipv4/tcp.c | 29 ++++++++++++++++++++++++----- net/ipv4/tcp_bpf.c | 36 ++++++++++++++++++++++++++++++++++++ 5 files changed, 77 insertions(+), 5 deletions(-)
include/linux/skmsg.h +2 -0
@@ -91,6 +91,8 @@ struct sk_psock {struct sk_psock_progs progs;#if IS_ENABLED (CONFIG_BPF_STREAM_PARSER )struct strparser strp; +u32 copied_seq; +u32 ingress_bytes;#endif struct sk_buff_head ingress_skb;struct list_head ingress_msg;
include/net/tcp.h +8 -0
@@ -729,6 +729,9 @@ void tcp_get_info(struct sock *, struct tcp_info *);/* Read 'sendfile()'-style from a TCP socket */ int tcp_read_sock (struct sock *sk,read_descriptor_t *desc,sk_read_actor_t recv_actor); +int tcp_read_sock_noack (struct sock *sk,read_descriptor_t *desc, +sk_read_actor_t recv_actor,bool noack, +u32 *copied_seq);int tcp_read_skb (struct sock *sk,skb_read_actor_t recv_actor);struct sk_buff *tcp_recv_skb (struct sock *sk,u32 seq,u32 *off);void tcp_read_done (struct sock *sk,size_t len);
@@ -2599,6 +2602,11 @@ struct sk_psock;#ifdef CONFIG_BPF_SYSCALL int tcp_bpf_update_proto (struct sock *sk,struct sk_psock *psock,bool restore);void tcp_bpf_clone (const struct sock *sk,struct sock *newsk); +#ifdef CONFIG_BPF_STREAM_PARSER +struct strparser ; +int tcp_bpf_strp_read_sock (struct strparser *strp,read_descriptor_t *desc, +sk_read_actor_t recv_actor); +#endif /* CONFIG_BPF_STREAM_PARSER */ #endif /* CONFIG_BPF_SYSCALL */ #ifdef CONFIG_INET
net/core/skmsg.c +7 -0
@@ -549,6 +549,9 @@ static int sk_psock_skb_ingress_enqueue(struct sk_buff *skb,return num_sge; } +#if IS_ENABLED (CONFIG_BPF_STREAM_PARSER ) + psock->ingress_bytes += len; +#endif copied = len; msg->sg.start =0 ; msg->sg.size = copied;
@@ -1144,6 +1147,10 @@ int sk_psock_init_strp(struct sock *sk, struct sk_psock *psock)if (!ret)sk_psock_set_state (psock,SK_PSOCK_RX_STRP_ENABLED ); +if (sk_is_tcp (sk)) { + psock->strp.cb.read_sock = tcp_bpf_strp_read_sock; + psock->copied_seq =tcp_sk (sk)->copied_seq; + }return ret; }
net/ipv4/tcp.c +24 -5
@@ -1565,12 +1565,13 @@ EXPORT_SYMBOL(tcp_recv_skb);* or for 'peeking' the socket using this routine * (although both would be easy to implement). */ -int tcp_read_sock (struct sock *sk,read_descriptor_t *desc, -sk_read_actor_t recv_actor) +static int __tcp_read_sock (struct sock *sk,read_descriptor_t *desc, +sk_read_actor_t recv_actor,bool noack, +u32 *copied_seq) {struct sk_buff *skb;struct tcp_sock *tp =tcp_sk (sk); -u32 seq = tp->copied_seq; +u32 seq = *copied_seq;u32 offset;int copied =0 ;
@@ -1624,9 +1625,12 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,tcp_eat_recv_skb (sk, skb);if (!desc->count)break ; -WRITE_ONCE (tp->copied_seq, seq); +WRITE_ONCE (*copied_seq, seq); } -WRITE_ONCE (tp->copied_seq, seq); +WRITE_ONCE (*copied_seq, seq); + +if (noack) + goto out;tcp_rcv_space_adjust (sk);
@@ -1635,10 +1639,25 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,tcp_recv_skb (sk, seq, &offset);tcp_cleanup_rbuf (sk, copied); } +out:return copied; } + +int tcp_read_sock (struct sock *sk,read_descriptor_t *desc, +sk_read_actor_t recv_actor) +{ +return __tcp_read_sock (sk, desc, recv_actor, false, + &tcp_sk (sk)->copied_seq); +}EXPORT_SYMBOL (tcp_read_sock); +int tcp_read_sock_noack (struct sock *sk,read_descriptor_t *desc, +sk_read_actor_t recv_actor,bool noack, +u32 *copied_seq) +{ +return __tcp_read_sock (sk, desc, recv_actor, noack, copied_seq); +} +int tcp_read_skb (struct sock *sk,skb_read_actor_t recv_actor) {struct sk_buff *skb;
net/ipv4/tcp_bpf.c +36 -0
@@ -646,6 +646,42 @@ static int tcp_bpf_assert_proto_ops(struct proto *ops) ops->sendmsg == tcp_sendmsg ?0 : -ENOTSUPP ; } +#if IS_ENABLED (CONFIG_BPF_STREAM_PARSER ) +int tcp_bpf_strp_read_sock (struct strparser *strp,read_descriptor_t *desc, +sk_read_actor_t recv_actor) +{ +struct sock *sk = strp->sk; +struct sk_psock *psock; +struct tcp_sock *tp; +int copied =0 ; + + tp =tcp_sk (sk); +rcu_read_lock (); + psock =sk_psock (sk); +if (WARN_ON_ONCE (!psock)) { + desc->error = -EINVAL ; + goto out; + } + + psock->ingress_bytes =0 ; + copied =tcp_read_sock_noack (sk, desc, recv_actor, true, + &psock->copied_seq); +if (copied <0 ) + goto out; +/* recv_actor may redirect skb to another socket (SK_REDIRECT) or +* just put skb into ingress queue of current socket (SK_PASS). +* For SK_REDIRECT, we need to ack the frame immediately but for +* SK_PASS, we want to delay the ack until tcp_bpf_recvmsg_parser(). +*/ + tp->copied_seq = psock->copied_seq - psock->ingress_bytes; +tcp_rcv_space_adjust (sk); +__tcp_cleanup_rbuf (sk, copied - psock->ingress_bytes); +out: +rcu_read_unlock (); +return copied; +} +#endif /* CONFIG_BPF_STREAM_PARSER */ +int tcp_bpf_update_proto (struct sock *sk,struct sk_psock *psock,bool restore) {int family = sk->sk_family ==AF_INET6 ?TCP_BPF_IPV6 :TCP_BPF_IPV4 ;
Signature · 1 line
2.43.5
Re: [PATCH bpf v9 2/5] bpf: fix wrong copied_seq calculation
Quoted 29 lines · Jiayuan Chen
'
sk->copied_seq' was updated in thetcp_eat_skb()function when the action of a BPF program wasSK_REDIRECT. For other actions, likeSK_PASS, the update logic for 'sk->copied_seq' was moved totcp_bpf_recvmsg_parser()to ensure the accuracy of the 'fionread' feature.It works for a single
stream_verdictscenario, as it also modifiedsk_data_ready->sk_psock_verdict_data_ready->tcp_read_skbto remove updating 'sk->copied_seq'.However, for programs where both
stream_parserandstream_verdictare active (strparser purpose),tcp_read_sock()was used instead oftcp_read_skb()(sk_data_ready->strp_data_ready->tcp_read_sock).tcp_read_sock()now still updates 'sk->copied_seq', leading to duplicate updates.In summary, for strparser +
SK_PASS,copied_seqis redundantly calculated in bothtcp_read_sock()andtcp_bpf_recvmsg_parser().The issue causes incorrect
copied_seqcalculations, which prevent correct data reads from therecv()interface in user-land.We do not want to add new
proto_opsto implement a new version oftcp_read_sock, as this would introduce code complexity [1].We could have added noack and
copied_seqto desc, and then calledops->read_sock. However, unfortunately, other modules didn’t fully initialize desc to zero. So, for now, we are directly callingtcp_read_sock_noack()intcp_bpf.c.
Quoted 5 lines
[1]: https://lore.kernel.org/bpf/[email protected]
Fixes e5c6de5fa025 ("bpf, sockmap: Incorrectly handling copied_seq")Suggested-by Jakub Sitnicki <[email protected]>Signed-off-by Jiayuan Chen <[email protected]>---
I'm happy with how this turned out, but let's run it by Eric.
PATCH v9 3/5 bpf: disable non stream socket for strparser
In reply to Jiayuan ChenCurrently, only TCP supports strparser, but sockmap doesn't intercept non-TCP connections to attach strparser. For example, with UDP, although the read/write handlers are replaced, strparser is not executed due to the lack of a read_sock operation.
Furthermore, in udp_bpf_recvmsg(), it checks whether the psock has data, and if not, it falls back to the native UDP read interface, making UDP + strparser appear to read correctly. According to its commit history, this behavior is unexpected.
Moreover, since UDP lacks the concept of streams, we intercept it directly.
--- net/core/sock_map.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
net/core/sock_map.c +4 -1
@@ -303,7 +303,10 @@ static int sock_map_link(struct bpf_map *map, struct sock *sk)write_lock_bh (&sk->sk_callback_lock);if (stream_parser && stream_verdict && !psock->saved_data_ready) { - ret =sk_psock_init_strp (sk, psock); +if (sk_is_tcp (sk)) + ret =sk_psock_init_strp (sk, psock); +else + ret = -EOPNOTSUPP ;if (ret) {write_unlock_bh (&sk->sk_callback_lock);sk_psock_put (sk, psock);
Signature · 1 line
2.43.5
Re: [PATCH bpf v9 3/5] bpf: disable non stream socket for strparser
Quoted 10 lines · Jiayuan Chen
Currently, only TCP supports strparser, but sockmap doesn't intercept non-TCP connections to attach strparser. For example, with UDP, although the read/write handlers are replaced, strparser is not executed due to the lack of a
read_sockoperation.Furthermore, in
udp_bpf_recvmsg(), it checks whether the psock has data, and if not, it falls back to the native UDP read interface, making UDP + strparser appear to read correctly. According to its commit history, this behavior is unexpected.
Quoted 5 lines
Moreover, since UDP lacks the concept of streams, we intercept it directly.
Fixes 1fa1fe8ff161 ("bpf, sockmap: Test shutdown() correctly exits epoll and recv()=0")Signed-off-by Jiayuan Chen <[email protected]>---
PATCH v9 4/5 selftests/bpf: fix invalid flag of recv()
In reply to Jiayuan ChenSOCK_NONBLOCK flag is only effective during socket creation, not during recv. Use MSG_DONTWAIT instead.
--- tools/testing/selftests/bpf/prog_tests/sockmap_basic.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
tools/testing/selftests/bpf/prog_tests/sockmap_basic.c +3 -3
@@ -522,8 +522,8 @@ static void test_sockmap_skb_verdict_shutdown(void)if (!ASSERT_EQ (err,1 ,"epoll_wait(fd)" )) goto out_close; - n =recv (c1, &b,1 ,SOCK_NONBLOCK ); -ASSERT_EQ (n,0 ,"recv_timeout(fin)" ); + n =recv (c1, &b,1 ,MSG_DONTWAIT ); +ASSERT_EQ (n,0 ,"recv(fin)" ); out_close:close (c1);close (p1);
@@ -628,7 +628,7 @@ static void test_sockmap_skb_verdict_fionread(bool pass_prog)ASSERT_EQ (avail, expected,"ioctl(FIONREAD)" );/* On DROP test there will be no data to read */ if (pass_prog) { - recvd =recv_timeout (c1, &buf,sizeof (buf),SOCK_NONBLOCK ,IO_TIMEOUT_SEC ); + recvd =recv_timeout (c1, &buf,sizeof (buf),MSG_DONTWAIT ,IO_TIMEOUT_SEC );ASSERT_EQ (recvd,sizeof (buf),"recv_timeout(c0)" ); }
Signature · 1 line
2.43.5
Re: [PATCH bpf v9 4/5] selftests/bpf: fix invalid flag of recv()
Quoted 5 lines · Jiayuan Chen
SOCK_NONBLOCKflag is only effective during socket creation, not during recv. UseMSG_DONTWAITinstead.Signed-off-by Jiayuan Chen <[email protected]>---
PATCH v9 5/5 selftests/bpf: add strparser test for bpf
In reply to Jiayuan ChenAdd test cases for bpf + strparser and separated them from sockmap_basic, as strparser has more encapsulation and parsing capabilities compared to standard sockmap.
--- .../selftests/bpf/prog_tests/sockmap_basic.c | 53 -- .../selftests/bpf/prog_tests/sockmap_strp.c | 454 ++++++++++++++++++ .../selftests/bpf/progs/test_sockmap_strp.c | 53 ++ 3 files changed, 507 insertions(+), 53 deletions(-) create mode 100644 tools/testing/selftests/bpf/prog_tests/sockmap_strp.c create mode 100644 tools/testing/selftests/bpf/progs/test_sockmap_strp.c
tools/testing/selftests/bpf/prog_tests/sockmap_basic.c +0 -53
@@ -531,57 +531,6 @@ static void test_sockmap_skb_verdict_shutdown(void)test_sockmap_pass_prog__destroy (skel); } -static void test_sockmap_stream_pass (void ) -{ -int zero =0 , sent, recvd; -int verdict, parser; -int err, map; -int c =-1 , p =-1 ; -struct test_sockmap_pass_prog *pass =NULL ; -char snd[256 ] ="0123456789" ; -char rcv[256 ] ="0" ; - - pass =test_sockmap_pass_prog__open_and_load (); - verdict =bpf_program__fd (pass->progs.prog_skb_verdict); - parser =bpf_program__fd (pass->progs.prog_skb_parser); - map =bpf_map__fd (pass->maps.sock_map_rx); - - err =bpf_prog_attach (parser, map,BPF_SK_SKB_STREAM_PARSER ,0 ); -if (!ASSERT_OK (err,"bpf_prog_attach stream parser" )) - goto out; - - err =bpf_prog_attach (verdict, map,BPF_SK_SKB_STREAM_VERDICT ,0 ); -if (!ASSERT_OK (err,"bpf_prog_attach stream verdict" )) - goto out; - - err =create_pair (AF_INET ,SOCK_STREAM , &c, &p); -if (err) - goto out; - -/* sk_data_ready of 'p' will be replaced by strparser handler */ - err =bpf_map_update_elem (map, &zero, &p,BPF_NOEXIST ); -if (!ASSERT_OK (err,"bpf_map_update_elem(p)" )) - goto out_close; - -/* -* as 'prog_skb_parser' return the original skb len and -* 'prog_skb_verdict' return SK_PASS, the kernel will just -* pass it through to original socket 'p' -*/ - sent =xsend (c, snd,sizeof (snd),0 ); -ASSERT_EQ (sent,sizeof (snd),"xsend(c)" ); - - recvd =recv_timeout (p, rcv,sizeof (rcv),SOCK_NONBLOCK , -IO_TIMEOUT_SEC ); -ASSERT_EQ (recvd,sizeof (rcv),"recv_timeout(p)" ); - -out_close: -close (c); -close (p); - -out: -test_sockmap_pass_prog__destroy (pass); -}static void test_sockmap_skb_verdict_fionread (bool pass_prog) {
@@ -1101,8 +1050,6 @@ void test_sockmap_basic(void)test_sockmap_progs_query (BPF_SK_SKB_VERDICT );if (test__start_subtest ("sockmap skb_verdict shutdown" ))test_sockmap_skb_verdict_shutdown (); -if (test__start_subtest ("sockmap stream parser and verdict pass" )) -test_sockmap_stream_pass ();if (test__start_subtest ("sockmap skb_verdict fionread" ))test_sockmap_skb_verdict_fionread (true);if (test__start_subtest ("sockmap skb_verdict fionread on drop" ))
tools/testing/selftests/bpf/prog_tests/sockmap_strp.c new file +454 -0
454 lines not on this page · raw message
tools/testing/selftests/bpf/progs/test_sockmap_strp.c new file +53 -0
53 lines not on this page · raw message
Signature · 1 line
2.43.5
Re: [PATCH bpf v9 5/5] selftests/bpf: add strparser test for bpf
Quoted 6 lines · Jiayuan Chen
Add test cases for bpf + strparser and separated them from
sockmap_basic, as strparser has more encapsulation and parsing capabilities compared to standard sockmap.Signed-off-by Jiayuan Chen <[email protected]>---
Jakub Sitnicki
maintainerQuoted 46 lines · Jiayuan Chen
A previous commit described in this topic
http://lore.kernel.org/bpf/[email protected]
directly updated 'sk->copied_seq' in thetcp_eat_skb()function when the action of a BPF program wasSK_REDIRECT. For other actions, likeSK_PASS, the update logic for 'sk->copied_seq' was moved totcp_bpf_recvmsg_parser()to ensure the accuracy of the 'fionread' feature.That commit works for a single
stream_verdictscenario, as it also modified 'sk_data_ready->sk_psock_verdict_data_ready->tcp_read_skb' to remove updating 'sk->copied_seq'.However, for programs where both
stream_parserandstream_verdictare active (strparser purpose),tcp_read_sock()was used instead oftcp_read_skb()(sk_data_ready->strp_data_ready->tcp_read_sock).tcp_read_sock()now still updates 'sk->copied_seq', leading to duplicated updates.In summary, for strparser +
SK_PASS,copied_seqis redundantly calculated in bothtcp_read_sock()andtcp_bpf_recvmsg_parser().The issue causes incorrect
copied_seqcalculations, which prevent correct data reads from therecv()interface in user-land.Also we added test cases for bpf + strparser and separated them from
sockmap_basic, as strparser has more encapsulation and parsing capabilities compared to sockmap.---
V8 -> v9
https://lore.kernel.org/bpf/[email protected]/
Fixed some issues suggested by Jakub Sitnicki.V7 -> V8
https://lore.kernel.org/bpf/[email protected]/
Avoid using addread_sockto psock. (Jakub Sitnicki)
Avoid using warpper function to check whether strparser is supported.V3 -> V7:
https://lore.kernel.org/bpf/[email protected]/
https://lore.kernel.org/bpf/[email protected]/
Avoid introducing newproto_ops. (Jakub Sitnicki). Add more edge test cases for strparser + bpf. Fix patchwork fail of test cases code.
Fix psock fetch without rcu lock.
Move code of modifying totcp_bpf.c.
Quoted 5 lines
V1 -> V3:
https://lore.kernel.org/bpf/[email protected]/
Fix patchwork fail by adding Fixes tag.
Save skb data offset for ENOMEM. (John Fastabend)
---
Thanks for addressing all feedback, Jiayuan. Series LGTM. Feel free to carry my tags if there is another iteration.
-jkbs
Quoted 47 lines · Jakub Sitnicki
Quoted 46 lines · Jiayuan Chen
A previous commit described in this topic
http://lore.kernel.org/bpf/[email protected]
directly updated 'sk->copied_seq' in thetcp_eat_skb()function when the action of a BPF program wasSK_REDIRECT. For other actions, likeSK_PASS, the update logic for 'sk->copied_seq' was moved totcp_bpf_recvmsg_parser()to ensure the accuracy of the 'fionread' feature.That commit works for a single
stream_verdictscenario, as it also modified 'sk_data_ready->sk_psock_verdict_data_ready->tcp_read_skb' to remove updating 'sk->copied_seq'.However, for programs where both
stream_parserandstream_verdictare active (strparser purpose),tcp_read_sock()was used instead oftcp_read_skb()(sk_data_ready->strp_data_ready->tcp_read_sock).tcp_read_sock()now still updates 'sk->copied_seq', leading to duplicated updates.In summary, for strparser +
SK_PASS,copied_seqis redundantly calculated in bothtcp_read_sock()andtcp_bpf_recvmsg_parser().The issue causes incorrect
copied_seqcalculations, which prevent correct data reads from therecv()interface in user-land.Also we added test cases for bpf + strparser and separated them from
sockmap_basic, as strparser has more encapsulation and parsing capabilities compared to sockmap.---
V8 -> v9
https://lore.kernel.org/bpf/[email protected]/
Fixed some issues suggested by Jakub Sitnicki.V7 -> V8
https://lore.kernel.org/bpf/[email protected]/
Avoid using addread_sockto psock. (Jakub Sitnicki)
Avoid using warpper function to check whether strparser is supported.V3 -> V7:
https://lore.kernel.org/bpf/[email protected]/
https://lore.kernel.org/bpf/[email protected]/
Avoid introducing newproto_ops. (Jakub Sitnicki). Add more edge test cases for strparser + bpf. Fix patchwork fail of test cases code.
Fix psock fetch without rcu lock.
Move code of modifying totcp_bpf.c.
Quoted 8 lines
Quoted 5 lines
V1 -> V3:
https://lore.kernel.org/bpf/[email protected]/
Fix patchwork fail by adding Fixes tag.
Save skb data offset for ENOMEM. (John Fastabend)
---Thanks for addressing all feedback, Jiayuan. Series LGTM. Feel free to carry my tags if there is another iteration.
+1 Thanks Jiayuan for sticking with this.
I've reviewed this a couple times. I had one nit on the if/else branch for a read call, but I haven't come up with anything better on my end and this fixes a real bug. So lets take it.
For the series.
Quoted 2 lines
-jkbs
This series was applied to bpf/bpf.git (master) by Martin KaFai Lau <[email protected]>:
Hello:
This series was applied to bpf/bpf.git (master)
by Martin KaFai Lau <[email protected]>:
Quoted 8 lines · On Wed, 22 Jan 2025 18:09:12 +0800 you wrote:
A previous commit described in this topic
http://lore.kernel.org/bpf/[email protected]
directly updated 'sk->copied_seq' in thetcp_eat_skb()function when the action of a BPF program wasSK_REDIRECT. For other actions, likeSK_PASS, the update logic for 'sk->copied_seq' was moved totcp_bpf_recvmsg_parser()to ensure the accuracy of the 'fionread' feature.[...]
Here is the summary with links:
- [bpf,v9,1/5] strparser: add read_sock callback
https://git.kernel.org/bpf/bpf/c/0532a79efd68 - [bpf,v9,2/5] bpf: fix wrong copied_seq calculation https://git.kernel.org/bpf/bpf/c/36b62df5683c - [bpf,v9,3/5] bpf: disable non stream socket for strparser https://git.kernel.org/bpf/bpf/c/5459cce6bf49 - [bpf,v9,4/5] selftests/bpf: fix invalid flag of recv() https://git.kernel.org/bpf/bpf/c/a0c11149509a - [bpf,v9,5/5] selftests/bpf: add strparser test for bpf https://git.kernel.org/bpf/bpf/c/6fcfe96e0f6e
You are awesome, thank you!
Signature · 2 lines
Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html