]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
selftests: bpf: Fix test_bpf_nf for trusted args becoming default
authorPuranjay Mohan <puranjay@kernel.org>
Fri, 2 Jan 2026 18:00:36 +0000 (10:00 -0800)
committerAlexei Starovoitov <ast@kernel.org>
Fri, 2 Jan 2026 20:04:29 +0000 (12:04 -0800)
With trusted args now being the default, passing NULL to kfunc
parameters that are pointers causes verifier rejection rather than a
runtime error. The test_bpf_nf test was failing because it attempted to
pass NULL to bpf_xdp_ct_lookup() to verify runtime error handling.

Since the NULL check now happens at verification time, remove the
runtime test case that passed NULL to the bpf_tuple parameter and
instead add verification-time tests to ensure the verifier correctly
rejects programs that pass NULL to trusted arguments.

Signed-off-by: Puranjay Mohan <puranjay@kernel.org>
Link: https://lore.kernel.org/r/20260102180038.2708325-11-puranjay@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
tools/testing/selftests/bpf/prog_tests/bpf_nf.c
tools/testing/selftests/bpf/progs/test_bpf_nf.c
tools/testing/selftests/bpf/progs/test_bpf_nf_fail.c

index dd6512fa652be08e10526193933b52b183bd76af..215878ea04deec17d3ac0214f853a9971cb54f30 100644 (file)
@@ -19,6 +19,10 @@ struct {
        { "change_timeout_after_alloc", "kernel function bpf_ct_change_timeout args#0 expected pointer to STRUCT nf_conn but" },
        { "change_status_after_alloc", "kernel function bpf_ct_change_status args#0 expected pointer to STRUCT nf_conn but" },
        { "write_not_allowlisted_field", "no write support to nf_conn at off" },
+       { "lookup_null_bpf_tuple", "Possibly NULL pointer passed to trusted arg1" },
+       { "lookup_null_bpf_opts", "Possibly NULL pointer passed to trusted arg3" },
+       { "xdp_lookup_null_bpf_tuple", "Possibly NULL pointer passed to trusted arg1" },
+       { "xdp_lookup_null_bpf_opts", "Possibly NULL pointer passed to trusted arg3" },
 };
 
 enum {
@@ -111,7 +115,6 @@ static void test_bpf_nf_ct(int mode)
        if (!ASSERT_OK(err, "bpf_prog_test_run"))
                goto end;
 
-       ASSERT_EQ(skel->bss->test_einval_bpf_tuple, -EINVAL, "Test EINVAL for NULL bpf_tuple");
        ASSERT_EQ(skel->bss->test_einval_reserved, -EINVAL, "Test EINVAL for reserved not set to 0");
        ASSERT_EQ(skel->bss->test_einval_reserved_new, -EINVAL, "Test EINVAL for reserved in new struct not set to 0");
        ASSERT_EQ(skel->bss->test_einval_netns_id, -EINVAL, "Test EINVAL for netns_id < -1");
index f7b330ddd007e8b14fe5cca353e13ce5c6daf663..076fbf03a1268f6f8b75307c714613e445db9d84 100644 (file)
@@ -15,7 +15,6 @@
 
 extern unsigned long CONFIG_HZ __kconfig;
 
-int test_einval_bpf_tuple = 0;
 int test_einval_reserved = 0;
 int test_einval_reserved_new = 0;
 int test_einval_netns_id = 0;
@@ -99,12 +98,6 @@ nf_ct_test(struct nf_conn *(*lookup_fn)(void *, struct bpf_sock_tuple *, u32,
 
        __builtin_memset(&bpf_tuple, 0, sizeof(bpf_tuple.ipv4));
 
-       ct = lookup_fn(ctx, NULL, 0, &opts_def, sizeof(opts_def));
-       if (ct)
-               bpf_ct_release(ct);
-       else
-               test_einval_bpf_tuple = opts_def.error;
-
        opts_def.reserved[0] = 1;
        ct = lookup_fn(ctx, &bpf_tuple, sizeof(bpf_tuple.ipv4), &opts_def,
                       sizeof(opts_def));
index a586f087ffeb476b9f421b3843cb264bddad8fa3..2c156cd166afe7a6ea02e0fc0ad5c148b1f1bb0e 100644 (file)
@@ -4,6 +4,7 @@
 #include <bpf/bpf_tracing.h>
 #include <bpf/bpf_helpers.h>
 #include <bpf/bpf_core_read.h>
+#include "bpf_misc.h"
 
 struct nf_conn;
 
@@ -18,6 +19,10 @@ struct nf_conn *bpf_skb_ct_alloc(struct __sk_buff *, struct bpf_sock_tuple *, u3
                                 struct bpf_ct_opts___local *, u32) __ksym;
 struct nf_conn *bpf_skb_ct_lookup(struct __sk_buff *, struct bpf_sock_tuple *, u32,
                                  struct bpf_ct_opts___local *, u32) __ksym;
+struct nf_conn *bpf_xdp_ct_alloc(struct xdp_md *, struct bpf_sock_tuple *, u32,
+                                struct bpf_ct_opts___local *, u32) __ksym;
+struct nf_conn *bpf_xdp_ct_lookup(struct xdp_md *, struct bpf_sock_tuple *, u32,
+                                 struct bpf_ct_opts___local *, u32) __ksym;
 struct nf_conn *bpf_ct_insert_entry(struct nf_conn *) __ksym;
 void bpf_ct_release(struct nf_conn *) __ksym;
 void bpf_ct_set_timeout(struct nf_conn *, u32) __ksym;
@@ -146,4 +151,56 @@ int change_status_after_alloc(struct __sk_buff *ctx)
        return 0;
 }
 
+SEC("?tc")
+__failure __msg("Possibly NULL pointer passed to trusted arg1")
+int lookup_null_bpf_tuple(struct __sk_buff *ctx)
+{
+       struct bpf_ct_opts___local opts = {};
+       struct nf_conn *ct;
+
+       ct = bpf_skb_ct_lookup(ctx, NULL, 0, &opts, sizeof(opts));
+       if (ct)
+               bpf_ct_release(ct);
+       return 0;
+}
+
+SEC("?tc")
+__failure __msg("Possibly NULL pointer passed to trusted arg3")
+int lookup_null_bpf_opts(struct __sk_buff *ctx)
+{
+       struct bpf_sock_tuple tup = {};
+       struct nf_conn *ct;
+
+       ct = bpf_skb_ct_lookup(ctx, &tup, sizeof(tup.ipv4), NULL, sizeof(struct bpf_ct_opts___local));
+       if (ct)
+               bpf_ct_release(ct);
+       return 0;
+}
+
+SEC("?xdp")
+__failure __msg("Possibly NULL pointer passed to trusted arg1")
+int xdp_lookup_null_bpf_tuple(struct xdp_md *ctx)
+{
+       struct bpf_ct_opts___local opts = {};
+       struct nf_conn *ct;
+
+       ct = bpf_xdp_ct_lookup(ctx, NULL, 0, &opts, sizeof(opts));
+       if (ct)
+               bpf_ct_release(ct);
+       return 0;
+}
+
+SEC("?xdp")
+__failure __msg("Possibly NULL pointer passed to trusted arg3")
+int xdp_lookup_null_bpf_opts(struct xdp_md *ctx)
+{
+       struct bpf_sock_tuple tup = {};
+       struct nf_conn *ct;
+
+       ct = bpf_xdp_ct_lookup(ctx, &tup, sizeof(tup.ipv4), NULL, sizeof(struct bpf_ct_opts___local));
+       if (ct)
+               bpf_ct_release(ct);
+       return 0;
+}
+
 char _license[] SEC("license") = "GPL";