* [PATCH bpf] bpf: fix end-of-list detection in cgroup_storage_get_next_key()
@ 2026-04-01 19:26 Weiming Shi
2026-04-02 0:56 ` sun jian
0 siblings, 1 reply; 4+ messages in thread
From: Weiming Shi @ 2026-04-01 19:26 UTC (permalink / raw)
To: Martin KaFai Lau, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko
Cc: Eduard Zingerman, Song Liu, Yonghong Song, John Fastabend,
KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa, bpf, Xiang Mei,
Weiming Shi
list_next_entry() never returns NULL -- when the current element is the
last entry it wraps to the list head via container_of(). The subsequent
NULL check is therefore dead code and get_next_key() never returns
-ENOENT for the last element, instead reading storage->key from a bogus
pointer that aliases internal map fields and copying the result to
userspace.
Replace it with list_entry_is_head() so the function correctly returns
-ENOENT when there are no more entries.
Fixes: de9cbbaadba5 ("bpf: introduce cgroup storage maps")
Reported-by: Xiang Mei <xmei5@asu.edu>
Signed-off-by: Weiming Shi <bestswngs@gmail.com>
---
kernel/bpf/local_storage.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kernel/bpf/local_storage.c b/kernel/bpf/local_storage.c
index 8fca0c64f7b1..23267213a17f 100644
--- a/kernel/bpf/local_storage.c
+++ b/kernel/bpf/local_storage.c
@@ -270,7 +270,7 @@ static int cgroup_storage_get_next_key(struct bpf_map *_map, void *key,
goto enoent;
storage = list_next_entry(storage, list_map);
- if (!storage)
+ if (list_entry_is_head(storage, &map->list, list_map))
goto enoent;
} else {
storage = list_first_entry(&map->list,
--
2.43.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH bpf] bpf: fix end-of-list detection in cgroup_storage_get_next_key()
2026-04-01 19:26 [PATCH bpf] bpf: fix end-of-list detection in cgroup_storage_get_next_key() Weiming Shi
@ 2026-04-02 0:56 ` sun jian
2026-04-03 13:05 ` Paul Chaignon
0 siblings, 1 reply; 4+ messages in thread
From: sun jian @ 2026-04-02 0:56 UTC (permalink / raw)
To: Weiming Shi
Cc: Martin KaFai Lau, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Eduard Zingerman, Song Liu, Yonghong Song,
John Fastabend, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa,
bpf, Xiang Mei
On Thu, Apr 2, 2026 at 3:31 AM Weiming Shi <bestswngs@gmail.com> wrote:
>
> list_next_entry() never returns NULL -- when the current element is the
> last entry it wraps to the list head via container_of(). The subsequent
> NULL check is therefore dead code and get_next_key() never returns
> -ENOENT for the last element, instead reading storage->key from a bogus
> pointer that aliases internal map fields and copying the result to
> userspace.
>
> Replace it with list_entry_is_head() so the function correctly returns
> -ENOENT when there are no more entries.
>
> Fixes: de9cbbaadba5 ("bpf: introduce cgroup storage maps")
> Reported-by: Xiang Mei <xmei5@asu.edu>
> Signed-off-by: Weiming Shi <bestswngs@gmail.com>
> ---
> kernel/bpf/local_storage.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/kernel/bpf/local_storage.c b/kernel/bpf/local_storage.c
> index 8fca0c64f7b1..23267213a17f 100644
> --- a/kernel/bpf/local_storage.c
> +++ b/kernel/bpf/local_storage.c
> @@ -270,7 +270,7 @@ static int cgroup_storage_get_next_key(struct bpf_map *_map, void *key,
> goto enoent;
>
> storage = list_next_entry(storage, list_map);
> - if (!storage)
> + if (list_entry_is_head(storage, &map->list, list_map))
> goto enoent;
> } else {
> storage = list_first_entry(&map->list,
> --
> 2.43.0
>
>
Looks correct to me. It might also be worth adding a selftest for this
cornet case.
Reviewed by Sun Jian <sun.jian.kdev@gmail.com>
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH bpf] bpf: fix end-of-list detection in cgroup_storage_get_next_key()
2026-04-02 0:56 ` sun jian
@ 2026-04-03 13:05 ` Paul Chaignon
2026-04-03 13:39 ` Weiming Shi
0 siblings, 1 reply; 4+ messages in thread
From: Paul Chaignon @ 2026-04-03 13:05 UTC (permalink / raw)
To: Weiming Shi
Cc: sun jian, Martin KaFai Lau, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Eduard Zingerman, Song Liu, Yonghong Song,
John Fastabend, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa,
bpf, Xiang Mei
On Thu, Apr 02, 2026 at 08:56:06AM +0800, sun jian wrote:
> On Thu, Apr 2, 2026 at 3:31 AM Weiming Shi <bestswngs@gmail.com> wrote:
> >
> > list_next_entry() never returns NULL -- when the current element is the
> > last entry it wraps to the list head via container_of(). The subsequent
> > NULL check is therefore dead code and get_next_key() never returns
> > -ENOENT for the last element, instead reading storage->key from a bogus
> > pointer that aliases internal map fields and copying the result to
> > userspace.
> >
> > Replace it with list_entry_is_head() so the function correctly returns
> > -ENOENT when there are no more entries.
> >
> > Fixes: de9cbbaadba5 ("bpf: introduce cgroup storage maps")
> > Reported-by: Xiang Mei <xmei5@asu.edu>
> > Signed-off-by: Weiming Shi <bestswngs@gmail.com>
Acked-by: Paul Chaignon <paul.chaignon@gmail.com>
> > ---
> > kernel/bpf/local_storage.c | 2 +-
> > 1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/kernel/bpf/local_storage.c b/kernel/bpf/local_storage.c
> > index 8fca0c64f7b1..23267213a17f 100644
> > --- a/kernel/bpf/local_storage.c
> > +++ b/kernel/bpf/local_storage.c
> > @@ -270,7 +270,7 @@ static int cgroup_storage_get_next_key(struct bpf_map *_map, void *key,
> > goto enoent;
> >
> > storage = list_next_entry(storage, list_map);
> > - if (!storage)
> > + if (list_entry_is_head(storage, &map->list, list_map))
> > goto enoent;
> > } else {
> > storage = list_first_entry(&map->list,
> > --
> > 2.43.0
> >
> >
> Looks correct to me. It might also be worth adding a selftest for this
> cornet case.
I agree, it would be good to cover this in selftests. You can use the
following diff for that:
diff --git a/tools/testing/selftests/bpf/prog_tests/cgroup_storage.c b/tools/testing/selftests/bpf/prog_tests/cgroup_storage.c
index cf395715ced4..5451a43b3563 100644
--- a/tools/testing/selftests/bpf/prog_tests/cgroup_storage.c
+++ b/tools/testing/selftests/bpf/prog_tests/cgroup_storage.c
@@ -86,6 +86,11 @@ void test_cgroup_storage(void)
err = SYS_NOFAIL(PING_CMD);
ASSERT_OK(err, "sixth ping");
+ err = bpf_map__get_next_key(skel->maps.cgroup_storage, &key, &key,
+ sizeof(key));
+ ASSERT_ERR(err, "bpf_map__get_next_key should fail");
+ ASSERT_EQ(errno, ENOENT, "no second key");
+
cleanup_progs:
cgroup_storage__destroy(skel);
cleanup_network:
>
> Reviewed by Sun Jian <sun.jian.kdev@gmail.com>
>
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH bpf] bpf: fix end-of-list detection in cgroup_storage_get_next_key()
2026-04-03 13:05 ` Paul Chaignon
@ 2026-04-03 13:39 ` Weiming Shi
0 siblings, 0 replies; 4+ messages in thread
From: Weiming Shi @ 2026-04-03 13:39 UTC (permalink / raw)
To: Paul Chaignon, sun.jian.kdev
Cc: Martin KaFai Lau, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Eduard Zingerman, Song Liu, Yonghong Song,
John Fastabend, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa,
bpf, Xiang Mei
On 26-04-03 15:05, Paul Chaignon wrote:
> On Thu, Apr 02, 2026 at 08:56:06AM +0800, sun jian wrote:
> > On Thu, Apr 2, 2026 at 3:31 AM Weiming Shi <bestswngs@gmail.com> wrote:
> > >
> > > list_next_entry() never returns NULL -- when the current element is the
> > > last entry it wraps to the list head via container_of(). The subsequent
> > > NULL check is therefore dead code and get_next_key() never returns
> > > -ENOENT for the last element, instead reading storage->key from a bogus
> > > pointer that aliases internal map fields and copying the result to
> > > userspace.
> > >
> > > Replace it with list_entry_is_head() so the function correctly returns
> > > -ENOENT when there are no more entries.
> > >
> > > Fixes: de9cbbaadba5 ("bpf: introduce cgroup storage maps")
> > > Reported-by: Xiang Mei <xmei5@asu.edu>
> > > Signed-off-by: Weiming Shi <bestswngs@gmail.com>
>
> Acked-by: Paul Chaignon <paul.chaignon@gmail.com>
>
> > > ---
> > > kernel/bpf/local_storage.c | 2 +-
> > > 1 file changed, 1 insertion(+), 1 deletion(-)
> > >
> > > diff --git a/kernel/bpf/local_storage.c b/kernel/bpf/local_storage.c
> > > index 8fca0c64f7b1..23267213a17f 100644
> > > --- a/kernel/bpf/local_storage.c
> > > +++ b/kernel/bpf/local_storage.c
> > > @@ -270,7 +270,7 @@ static int cgroup_storage_get_next_key(struct bpf_map *_map, void *key,
> > > goto enoent;
> > >
> > > storage = list_next_entry(storage, list_map);
> > > - if (!storage)
> > > + if (list_entry_is_head(storage, &map->list, list_map))
> > > goto enoent;
> > > } else {
> > > storage = list_first_entry(&map->list,
> > > --
> > > 2.43.0
> > >
> > >
> > Looks correct to me. It might also be worth adding a selftest for this
> > cornet case.
>
> I agree, it would be good to cover this in selftests. You can use the
> following diff for that:
>
> diff --git a/tools/testing/selftests/bpf/prog_tests/cgroup_storage.c b/tools/testing/selftests/bpf/prog_tests/cgroup_storage.c
> index cf395715ced4..5451a43b3563 100644
> --- a/tools/testing/selftests/bpf/prog_tests/cgroup_storage.c
> +++ b/tools/testing/selftests/bpf/prog_tests/cgroup_storage.c
> @@ -86,6 +86,11 @@ void test_cgroup_storage(void)
> err = SYS_NOFAIL(PING_CMD);
> ASSERT_OK(err, "sixth ping");
>
> + err = bpf_map__get_next_key(skel->maps.cgroup_storage, &key, &key,
> + sizeof(key));
> + ASSERT_ERR(err, "bpf_map__get_next_key should fail");
> + ASSERT_EQ(errno, ENOENT, "no second key");
> +
> cleanup_progs:
> cgroup_storage__destroy(skel);
> cleanup_network:
>
>
> >
> > Reviewed by Sun Jian <sun.jian.kdev@gmail.com>
> >
Thanks for the your review and the selftest suggestion! I've incorporated it in v2.
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-04-03 13:39 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-01 19:26 [PATCH bpf] bpf: fix end-of-list detection in cgroup_storage_get_next_key() Weiming Shi
2026-04-02 0:56 ` sun jian
2026-04-03 13:05 ` Paul Chaignon
2026-04-03 13:39 ` Weiming Shi
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox