diff --git a/kernel/bpf/wakeup_source_iter.c b/kernel/bpf/wakeup_source_iter.c index ab83d212a1f9..149baecfe436 100644 --- a/kernel/bpf/wakeup_source_iter.c +++ b/kernel/bpf/wakeup_source_iter.c
[ ... ]
+__bpf_kfunc int bpf_iter_wakeup_source_new(struct bpf_iter_wakeup_source *it) +{
- it->srcuidx = wakeup_sources_read_lock();
- it->ws = wakeup_sources_walk_start();
- return 0;
+}
+__bpf_kfunc struct wakeup_source *bpf_iter_wakeup_source_next(struct bpf_iter_wakeup_source *it) +{
- struct wakeup_source *prev = it->ws;
- if (!prev)
return NULL;- it->ws = wakeup_sources_walk_next(it->ws);
- return prev;
+}
When the wakeup_sources list is empty, wakeup_sources_walk_start() returns a bogus pointer via list_entry_rcu()/container_of() on the list head itself, rather than NULL. The check "if (!prev)" at line 112 will not catch this bogus pointer since it is non-NULL.
Does this return a bogus pointer to the BPF program when the wakeup_sources list is empty? If so, the BPF program could then access invalid memory when it tries to read fields of the returned wakeup_source.
For reference, wakeup_sources_walk_start() in drivers/base/power/wakeup.c:
struct wakeup_source *wakeup_sources_walk_start(void) { struct list_head *ws_head = &wakeup_sources; return list_entry_rcu(ws_head->next, struct wakeup_source, entry); }
When wakeup_sources is empty, ws_head->next == ws_head, so this returns container_of(ws_head, struct wakeup_source, entry) which points to memory before the wakeup_sources variable rather than a valid wakeup_source struct.
Other BPF open-coded iterators like bpf_iter_dmabuf handle this differently by initializing to NULL and getting the first element lazily in _next(). Would a similar approach work here?
--- 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