All of lore.kernel.org
 help / color / mirror / Atom feed
From: Leon Hwang <leon.hwang@linux.dev>
To: Yonghong Song <yonghong.song@linux.dev>, bpf@vger.kernel.org
Cc: ast@kernel.org, andrii@kernel.org, daniel@iogearbox.net,
	martin.lau@linux.dev, eddyz87@gmail.com, song@kernel.org,
	john.fastabend@gmail.com, kpsingh@kernel.org, sdf@fomichev.me,
	haoluo@google.com, jolsa@kernel.org, memxor@gmail.com,
	ameryhung@gmail.com, linux-kernel@vger.kernel.org,
	kernel-patches-bot@fb.com
Subject: Re: [PATCH bpf-next v6 2/2] selftests/bpf: Add test to verify freeing the special fields when update [lru_,]percpu_hash maps
Date: Tue, 11 Nov 2025 21:38:12 +0800	[thread overview]
Message-ID: <04c35045-ef5b-4e92-9da9-6710ce8fdabf@linux.dev> (raw)
In-Reply-To: <9f662e2c-7370-4f99-bdec-bc123495e1c5@linux.dev>



On 2025/11/7 10:00, Yonghong Song wrote:
>
>
> On 11/5/25 7:14 AM, Leon Hwang wrote:
>> Add test to verify that updating [lru_,]percpu_hash maps decrements
>> refcount when BPF_KPTR_REF objects are involved.
>>
>> The tests perform the following steps:
>>
>> 1. Call update_elem() to insert an initial value.
>> 2. Use bpf_refcount_acquire() to increment the refcount.
>> 3. Store the node pointer in the map value.
>> 4. Add the node to a linked list.
>> 5. Probe-read the refcount and verify it is *2*.
>> 6. Call update_elem() again to trigger refcount decrement.
>> 7. Probe-read the refcount and verify it is *1*.
>>
>> Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
>
> LGTM with a few nits below.
>
> Acked-by: Yonghong Song <yonghong.song@linux.dev>
>

Hi Yonghong,

Thanks for your review and ack.

>> ---
>>   .../bpf/prog_tests/refcounted_kptr.c          | 57 ++++++++++++++++++
>>   .../selftests/bpf/progs/refcounted_kptr.c     | 60 +++++++++++++++++++
>>   2 files changed, 117 insertions(+)
>>
>> diff --git a/tools/testing/selftests/bpf/prog_tests/refcounted_kptr.c
>> b/tools/testing/selftests/bpf/prog_tests/refcounted_kptr.c
>> index d6bd5e16e6372..086f679fa3f61 100644
>> --- a/tools/testing/selftests/bpf/prog_tests/refcounted_kptr.c
>> +++ b/tools/testing/selftests/bpf/prog_tests/refcounted_kptr.c
>> @@ -44,3 +44,60 @@ void test_refcounted_kptr_wrong_owner(void)
>>       ASSERT_OK(opts.retval, "rbtree_wrong_owner_remove_fail_a2 retval");
>>       refcounted_kptr__destroy(skel);
>>   }
>> +
>> +void test_percpu_hash_refcounted_kptr_refcount_leak(void)
>> +{
>> +    struct refcounted_kptr *skel;
>> +    int cpu_nr, fd, err, key = 0;
>> +    struct bpf_map *map;
>> +    size_t values_sz;
>> +    u64 *values;
>> +    LIBBPF_OPTS(bpf_test_run_opts, opts,
>> +            .data_in = &pkt_v4,
>> +            .data_size_in = sizeof(pkt_v4),
>> +            .repeat = 1,
>> +    );
>> +
>> +    cpu_nr = libbpf_num_possible_cpus();
>> +    if (!ASSERT_GT(cpu_nr, 0, "libbpf_num_possible_cpus"))
>> +        return;
>> +
>> +    values = calloc(cpu_nr, sizeof(u64));
>> +    if (!ASSERT_OK_PTR(values, "calloc values"))
>> +        return;
>> +
>> +    skel = refcounted_kptr__open_and_load();
>> +    if (!ASSERT_OK_PTR(skel, "refcounted_kptr__open_and_load")) {
>> +        free(values);
>> +        return;
>> +    }
>> +
>> +    values_sz = cpu_nr * sizeof(u64);
>> +    memset(values, 0, values_sz);
>> +
>> +    map = skel->maps.percpu_hash;
>> +    err = bpf_map__update_elem(map, &key, sizeof(key), values,
>> values_sz, 0);
>> +    if (!ASSERT_OK(err, "bpf_map__update_elem"))
>> +        goto out;
>> +
>> +    fd = bpf_program__fd(skel->progs.percpu_hash_refcount_leak);
>> +    err = bpf_prog_test_run_opts(fd, &opts);
>> +    if (!ASSERT_OK(err, "bpf_prog_test_run_opts"))
>> +        goto out;
>> +    if (!ASSERT_EQ(opts.retval, 2, "opts.retval"))
>> +        goto out;
>> +
>> +    err = bpf_map__update_elem(map, &key, sizeof(key), values,
>> values_sz, 0);
>> +    if (!ASSERT_OK(err, "bpf_map__update_elem"))
>> +        goto out;
>> +
>> +    fd = bpf_program__fd(skel->progs.check_percpu_hash_refcount);
>> +    err = bpf_prog_test_run_opts(fd, &opts);
>> +    ASSERT_OK(err, "bpf_prog_test_run_opts");
>> +    ASSERT_EQ(opts.retval, 1, "opts.retval");
>> +
>> +out:
>> +    refcounted_kptr__destroy(skel);
>> +    free(values);
>> +}
>> +
>
> Empty line here.
>
>> diff --git a/tools/testing/selftests/bpf/progs/refcounted_kptr.c b/
>> tools/testing/selftests/bpf/progs/refcounted_kptr.c
>> index 893a4fdb4b6e9..1aca85d86aebc 100644
>> --- a/tools/testing/selftests/bpf/progs/refcounted_kptr.c
>> +++ b/tools/testing/selftests/bpf/progs/refcounted_kptr.c
>> @@ -568,4 +568,64 @@ int
>> BPF_PROG(rbtree_sleepable_rcu_no_explicit_rcu_lock,
>>       return 0;
>>   }
>>   +private(kptr_ref) u64 ref;
>> +
>> +static int probe_read_refcount(void)
>> +{
>> +    u32 refcount;
>> +
>> +    bpf_probe_read_kernel(&refcount, sizeof(refcount), (void *) ref);
>> +    return refcount;
>> +}
>> +
>> +static int __insert_in_list(struct bpf_list_head *head, struct
>> bpf_spin_lock *lock,
>> +                struct node_data __kptr **node)
>> +{
>> +    struct node_data *node_new, *node_ref, *node_old;
>> +
>> +    node_new = bpf_obj_new(typeof(*node_new));
>> +    if (!node_new)
>> +        return -1;
>> +
>> +    node_ref = bpf_refcount_acquire(node_new);
>> +    node_old = bpf_kptr_xchg(node, node_new);
>
> Change the above to node_old = bpf_kptr_xchg(node, node_node_ref); might
> be better for reasoning although node_ref/node_new are the same.
>

Nope — node_ref and node_new are different for the verifier.

When trying node_old = bpf_kptr_xchg(node, node_ref), the verifier reported:

[verifier log snipped for brevity...]
; bpf_obj_drop(node_ref); @ refcounted_kptr.c:594
26: (bf) r1 = r6                      ; R1=scalar(id=7) R6=scalar(id=7)
refs=3
27: (b7) r2 = 0                       ; R2=0 refs=3
28: (85) call bpf_obj_drop_impl#54490
R1 must be referenced or trusted
processed 27 insns (limit 1000000) max_states_per_insn 0 total_states 2
peak_states 2 mark_read 0

So the verifier rejected it because R6 became scalar(id=7) from
ptr_node_data(ref_obj_id=4).

---

Hi Alexei, could you please drop the extra empty line when applying this
patch?

Then I don't need to send another revision.

Thanks,
Leon

[...]

  reply	other threads:[~2025-11-11 13:38 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-11-05 15:14 [PATCH bpf-next v6 0/2] bpf: Free special fields when update [lru_,]percpu_hash maps Leon Hwang
2025-11-05 15:14 ` [PATCH bpf-next v6 1/2] " Leon Hwang
2025-11-07  1:56   ` Yonghong Song
2025-11-05 15:14 ` [PATCH bpf-next v6 2/2] selftests/bpf: Add test to verify freeing the " Leon Hwang
2025-11-07  2:00   ` Yonghong Song
2025-11-11 13:38     ` Leon Hwang [this message]
2025-11-11 13:52       ` Leon Hwang
2025-11-11 21:58         ` Yonghong Song
2025-11-13 13:16           ` Leon Hwang
2025-11-13 17:30 ` [PATCH bpf-next v6 0/2] bpf: Free " patchwork-bot+netdevbpf

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=04c35045-ef5b-4e92-9da9-6710ce8fdabf@linux.dev \
    --to=leon.hwang@linux.dev \
    --cc=ameryhung@gmail.com \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=eddyz87@gmail.com \
    --cc=haoluo@google.com \
    --cc=john.fastabend@gmail.com \
    --cc=jolsa@kernel.org \
    --cc=kernel-patches-bot@fb.com \
    --cc=kpsingh@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=martin.lau@linux.dev \
    --cc=memxor@gmail.com \
    --cc=sdf@fomichev.me \
    --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.