Add coverage for nullable BTF pointers that are read under bpf_rcu_read_lock() and then used after bpf_rcu_read_unlock().
The unchecked skb->sk dereference should be rejected because the pointer can still be NULL after it loses MEM_RCU trust. The matched control performs an explicit NULL check after unlock and should keep loading successfully. Signed-off-by: Yiyang Chen <[email protected]> --- .../selftests/bpf/prog_tests/rcu_read_lock.c | 17 ++++++++++++++++ .../selftests/bpf/progs/rcu_read_lock.c | 20 +++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/tools/testing/selftests/bpf/prog_tests/rcu_read_lock.c b/tools/testing/selftests/bpf/prog_tests/rcu_read_lock.c index 246eb259c..be0317a47 100644 --- a/tools/testing/selftests/bpf/prog_tests/rcu_read_lock.c +++ b/tools/testing/selftests/bpf/prog_tests/rcu_read_lock.c @@ -72,6 +72,20 @@ static void test_rcuptr_acquire(void) rcu_read_lock__destroy(skel); } +static void test_rcuptr_null_check(void) +{ + struct rcu_read_lock *skel; + + skel = rcu_read_lock__open(); + if (!ASSERT_OK_PTR(skel, "skel_open")) + return; + + bpf_program__set_autoload(skel->progs.rcu_null_check_after_unlock, true); + ASSERT_OK(rcu_read_lock__load(skel), "skel_load"); + + rcu_read_lock__destroy(skel); +} + static const char * const inproper_region_tests[] = { "miss_lock", "no_lock", @@ -113,6 +127,7 @@ static void test_inproper_region(void) static const char * const rcuptr_misuse_tests[] = { "task_untrusted_rcuptr", "cross_rcu_region", + "rcu_null_deref_after_unlock", }; static void test_rcuptr_misuse(void) @@ -150,6 +165,8 @@ void test_rcu_read_lock(void) test_success(); if (test__start_subtest("rcuptr_acquire")) test_rcuptr_acquire(); + if (test__start_subtest("rcuptr_null_check")) + test_rcuptr_null_check(); if (test__start_subtest("negative_tests_inproper_region")) test_inproper_region(); if (test__start_subtest("negative_tests_rcuptr_misuse")) diff --git a/tools/testing/selftests/bpf/progs/rcu_read_lock.c b/tools/testing/selftests/bpf/progs/rcu_read_lock.c index b4e073168..b78542706 100644 --- a/tools/testing/selftests/bpf/progs/rcu_read_lock.c +++ b/tools/testing/selftests/bpf/progs/rcu_read_lock.c @@ -372,6 +372,26 @@ int cross_rcu_region(void *ctx) return 0; } +SEC("?tp_btf/net_dev_queue") +int BPF_PROG(rcu_null_check_after_unlock, struct sk_buff *skb) +{ + bpf_rcu_read_lock(); + bpf_rcu_read_unlock(); + + if (!skb->sk) + return 0; + return skb->sk->__sk_common.skc_daddr; +} + +SEC("?tp_btf/net_dev_queue") +int BPF_PROG(rcu_null_deref_after_unlock, struct sk_buff *skb) +{ + bpf_rcu_read_lock(); + bpf_rcu_read_unlock(); + + return skb->sk->__sk_common.skc_daddr; +} + __noinline static int static_subprog(void *ctx) { -- 2.34.1

