All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jiayuan Chen <jiayuan.chen@linux.dev>
To: Martin KaFai Lau <martin.lau@linux.dev>
Cc: Jiayuan Chen <jiayuan.chen@shopee.com>,
	Daniel Borkmann <daniel@iogearbox.net>,
	John Fastabend <john.fastabend@gmail.com>,
	Stanislav Fomichev <sdf@fomichev.me>,
	Alexei Starovoitov <ast@kernel.org>,
	Andrii Nakryiko <andrii@kernel.org>,
	Eduard Zingerman <eddyz87@gmail.com>, Song Liu <song@kernel.org>,
	Yonghong Song <yonghong.song@linux.dev>,
	KP Singh <kpsingh@kernel.org>, Hao Luo <haoluo@google.com>,
	Jiri Olsa <jolsa@kernel.org>,
	"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>, Shuah Khan <shuah@kernel.org>,
	Kuniyuki Iwashima <kuniyu@google.com>,
	bpf@vger.kernel.org, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org
Subject: Re: [PATCH bpf v3 2/2] selftests/bpf: Add protocol check test for bpf_sk_assign_tcp_reqsk()
Date: Sat, 28 Mar 2026 18:58:01 +0800	[thread overview]
Message-ID: <f33c5124-3865-455e-a048-73d87d020bec@linux.dev> (raw)
In-Reply-To: <8d619537-cb9a-4fdb-a440-20b59b7f5088@linux.dev>


On 3/28/26 3:53 AM, Martin KaFai Lau wrote:
>> From: Jiayuan Chen <jiayuan.chen@shopee.com>
>>
>> Add test_tcp_custom_syncookie_protocol_check to verify that
>> bpf_sk_assign_tcp_reqsk() rejects non-TCP skbs. The test sends a UDP
>> packet through TC ingress where a BPF program calls
>> bpf_sk_assign_tcp_reqsk() on it and checks that the kfunc returns an
>> error. A UDP server recv() is used as synchronization to ensure the
>> BPF program has finished processing before checking the result.
>>
>> Without the fix in bpf_sk_assign_tcp_reqsk(), the kfunc succeeds and
>> attaches a TCP reqsk to the UDP skb, which causes a null pointer
>> dereference panic when the kernel processes it through the UDP receive
>> path.
>>
>> Test result:
>>
>>    ./test_progs -a tcp_custom_syncookie_protocol_check -v
>>    setup_netns:PASS:create netns 0 nsec
>>    setup_netns:PASS:ip 0 nsec
>>    write_sysctl:PASS:open sysctl 0 nsec
>>    write_sysctl:PASS:write sysctl 0 nsec
>>    setup_netns:PASS:write_sysctl 0 nsec
>>    test_tcp_custom_syncookie_protocol_check:PASS:open_and_load 0 nsec
>>    setup_tc:PASS:qdisc add dev lo clsact 0 nsec
>>    setup_tc:PASS:filter add dev lo ingress 0 nsec
>>    run_protocol_check:PASS:start tcp_server 0 nsec
>>    run_protocol_check:PASS:start udp_server 0 nsec
>>    run_protocol_check:PASS:connect udp_client 0 nsec
>>    run_protocol_check:PASS:send udp 0 nsec
>>    run_protocol_check:PASS:recv udp 0 nsec
>>    run_protocol_check:PASS:udp_intercepted 0 nsec
>>    run_protocol_check:PASS:assign_ret 0 nsec
>>    #471/1   tcp_custom_syncookie_protocol_check/IPv4 TCP:OK
>>    run_protocol_check:PASS:start tcp_server 0 nsec
>>    run_protocol_check:PASS:start udp_server 0 nsec
>>    run_protocol_check:PASS:connect udp_client 0 nsec
>>    run_protocol_check:PASS:send udp 0 nsec
>>    run_protocol_check:PASS:recv udp 0 nsec
>>    run_protocol_check:PASS:udp_intercepted 0 nsec
>>    run_protocol_check:PASS:assign_ret 0 nsec
>>    #471/2   tcp_custom_syncookie_protocol_check/IPv6 TCP:OK
>>    #471     tcp_custom_syncookie_protocol_check:OK
>>    Summary: 1/2 PASSED, 0 SKIPPED, 0 FAILED
>>
>> Cc: Jiayuan Chen <jiayuan.chen@linux.dev>
>> Signed-off-by: Jiayuan Chen <jiayuan.chen@shopee.com>
>> ---
>>   .../bpf/prog_tests/tcp_custom_syncookie.c     |  94 ++++++++++++++-
>>   .../bpf/progs/test_tcp_custom_syncookie.c     | 109 ++++++++++++++++++
>>   2 files changed, 199 insertions(+), 4 deletions(-)
>>
>> diff --git 
>> a/tools/testing/selftests/bpf/prog_tests/tcp_custom_syncookie.c 
>> b/tools/testing/selftests/bpf/prog_tests/tcp_custom_syncookie.c
>> index eaf441dc7e79..e46031d0786b 100644
>> --- a/tools/testing/selftests/bpf/prog_tests/tcp_custom_syncookie.c
>> +++ b/tools/testing/selftests/bpf/prog_tests/tcp_custom_syncookie.c
>> @@ -5,6 +5,7 @@
>>   #include <sched.h>
>>   #include <stdlib.h>
>>   #include <net/if.h>
>> +#include <netinet/in.h>
>>     #include "test_progs.h"
>>   #include "cgroup_helpers.h"
>> @@ -47,11 +48,10 @@ static int setup_netns(void)
>>       return -1;
>>   }
>>   -static int setup_tc(struct test_tcp_custom_syncookie *skel)
>> +static int setup_tc(int prog_fd)
>>   {
>>       LIBBPF_OPTS(bpf_tc_hook, qdisc_lo, .attach_point = 
>> BPF_TC_INGRESS);
>> -    LIBBPF_OPTS(bpf_tc_opts, tc_attach,
>> -            .prog_fd = 
>> bpf_program__fd(skel->progs.tcp_custom_syncookie));
>> +    LIBBPF_OPTS(bpf_tc_opts, tc_attach, .prog_fd = prog_fd);
>>         qdisc_lo.ifindex = if_nametoindex("lo");
>>       if (!ASSERT_OK(bpf_tc_hook_create(&qdisc_lo), "qdisc add dev lo 
>> clsact"))
>> @@ -127,7 +127,7 @@ void test_tcp_custom_syncookie(void)
>>       if (!ASSERT_OK_PTR(skel, "open_and_load"))
>>           return;
>>   -    if (setup_tc(skel))
>> +    if (setup_tc(bpf_program__fd(skel->progs.tcp_custom_syncookie)))
>>           goto destroy_skel;
>>         for (i = 0; i < ARRAY_SIZE(test_cases); i++) {
>> @@ -145,6 +145,92 @@ void test_tcp_custom_syncookie(void)
>>     destroy_skel:
>>       system("tc qdisc del dev lo clsact");
>> +    test_tcp_custom_syncookie__destroy(skel);
>> +}
>> +
>> +/* Test: bpf_sk_assign_tcp_reqsk() should reject non-TCP skb.
>> + *
>> + * Send a UDP packet through TC ingress where a BPF program calls
>> + * bpf_sk_assign_tcp_reqsk() on it. The kfunc should return an error
>> + * because the skb carries UDP, not TCP.
>> + *
>> + * TCP and UDP servers share the same port. The BPF program intercepts
>> + * the UDP packet, looks up the TCP listener via the dest port, and
>> + * attempts to assign a TCP reqsk to the UDP skb.
>> + */
>> +static void run_protocol_check(struct test_tcp_custom_syncookie *skel,
>> +                   int family, const char *addr)
>> +{
>> +    int tcp_server = -1, udp_server = -1, udp_client = -1;
>> +    char buf[32] = "test";
>> +    int port, ret;
>> +
>> +    tcp_server = start_server(family, SOCK_STREAM, addr, 0, 0);
>> +    if (!ASSERT_NEQ(tcp_server, -1, "start tcp_server"))
>> +        return;
>> +
>> +    port = ntohs(get_socket_local_port(tcp_server));
>> +
>> +    /* UDP server on same port for synchronization and port sharing */
>> +    udp_server = start_server(family, SOCK_DGRAM, addr, port, 0);
>> +    if (!ASSERT_NEQ(udp_server, -1, "start udp_server"))
>> +        goto close_tcp;
>> +
>> +    skel->bss->udp_intercepted = false;
>> +    skel->data->assign_ret = -1;
>
> assign_ret is init to -1
>
>> +
>> +    udp_client = connect_to_fd(udp_server, 0);
>> +    if (!ASSERT_NEQ(udp_client, -1, "connect udp_client"))
>> +        goto close_udp_server;
>>   +    ret = send(udp_client, buf, sizeof(buf), 0);
>> +    if (!ASSERT_EQ(ret, sizeof(buf), "send udp"))
>> +        goto close_udp_client;
>> +
>> +    /* recv() ensures TC ingress BPF has processed the skb */
>> +    ret = recv(udp_server, buf, sizeof(buf), 0);
>> +    if (!ASSERT_EQ(ret, sizeof(buf), "recv udp"))
>> +        goto close_udp_client;
>> +
>> +    ASSERT_EQ(skel->bss->udp_intercepted, true, "udp_intercepted");
>> +
>> +    /* assign_ret == 0 means kfunc accepted UDP skb (bug).
>> +     * assign_ret < 0 means kfunc correctly rejected it (fixed).
>> +     */
>> +    ASSERT_NEQ(skel->data->assign_ret, 0, "assign_ret");
>
> and here it checks NEQ 0....
>
> Maybe init assign_ret to 0?
>
> Also, why not specifically check for -EINVAL?


You're right, checking for -EINVAL is more precise and avoids hiding a 
silent failure in the lookup path.

Will init assign_ret to 0 and check for -EINVAL instead.


      reply	other threads:[~2026-03-28 10:58 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-27 13:38 [PATCH bpf v3 0/2] bpf: tcp: Fix null-ptr-deref in arbitrary SYN Cookie Jiayuan Chen
2026-03-27 13:38 ` [PATCH bpf v3 1/2] bpf: tcp: Reject non-TCP skb in bpf_sk_assign_tcp_reqsk() Jiayuan Chen
2026-03-27 13:38 ` [PATCH bpf v3 2/2] selftests/bpf: Add protocol check test for bpf_sk_assign_tcp_reqsk() Jiayuan Chen
2026-03-27 19:53   ` Martin KaFai Lau
2026-03-28 10:58     ` Jiayuan Chen [this message]

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=f33c5124-3865-455e-a048-73d87d020bec@linux.dev \
    --to=jiayuan.chen@linux.dev \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=davem@davemloft.net \
    --cc=eddyz87@gmail.com \
    --cc=edumazet@google.com \
    --cc=haoluo@google.com \
    --cc=horms@kernel.org \
    --cc=jiayuan.chen@shopee.com \
    --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=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=sdf@fomichev.me \
    --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.