6.11-stable review patch. If anyone has any objections, please let me know.
------------------
From: Masahiro Yamada masahiroy@kernel.org
[ Upstream commit 4d46b5b623e0adee1153b1d80689211e5094ae44 ]
Since commit f79dc03fe68c ("kconfig: refactor choice value calculation"), Kconfig for ARCH=powerpc may result in an infinite loop. This occurs because there are two entries for POWERPC64_CPU in a choice block.
If the same symbol appears twice in a choice block, the ->choice_link node is added twice to ->choice_members, resulting a corrupted linked list.
A simple test case is:
choice prompt "choice"
config A bool "A"
config B bool "B 1"
config B bool "B 2"
endchoice
Running 'make defconfig' results in an infinite loop.
One solution is to replace the current two entries:
config POWERPC64_CPU bool "Generic (POWER5 and PowerPC 970 and above)" depends on PPC_BOOK3S_64 && !CPU_LITTLE_ENDIAN select PPC_64S_HASH_MMU
config POWERPC64_CPU bool "Generic (POWER8 and above)" depends on PPC_BOOK3S_64 && CPU_LITTLE_ENDIAN select ARCH_HAS_FAST_MULTIPLIER select PPC_64S_HASH_MMU select PPC_HAS_LBARX_LHARX
with the following single entry:
config POWERPC64_CPU bool "Generic 64 bit powerpc" depends on PPC_BOOK3S_64 select ARCH_HAS_FAST_MULTIPLIER if CPU_LITTLE_ENDIAN select PPC_64S_HASH_MMU select PPC_HAS_LBARX_LHARX if CPU_LITTLE_ENDIAN
In my opinion, the latter looks cleaner, but PowerPC maintainers may prefer to display different prompts depending on CPU_LITTLE_ENDIAN.
For now, this commit fixes the issue in Kconfig, restoring the original behavior. I will reconsider whether such a use case is worth supporting.
Fixes: f79dc03fe68c ("kconfig: refactor choice value calculation") Reported-by: Marco Bonelli marco@mebeim.net Closes: https://lore.kernel.org/all/1763151587.3581913.1727224126288@privateemail.co... Signed-off-by: Masahiro Yamada masahiroy@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- scripts/kconfig/parser.y | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/scripts/kconfig/parser.y b/scripts/kconfig/parser.y index 61900feb4254a..add1ce4b5091d 100644 --- a/scripts/kconfig/parser.y +++ b/scripts/kconfig/parser.y @@ -158,8 +158,14 @@ config_stmt: config_entry_start config_option_list yynerrs++; }
- list_add_tail(¤t_entry->sym->choice_link, - ¤t_choice->choice_members); + /* + * If the same symbol appears twice in a choice block, the list + * node would be added twice, leading to a broken linked list. + * list_empty() ensures that this symbol has not yet added. + */ + if (list_empty(¤t_entry->sym->choice_link)) + list_add_tail(¤t_entry->sym->choice_link, + ¤t_choice->choice_members); }
printd(DEBUG_PARSE, "%s:%d:endconfig\n", cur_filename, cur_lineno);