All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Kaitao Cheng" <kaitao.cheng@linux.dev>
Cc: dri-devel@lists.freedesktop.org
Subject: Re: [PATCH v2 14/14] list: Cache cursors in entry iterators
Date: Tue, 09 Jun 2026 06:59:51 +0000	[thread overview]
Message-ID: <20260609065951.DC20B1F00893@smtp.kernel.org> (raw)
In-Reply-To: <20260609064122.95825-2-kaitao.cheng@linux.dev>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Critical] Modifying the standard list iterators to pre-cache the `next` pointer fundamentally changes their traversal semantics from dynamic to static evaluation, causing use-after-free (UAF) vulnerabilities and silently breaking loops that modify the list ahead of the cursor or skip elements by advancing `pos`.
- [High] Eliminating the distinction between safe and non-safe list iterators obscures code intent, removes a vital visual guardrail for destructive operations, and introduces severe backporting risks.
--

commit e1c09f66ccd28cca66865681febeb6f8233f0a36
Author: Kaitao Cheng <chengkaitao@kylinos.cn>

list: Cache cursors in entry iterators

This commit introduces private next and previous cursor variables into the
standard list iteration macros. It changes the semantics of the
list_for_each_entry() family to cache the next pointer before executing the
loop body. It also updates comments to recommend the non-safe variants over
the safe ones when a temporary cursor is not needed.

> diff --git a/include/linux/list.h b/include/linux/list.h
> index 09d979976b3b8..9df84a56a789b 100644
> --- a/include/linux/list.h
> +++ b/include/linux/list.h
> @@ -809,6 +809,29 @@ static inline size_t list_count_nodes(struct list_head *head)
>  #define list_entry_is_head(pos, head, member)				\
>  	list_is_head(&pos->member, (head))
>  
> +#define __list_for_each_entry(pos, next, head, member)			\
> +	for (typeof(pos) next = list_next_entry(pos =			\
> +		list_first_entry(head, typeof(*pos), member), member);	\
> +	     !list_entry_is_head(pos, head, member);			\
> +	     pos = next, next = list_next_entry(next, member))

[ ... ]

> @@ -816,9 +839,7 @@ static inline size_t list_count_nodes(struct list_head *head)
>   * @member:	the name of the list_head within the struct.
>   */
>  #define list_for_each_entry(pos, head, member)				\
> -	for (pos = list_first_entry(head, typeof(*pos), member);	\
> -	     !list_entry_is_head(pos, head, member);			\
> -	     pos = list_next_entry(pos, member))
> +	__list_for_each_entry(pos, __UNIQUE_ID(next), head, member)

[Severity: Critical]
Does caching the next pointer fundamentally change the dynamic traversal
semantics of the standard list iterators kernel-wide?

A common kernel pattern is pinning the current entry (pos), dropping the
lock to perform a blocking operation, and reacquiring the lock. With
dynamic evaluation, pos->next is safely fetched under the lock.

With the new cached next pointer, if the next element was removed and freed
by a concurrent thread while the lock was dropped, next becomes a dangling
pointer, which could lead to a use-after-free when the loop steps.

Will this also silently skip dynamically inserted elements? If a loop body
inserts a new element immediately after pos, the old macro would naturally
visit it next. The new macro appears to silently skip it because it advances
using the pre-cached next.

Could this also overwrite manual cursor updates? If the loop body explicitly
alters pos to skip elements, the loop increment (pos = next) might overwrite
the updated cursor with the pre-cached next, negating the skip and potentially
causing incorrect traversal behavior.

[ ... ]

> @@ -901,6 +917,8 @@ static inline size_t list_count_nodes(struct list_head *head)
>   * @n:		another type * to use as temporary storage
>   * @head:	the head for your list.
>   * @member:	the name of the list_head within the struct.
> + *
> + * Prefer list_for_each_entry() unless the temporary cursor is needed.
>   */
>  #define list_for_each_entry_safe(pos, n, head, member)			\

[Severity: High]
Does advising developers to prefer list_for_each_entry() over the _safe
variant for removals obscure the intent of the code?

The _safe variant explicitly signals to reviewers and static analysis tools
that the loop body may mutate the list. Conflating variable-scoping
convenience with traversal safety constraints removes a visual guardrail for
destructive operations.

Additionally, does this introduce a backporting hazard? If developers write
new code that unlinks elements using list_for_each_entry(), backporting those
patches to older stable kernels (which lack this caching patch) will compile
cleanly but might reliably introduce use-after-free vulnerabilities, as older
kernels evaluate pos->next after pos has been unlinked.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260609064122.95825-1-kaitao.cheng@linux.dev?part=14

  reply	other threads:[~2026-06-09  6:59 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-09  6:13 [PATCH v2 00/14] list: Prepare entry iterators to cache cursor state Kaitao Cheng
2026-06-09  6:13 ` [PATCH v2 01/14] drbd: Open-code transfer log list walk Kaitao Cheng
2026-06-09  6:53   ` sashiko-bot
2026-06-09  6:13 ` [PATCH v2 02/14] firewire: core: Open-code topology " Kaitao Cheng
2026-06-09  6:53   ` sashiko-bot
2026-06-09  6:25 ` [PATCH v2 03/14] drm/bridge: Open-code bridge chain list walks Kaitao Cheng
2026-06-09  6:25   ` [PATCH v2 04/14] drm/i915/gt: Open-code active timeline walk Kaitao Cheng
2026-06-09  7:00     ` Andy Shevchenko
2026-06-09  6:25   ` [PATCH v2 05/14] drm/i915: Open-code DFS dependency list walk Kaitao Cheng
2026-06-09  6:25   ` [PATCH v2 06/14] drm/ttm: Open-code reservation " Kaitao Cheng
2026-06-09  6:51     ` sashiko-bot
2026-06-09  6:25   ` [PATCH v2 07/14] spi: fsi: Open-code message transfer walk Kaitao Cheng
2026-06-09  7:02     ` Andy Shevchenko
2026-06-09  6:25   ` [PATCH v2 08/14] spi: stm32-ospi: " Kaitao Cheng
2026-06-09  6:57     ` sashiko-bot
2026-06-09  6:25   ` [PATCH v2 09/14] spi: stm32-qspi: " Kaitao Cheng
2026-06-09  6:55     ` sashiko-bot
2026-06-09  6:38 ` [PATCH v2 10/14] spi: tegra210-quad: " Kaitao Cheng
2026-06-09  6:38   ` [PATCH v2 11/14] locking/locktorture: Open-code ww mutex list walk Kaitao Cheng
2026-06-09  6:54     ` sashiko-bot
2026-06-09  6:38   ` [PATCH v2 12/14] locking/ww_mutex: Open-code stress reorder " Kaitao Cheng
2026-06-09  6:57   ` [PATCH v2 10/14] spi: tegra210-quad: Open-code message transfer walk sashiko-bot
2026-06-09  6:41 ` [PATCH v2 13/14] ASoC: dapm: Open-code widget invalidation walk Kaitao Cheng
2026-06-09  6:41   ` [PATCH v2 14/14] list: Cache cursors in entry iterators Kaitao Cheng
2026-06-09  6:59     ` sashiko-bot [this message]
2026-06-09  6:55   ` [PATCH v2 13/14] ASoC: dapm: Open-code widget invalidation walk sashiko-bot
2026-06-09  6:47 ` [PATCH v2 00/14] list: Prepare entry iterators to cache cursor state Andy Shevchenko
2026-06-09  7:05   ` Andy Shevchenko
2026-06-09 10:33 ` Christian König

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=20260609065951.DC20B1F00893@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=kaitao.cheng@linux.dev \
    --cc=sashiko-reviews@lists.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.