[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <b57e110f8aea2321436cdcb97a851ccc73028755f93152591bf3979e22dbe81e@mail.kernel.org>
Date: Thu, 8 Jan 2026 23:21:48 +0000 (UTC)
From: bot+bpf-ci@...nel.org
To: wusamuel@...gle.com,ast@...nel.org,daniel@...earbox.net,andrii@...nel.org,martin.lau@...ux.dev,eddyz87@...il.com,song@...nel.org,yonghong.song@...ux.dev,john.fastabend@...il.com,kpsingh@...nel.org,sdf@...ichev.me,haoluo@...gle.com,jolsa@...nel.org,shuah@...nel.org
Cc: wusamuel@...gle.com,kernel-team@...roid.com,linux-kernel@...r.kernel.org,bpf@...r.kernel.org,linux-kselftest@...r.kernel.org,ast@...nel.org,andrii@...nel.org,daniel@...earbox.net,martin.lau@...nel.org,eddyz87@...il.com,yonghong.song@...ux.dev,clm@...a.com,ihor.solodrai@...ux.dev
Subject: Re: [PATCH bpf-next v2 1/4] bpf: Add wakeup_source iterator
> diff --git a/kernel/bpf/wakeup_source_iter.c b/kernel/bpf/wakeup_source_iter.c
> new file mode 100644
> index 000000000000..ab83d212a1f9
> --- /dev/null
> +++ b/kernel/bpf/wakeup_source_iter.c
[ ... ]
> +static void *wakeup_source_iter_seq_start(struct seq_file *seq, loff_t *pos)
> +{
> + int *srcuidx = seq->private;
> + struct wakeup_source *ws;
> + loff_t i;
> +
> + *srcuidx = wakeup_sources_read_lock();
> +
> + ws = wakeup_sources_walk_start();
> + for (i = 0; ws && i < *pos; i++)
> + ws = wakeup_sources_walk_next(ws);
> +
> + return ws;
> +}
What happens when the wakeup_sources list is empty?
wakeup_sources_walk_start() uses list_entry_rcu(ws_head->next, ...) which
does not check for an empty list. When the list is empty, ws_head->next
points back to ws_head itself, so list_entry_rcu() computes a pointer to
memory before the static list head, resulting in an invalid pointer.
The loop condition (ws && i < *pos) does not execute when *pos is 0,
so this invalid pointer is returned directly. Unlike the existing debugfs
implementation wakeup_sources_stats_seq_start() which uses
list_for_each_entry_rcu_locked() and properly returns NULL for an empty
list, this function returns a non-NULL invalid pointer.
The BPF iterator framework in bpf_seq_read() checks if (!p) goto stop,
but since the invalid pointer is non-NULL, this check passes and the
show callback is invoked with the invalid pointer. Could this pass
garbage memory to the BPF program?
The for_each_wakeup_source() macro might mask this issue because
wakeup_sources_walk_next() on this invalid pointer will return NULL,
but the seq_file framework calls show() before next(), so the first
invocation receives the invalid pointer.
---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
CI run summary: https://github.com/kernel-patches/bpf/actions/runs/20835022582
Powered by blists - more mailing lists