* [PATCH v2] kconfig: Add transitional symbol attribute for migration support
@ 2025-08-30 2:01 Kees Cook
2025-09-01 8:34 ` Vegard Nossum
` (2 more replies)
0 siblings, 3 replies; 12+ messages in thread
From: Kees Cook @ 2025-08-30 2:01 UTC (permalink / raw)
To: Nathan Chancellor
Cc: Kees Cook, Nicolas Schier, Jonathan Corbet, Masahiro Yamada,
Randy Dunlap, Arnd Bergmann, Krzysztof Kozlowski, linux-kbuild,
linux-doc, Miguel Ojeda, Stephen Brennan, Marco Bonelli,
Petr Vorel, linux-kernel, linux-hardening
During kernel option migrations (e.g. CONFIG_CFI_CLANG to CONFIG_CFI),
existing .config files need to maintain backward compatibility while
preventing deprecated options from appearing in newly generated
configurations. This is challenging with existing Kconfig mechanisms
because:
1. Simply removing old options breaks existing .config files.
2. Manually listing an option as "deprecated" leaves it needlessly
visible and still writes them to new .config files.
3. Using any method to remove visibility (.e.g no 'prompt', 'if n',
etc) prevents the option from being processed at all.
Add a "transitional" attribute that creates symbols which are:
- Processed during configuration (can influence other symbols' defaults)
- Hidden from user menus (no prompts appear)
- Omitted from newly written .config files (gets migrated)
- Restricted to only having help sections (no defaults, selects, etc)
making it truly just a "prior value pass-through" option.
The transitional syntax requires a type argument and prevents type
redefinition:
config OLD_OPTION
transitional bool
help
Transitional config for OLD_OPTION migration.
config NEW_OPTION
bool "New option"
default OLD_OPTION
This allows seamless migration: olddefconfig processes existing
CONFIG_OLD_OPTION=y settings to enable CONFIG_NEW_OPTION=y, while
CONFIG_OLD_OPTION is omitted from newly generated .config files.
Implementation details:
- Parser validates transitional symbols can only have help sections
- Symbol visibility logic updated: usable = (visible != no || transitional)
- Transitional symbols preserve user values during configuration
- Type safety enforced to prevent redefinition after transitional declaration
- Used distinct struct members instead of new flags for readability
- Documentation added to show the usage
Signed-off-by: Kees Cook <kees@kernel.org>
---
With help from Claude Code to show me how to navigate the kconfig parser.
v2: fixed human-introduced errors
v1: https://lore.kernel.org/all/20250830014438.work.682-kees@kernel.org/
Cc: Nathan Chancellor <nathan@kernel.org>
Cc: Nicolas Schier <nicolas.schier@linux.dev>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Masahiro Yamada <masahiroy@kernel.org>
Cc: Randy Dunlap <rdunlap@infradead.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Cc: <linux-kbuild@vger.kernel.org>
Cc: <linux-doc@vger.kernel.org>
---
scripts/kconfig/expr.h | 15 +++++++
scripts/kconfig/lexer.l | 1 +
scripts/kconfig/parser.y | 51 +++++++++++++++++++++++
scripts/kconfig/symbol.c | 11 +++--
Documentation/kbuild/kconfig-language.rst | 31 ++++++++++++++
5 files changed, 106 insertions(+), 3 deletions(-)
diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h
index fe2231e0e6a4..be51574d6c77 100644
--- a/scripts/kconfig/expr.h
+++ b/scripts/kconfig/expr.h
@@ -127,6 +127,21 @@ struct symbol {
/* SYMBOL_* flags */
int flags;
+ /*
+ * Transitional symbol - processed during configuration but hidden from
+ * user in menus and omitted from newly written .config files. Used for
+ * backward compatibility during config option migrations (e.g.,
+ * CFI_CLANG → CFI). Transitional symbols can still influence default
+ * expressions of other symbols.
+ */
+ bool transitional:1;
+
+ /*
+ * Symbol usability - calculated as (visible != no || transitional).
+ * Determines if symbol can be used in expressions.
+ */
+ bool usable:1;
+
/* List of properties. See prop_type. */
struct property *prop;
diff --git a/scripts/kconfig/lexer.l b/scripts/kconfig/lexer.l
index 9c2cdfc33c6f..6d2c92c6095d 100644
--- a/scripts/kconfig/lexer.l
+++ b/scripts/kconfig/lexer.l
@@ -126,6 +126,7 @@ n [A-Za-z0-9_-]
"select" return T_SELECT;
"source" return T_SOURCE;
"string" return T_STRING;
+"transitional" return T_TRANSITIONAL;
"tristate" return T_TRISTATE;
"visible" return T_VISIBLE;
"||" return T_OR;
diff --git a/scripts/kconfig/parser.y b/scripts/kconfig/parser.y
index e9c3c664e925..01d2d0f720ce 100644
--- a/scripts/kconfig/parser.y
+++ b/scripts/kconfig/parser.y
@@ -75,6 +75,7 @@ struct menu *current_menu, *current_entry, *current_choice;
%token T_SELECT
%token T_SOURCE
%token T_STRING
+%token T_TRANSITIONAL
%token T_TRISTATE
%token T_VISIBLE
%token T_EOL
@@ -205,6 +206,16 @@ config_option: T_PROMPT T_WORD_QUOTE if_expr T_EOL
printd(DEBUG_PARSE, "%s:%d:prompt\n", cur_filename, cur_lineno);
};
+config_option: T_TRANSITIONAL type T_EOL
+{
+ if (current_entry->sym->type != S_UNKNOWN)
+ yyerror("transitional type cannot be set after symbol type is already defined");
+ menu_set_type($2);
+ current_entry->sym->transitional = true;
+ printd(DEBUG_PARSE, "%s:%d:transitional(%u)\n", cur_filename, cur_lineno,
+ $2);
+};
+
config_option: default expr if_expr T_EOL
{
menu_add_expr(P_DEFAULT, $2, $3);
@@ -482,6 +493,43 @@ assign_val:
%%
+/**
+ * transitional_check_sanity - check transitional symbols have no other
+ * properties
+ *
+ * @menu: menu of the potentially transitional symbol
+ *
+ * Return: -1 if an error is found, 0 otherwise.
+ */
+static int transitional_check_sanity(const struct menu *menu)
+{
+ struct property *prop;
+
+ if (!menu->sym || !menu->sym->transitional)
+ return 0;
+
+ /* Check for depends and visible conditions. */
+ if ((menu->dep && !expr_is_yes(menu->dep)) ||
+ (menu->visibility && !expr_is_yes(menu->visibility))) {
+ fprintf(stderr, "%s:%d: error: %s",
+ menu->filename, menu->lineno,
+ "transitional symbols can only have help sections\n");
+ return -1;
+ }
+
+ /* Check for any property other than "help". */
+ for (prop = menu->sym->prop; prop; prop = prop->next) {
+ if (prop->type != P_COMMENT) {
+ fprintf(stderr, "%s:%d: error: %s",
+ prop->filename, prop->lineno,
+ "transitional symbols can only have help sections\n");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
/**
* choice_check_sanity - check sanity of a choice member
*
@@ -558,6 +606,9 @@ void conf_parse(const char *name)
if (menu->sym && sym_check_deps(menu->sym))
yynerrs++;
+ if (transitional_check_sanity(menu))
+ yynerrs++;
+
if (menu->sym && sym_is_choice(menu->sym)) {
menu_for_each_sub_entry(child, menu)
if (child->sym && choice_check_sanity(child))
diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
index 26ab10c0fd76..b822c0c897e5 100644
--- a/scripts/kconfig/symbol.c
+++ b/scripts/kconfig/symbol.c
@@ -447,6 +447,9 @@ void sym_calc_value(struct symbol *sym)
if (sym->visible != no)
sym->flags |= SYMBOL_WRITE;
+ /* Calculate usable flag */
+ sym->usable = (sym->visible != no || sym->transitional);
+
/* set default if recursively called */
sym->curr = newval;
@@ -459,13 +462,15 @@ void sym_calc_value(struct symbol *sym)
sym_calc_choice(choice_menu);
newval.tri = sym->curr.tri;
} else {
- if (sym->visible != no) {
+ if (sym->usable) {
/* if the symbol is visible use the user value
* if available, otherwise try the default value
*/
if (sym_has_value(sym)) {
+ tristate value = sym->transitional ?
+ sym->def[S_DEF_USER].tri : sym->visible;
newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri,
- sym->visible);
+ value);
goto calc_newval;
}
}
@@ -497,7 +502,7 @@ void sym_calc_value(struct symbol *sym)
case S_STRING:
case S_HEX:
case S_INT:
- if (sym->visible != no && sym_has_value(sym)) {
+ if (sym->usable && sym_has_value(sym)) {
newval.val = sym->def[S_DEF_USER].val;
break;
}
diff --git a/Documentation/kbuild/kconfig-language.rst b/Documentation/kbuild/kconfig-language.rst
index a91abb8f6840..345c334ce680 100644
--- a/Documentation/kbuild/kconfig-language.rst
+++ b/Documentation/kbuild/kconfig-language.rst
@@ -232,6 +232,37 @@ applicable everywhere (see syntax).
enables the third modular state for all config symbols.
At most one symbol may have the "modules" option set.
+- transitional attribute: "transitional"
+ This declares the symbol as transitional, meaning it should be processed
+ during configuration but omitted from newly written .config files.
+ Transitional symbols are useful for backward compatibility during config
+ option migrations - they allow olddefconfig to process existing .config
+ files while ensuring the old option doesn't appear in new configurations.
+
+ A transitional symbol:
+ - Has no prompt (is not visible to users in menus)
+ - Is processed normally during configuration (values are read and used)
+ - Can be referenced in default expressions of other symbols
+ - Is not written to new .config files
+ - Cannot have any other properties (it is a pass-through option)
+
+ Example migration from OLD_NAME to NEW_NAME::
+
+ config NEW_NAME
+ bool "New option name"
+ default OLD_NAME
+ help
+ This replaces the old CONFIG_OLD_NAME option.
+
+ config OLD_NAME
+ transitional bool
+ help
+ Transitional config for OLD_NAME to NEW_NAME migration.
+
+ With this setup, existing .config files with "CONFIG_OLD_NAME=y" will
+ result in "CONFIG_NEW_NAME=y" being set, while CONFIG_OLD_NAME will be
+ omitted from newly written .config files.
+
Menu dependencies
-----------------
--
2.34.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH v2] kconfig: Add transitional symbol attribute for migration support
2025-08-30 2:01 [PATCH v2] kconfig: Add transitional symbol attribute for migration support Kees Cook
@ 2025-09-01 8:34 ` Vegard Nossum
2025-09-01 16:56 ` Kees Cook
2025-09-01 9:09 ` Jani Nikula
2025-09-01 16:39 ` Randy Dunlap
2 siblings, 1 reply; 12+ messages in thread
From: Vegard Nossum @ 2025-09-01 8:34 UTC (permalink / raw)
To: Kees Cook, Nathan Chancellor
Cc: Nicolas Schier, Jonathan Corbet, Masahiro Yamada, Randy Dunlap,
Arnd Bergmann, Krzysztof Kozlowski, linux-kbuild, linux-doc,
Miguel Ojeda, Stephen Brennan, Marco Bonelli, Petr Vorel,
linux-kernel, linux-hardening
Hi,
Drive-by review... consider it more as "here's some stuff that could be
worth looking at" rather than blocking in any way.
On 30/08/2025 04:01, Kees Cook wrote:
> During kernel option migrations (e.g. CONFIG_CFI_CLANG to CONFIG_CFI),
> existing .config files need to maintain backward compatibility while
> preventing deprecated options from appearing in newly generated
> configurations. This is challenging with existing Kconfig mechanisms
> because:
>
> 1. Simply removing old options breaks existing .config files.
> 2. Manually listing an option as "deprecated" leaves it needlessly
> visible and still writes them to new .config files.
> 3. Using any method to remove visibility (.e.g no 'prompt', 'if n',
> etc) prevents the option from being processed at all.
>
> Add a "transitional" attribute that creates symbols which are:
> - Processed during configuration (can influence other symbols' defaults)
> - Hidden from user menus (no prompts appear)
> - Omitted from newly written .config files (gets migrated)
> - Restricted to only having help sections (no defaults, selects, etc)
> making it truly just a "prior value pass-through" option.
>
> The transitional syntax requires a type argument and prevents type
> redefinition:
>
> config OLD_OPTION
> transitional bool
> help
> Transitional config for OLD_OPTION migration.
>
> config NEW_OPTION
> bool "New option"
> default OLD_OPTION
Can you add this to scripts/kconfig/tests/ + both positive and negative
tests? Tests are run with 'make testconfig' but (AFAICT) doesn't
actually recompile config/mconf/etc. before running the tests, so small
gotcha there.
> This allows seamless migration: olddefconfig processes existing
> CONFIG_OLD_OPTION=y settings to enable CONFIG_NEW_OPTION=y, while
> CONFIG_OLD_OPTION is omitted from newly generated .config files.
>
> Implementation details:
> - Parser validates transitional symbols can only have help sections
> - Symbol visibility logic updated: usable = (visible != no || transitional)
> - Transitional symbols preserve user values during configuration
> - Type safety enforced to prevent redefinition after transitional declaration
> - Used distinct struct members instead of new flags for readability
> - Documentation added to show the usage
>
> Signed-off-by: Kees Cook <kees@kernel.org>
> ---
> With help from Claude Code to show me how to navigate the kconfig parser.
>
> v2: fixed human-introduced errors
> v1: https://lore.kernel.org/all/20250830014438.work.682-kees@kernel.org/
>
> Cc: Nathan Chancellor <nathan@kernel.org>
> Cc: Nicolas Schier <nicolas.schier@linux.dev>
> Cc: Jonathan Corbet <corbet@lwn.net>
> Cc: Masahiro Yamada <masahiroy@kernel.org>
> Cc: Randy Dunlap <rdunlap@infradead.org>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> Cc: <linux-kbuild@vger.kernel.org>
> Cc: <linux-doc@vger.kernel.org>
> ---
> scripts/kconfig/expr.h | 15 +++++++
> scripts/kconfig/lexer.l | 1 +
> scripts/kconfig/parser.y | 51 +++++++++++++++++++++++
> scripts/kconfig/symbol.c | 11 +++--
> Documentation/kbuild/kconfig-language.rst | 31 ++++++++++++++
> 5 files changed, 106 insertions(+), 3 deletions(-)
>
> diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h
> index fe2231e0e6a4..be51574d6c77 100644
> --- a/scripts/kconfig/expr.h
> +++ b/scripts/kconfig/expr.h
> @@ -127,6 +127,21 @@ struct symbol {
> /* SYMBOL_* flags */
> int flags;
>
> + /*
> + * Transitional symbol - processed during configuration but hidden from
> + * user in menus and omitted from newly written .config files. Used for
> + * backward compatibility during config option migrations (e.g.,
> + * CFI_CLANG → CFI). Transitional symbols can still influence default
> + * expressions of other symbols.
> + */
> + bool transitional:1;
> +
> + /*
> + * Symbol usability - calculated as (visible != no || transitional).
> + * Determines if symbol can be used in expressions.
> + */
> + bool usable:1;
> +
It's a bit of a "red flag" to see bitfield bools just after an "int
flags;" member... should these be SYMBOL_ flags?
Speaking of SYMBOL_ flags, there's apparently one that controls whether
a given symbol should be written out to .config:
scripts/kconfig/expr.h:#define SYMBOL_WRITE 0x0200 /* write symbol
to file (KCONFIG_CONFIG) */
This seems like something you'd like to use somehow -- maybe simply
clear it in sym_calc_value() if it's transitional? Similar to how it's
done for choice values:
if (sym_is_choice(sym))
sym->flags &= ~SYMBOL_WRITE;
> /* List of properties. See prop_type. */
> struct property *prop;
>
> diff --git a/scripts/kconfig/lexer.l b/scripts/kconfig/lexer.l
> index 9c2cdfc33c6f..6d2c92c6095d 100644
> --- a/scripts/kconfig/lexer.l
> +++ b/scripts/kconfig/lexer.l
> @@ -126,6 +126,7 @@ n [A-Za-z0-9_-]
> "select" return T_SELECT;
> "source" return T_SOURCE;
> "string" return T_STRING;
> +"transitional" return T_TRANSITIONAL;
> "tristate" return T_TRISTATE;
> "visible" return T_VISIBLE;
> "||" return T_OR;
> diff --git a/scripts/kconfig/parser.y b/scripts/kconfig/parser.y
> index e9c3c664e925..01d2d0f720ce 100644
> --- a/scripts/kconfig/parser.y
> +++ b/scripts/kconfig/parser.y
> @@ -75,6 +75,7 @@ struct menu *current_menu, *current_entry, *current_choice;
> %token T_SELECT
> %token T_SOURCE
> %token T_STRING
> +%token T_TRANSITIONAL
> %token T_TRISTATE
> %token T_VISIBLE
> %token T_EOL
> @@ -205,6 +206,16 @@ config_option: T_PROMPT T_WORD_QUOTE if_expr T_EOL
> printd(DEBUG_PARSE, "%s:%d:prompt\n", cur_filename, cur_lineno);
> };
>
> +config_option: T_TRANSITIONAL type T_EOL
> +{
> + if (current_entry->sym->type != S_UNKNOWN)
> + yyerror("transitional type cannot be set after symbol type is already defined");
> + menu_set_type($2);
> + current_entry->sym->transitional = true;
> + printd(DEBUG_PARSE, "%s:%d:transitional(%u)\n", cur_filename, cur_lineno,
> + $2);
> +};
You could also consider making this an attribute similar to the
"modules" flags and simplify:
config_option: T_TRANSITIONAL T_EOL
{
current_entry->sym->transitional = true;
printd(DEBUG_PARSE, "%s:%d:transitional\n", cur_filename,
cur_lineno);
};
...it would mean the config options look this way:
config OLD_OPTION
bool
transitional
(If not, menu_set_type() does already contain a check for whether the
type has already been set.)
> +
> config_option: default expr if_expr T_EOL
> {
> menu_add_expr(P_DEFAULT, $2, $3);
> @@ -482,6 +493,43 @@ assign_val:
>
> %%
>
> +/**
> + * transitional_check_sanity - check transitional symbols have no other
> + * properties
> + *
> + * @menu: menu of the potentially transitional symbol
> + *
> + * Return: -1 if an error is found, 0 otherwise.
> + */
> +static int transitional_check_sanity(const struct menu *menu)
> +{
> + struct property *prop;
> +
> + if (!menu->sym || !menu->sym->transitional)
> + return 0;
> +
> + /* Check for depends and visible conditions. */
> + if ((menu->dep && !expr_is_yes(menu->dep)) ||
> + (menu->visibility && !expr_is_yes(menu->visibility))) {
> + fprintf(stderr, "%s:%d: error: %s",
> + menu->filename, menu->lineno,
> + "transitional symbols can only have help sections\n");
> + return -1;
> + }
> +
> + /* Check for any property other than "help". */
> + for (prop = menu->sym->prop; prop; prop = prop->next) {
> + if (prop->type != P_COMMENT) {
> + fprintf(stderr, "%s:%d: error: %s",
> + prop->filename, prop->lineno,
> + "transitional symbols can only have help sections\n");
> + return -1;
> + }
> + }
> +
> + return 0;
> +}
> +
> /**
> * choice_check_sanity - check sanity of a choice member
> *
> @@ -558,6 +606,9 @@ void conf_parse(const char *name)
> if (menu->sym && sym_check_deps(menu->sym))
> yynerrs++;
>
> + if (transitional_check_sanity(menu))
> + yynerrs++;
> +
> if (menu->sym && sym_is_choice(menu->sym)) {
> menu_for_each_sub_entry(child, menu)
> if (child->sym && choice_check_sanity(child))
> diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
> index 26ab10c0fd76..b822c0c897e5 100644
> --- a/scripts/kconfig/symbol.c
> +++ b/scripts/kconfig/symbol.c
> @@ -447,6 +447,9 @@ void sym_calc_value(struct symbol *sym)
> if (sym->visible != no)
> sym->flags |= SYMBOL_WRITE;
>
> + /* Calculate usable flag */
> + sym->usable = (sym->visible != no || sym->transitional);
> +
Is this actually ever used outside of this function? (IOW could this
just be a local variable instead of a sym-> flag/member?) Or do we need
to set it here because sym_calc_value() calls itself recursively? To me
it looks like we only ever access sym->usable for the "sym" that was
passed as an argument to the function.
> /* set default if recursively called */
> sym->curr = newval;
>
> @@ -459,13 +462,15 @@ void sym_calc_value(struct symbol *sym)
> sym_calc_choice(choice_menu);
> newval.tri = sym->curr.tri;
> } else {
> - if (sym->visible != no) {
> + if (sym->usable) {
> /* if the symbol is visible use the user value
> * if available, otherwise try the default value
> */
> if (sym_has_value(sym)) {
> + tristate value = sym->transitional ?
> + sym->def[S_DEF_USER].tri : sym->visible;
> newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri,
> - sym->visible);
> + value);
This looks a bit odd to me. Just thinking out loud: your new logic is
there to be able to use a value even though it's not visible. In the
case where it's transitional you use the .config value instead of the
condition that makes it visible.
Could you simply change sym_calc_visibility() instead to always return
'yes' when the symbol is transitional? Wouldn't that simplify everything
in sym_calc_value()?
> goto calc_newval;
> }
> }
> @@ -497,7 +502,7 @@ void sym_calc_value(struct symbol *sym)
> case S_STRING:
> case S_HEX:
> case S_INT:
> - if (sym->visible != no && sym_has_value(sym)) {
> + if (sym->usable && sym_has_value(sym)) {
> newval.val = sym->def[S_DEF_USER].val;
> break;
> }
Ok.
> diff --git a/Documentation/kbuild/kconfig-language.rst b/Documentation/kbuild/kconfig-language.rst
> index a91abb8f6840..345c334ce680 100644
> --- a/Documentation/kbuild/kconfig-language.rst
> +++ b/Documentation/kbuild/kconfig-language.rst
> @@ -232,6 +232,37 @@ applicable everywhere (see syntax).
> enables the third modular state for all config symbols.
> At most one symbol may have the "modules" option set.
>
> +- transitional attribute: "transitional"
> + This declares the symbol as transitional, meaning it should be processed
> + during configuration but omitted from newly written .config files.
> + Transitional symbols are useful for backward compatibility during config
> + option migrations - they allow olddefconfig to process existing .config
> + files while ensuring the old option doesn't appear in new configurations.
> +
> + A transitional symbol:
> + - Has no prompt (is not visible to users in menus)
> + - Is processed normally during configuration (values are read and used)
> + - Can be referenced in default expressions of other symbols
> + - Is not written to new .config files
> + - Cannot have any other properties (it is a pass-through option)
> +
> + Example migration from OLD_NAME to NEW_NAME::
> +
> + config NEW_NAME
> + bool "New option name"
> + default OLD_NAME
> + help
> + This replaces the old CONFIG_OLD_NAME option.
> +
> + config OLD_NAME
> + transitional bool
> + help
> + Transitional config for OLD_NAME to NEW_NAME migration.
> +
> + With this setup, existing .config files with "CONFIG_OLD_NAME=y" will
> + result in "CONFIG_NEW_NAME=y" being set, while CONFIG_OLD_NAME will be
> + omitted from newly written .config files.
> +
> Menu dependencies
> -----------------
>
Vegard
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2] kconfig: Add transitional symbol attribute for migration support
2025-08-30 2:01 [PATCH v2] kconfig: Add transitional symbol attribute for migration support Kees Cook
2025-09-01 8:34 ` Vegard Nossum
@ 2025-09-01 9:09 ` Jani Nikula
2025-09-01 16:48 ` Kees Cook
2025-09-01 16:39 ` Randy Dunlap
2 siblings, 1 reply; 12+ messages in thread
From: Jani Nikula @ 2025-09-01 9:09 UTC (permalink / raw)
To: Kees Cook, Nathan Chancellor
Cc: Kees Cook, Nicolas Schier, Jonathan Corbet, Masahiro Yamada,
Randy Dunlap, Arnd Bergmann, Krzysztof Kozlowski, linux-kbuild,
linux-doc, Miguel Ojeda, Stephen Brennan, Marco Bonelli,
Petr Vorel, linux-kernel, linux-hardening
On Fri, 29 Aug 2025, Kees Cook <kees@kernel.org> wrote:
> During kernel option migrations (e.g. CONFIG_CFI_CLANG to CONFIG_CFI),
> existing .config files need to maintain backward compatibility while
> preventing deprecated options from appearing in newly generated
> configurations. This is challenging with existing Kconfig mechanisms
> because:
>
> 1. Simply removing old options breaks existing .config files.
> 2. Manually listing an option as "deprecated" leaves it needlessly
> visible and still writes them to new .config files.
> 3. Using any method to remove visibility (.e.g no 'prompt', 'if n',
> etc) prevents the option from being processed at all.
>
> Add a "transitional" attribute that creates symbols which are:
> - Processed during configuration (can influence other symbols' defaults)
> - Hidden from user menus (no prompts appear)
> - Omitted from newly written .config files (gets migrated)
> - Restricted to only having help sections (no defaults, selects, etc)
> making it truly just a "prior value pass-through" option.
>
> The transitional syntax requires a type argument and prevents type
> redefinition:
>
> config OLD_OPTION
> transitional bool
> help
> Transitional config for OLD_OPTION migration.
How long do you think we'll need to keep the transitional config options
around? Forever?
BR,
Jani.
> config NEW_OPTION
> bool "New option"
> default OLD_OPTION
>
> This allows seamless migration: olddefconfig processes existing
> CONFIG_OLD_OPTION=y settings to enable CONFIG_NEW_OPTION=y, while
> CONFIG_OLD_OPTION is omitted from newly generated .config files.
>
> Implementation details:
> - Parser validates transitional symbols can only have help sections
> - Symbol visibility logic updated: usable = (visible != no || transitional)
> - Transitional symbols preserve user values during configuration
> - Type safety enforced to prevent redefinition after transitional declaration
> - Used distinct struct members instead of new flags for readability
> - Documentation added to show the usage
>
> Signed-off-by: Kees Cook <kees@kernel.org>
> ---
> With help from Claude Code to show me how to navigate the kconfig parser.
>
> v2: fixed human-introduced errors
> v1: https://lore.kernel.org/all/20250830014438.work.682-kees@kernel.org/
>
> Cc: Nathan Chancellor <nathan@kernel.org>
> Cc: Nicolas Schier <nicolas.schier@linux.dev>
> Cc: Jonathan Corbet <corbet@lwn.net>
> Cc: Masahiro Yamada <masahiroy@kernel.org>
> Cc: Randy Dunlap <rdunlap@infradead.org>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> Cc: <linux-kbuild@vger.kernel.org>
> Cc: <linux-doc@vger.kernel.org>
> ---
> scripts/kconfig/expr.h | 15 +++++++
> scripts/kconfig/lexer.l | 1 +
> scripts/kconfig/parser.y | 51 +++++++++++++++++++++++
> scripts/kconfig/symbol.c | 11 +++--
> Documentation/kbuild/kconfig-language.rst | 31 ++++++++++++++
> 5 files changed, 106 insertions(+), 3 deletions(-)
>
> diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h
> index fe2231e0e6a4..be51574d6c77 100644
> --- a/scripts/kconfig/expr.h
> +++ b/scripts/kconfig/expr.h
> @@ -127,6 +127,21 @@ struct symbol {
> /* SYMBOL_* flags */
> int flags;
>
> + /*
> + * Transitional symbol - processed during configuration but hidden from
> + * user in menus and omitted from newly written .config files. Used for
> + * backward compatibility during config option migrations (e.g.,
> + * CFI_CLANG → CFI). Transitional symbols can still influence default
> + * expressions of other symbols.
> + */
> + bool transitional:1;
> +
> + /*
> + * Symbol usability - calculated as (visible != no || transitional).
> + * Determines if symbol can be used in expressions.
> + */
> + bool usable:1;
> +
> /* List of properties. See prop_type. */
> struct property *prop;
>
> diff --git a/scripts/kconfig/lexer.l b/scripts/kconfig/lexer.l
> index 9c2cdfc33c6f..6d2c92c6095d 100644
> --- a/scripts/kconfig/lexer.l
> +++ b/scripts/kconfig/lexer.l
> @@ -126,6 +126,7 @@ n [A-Za-z0-9_-]
> "select" return T_SELECT;
> "source" return T_SOURCE;
> "string" return T_STRING;
> +"transitional" return T_TRANSITIONAL;
> "tristate" return T_TRISTATE;
> "visible" return T_VISIBLE;
> "||" return T_OR;
> diff --git a/scripts/kconfig/parser.y b/scripts/kconfig/parser.y
> index e9c3c664e925..01d2d0f720ce 100644
> --- a/scripts/kconfig/parser.y
> +++ b/scripts/kconfig/parser.y
> @@ -75,6 +75,7 @@ struct menu *current_menu, *current_entry, *current_choice;
> %token T_SELECT
> %token T_SOURCE
> %token T_STRING
> +%token T_TRANSITIONAL
> %token T_TRISTATE
> %token T_VISIBLE
> %token T_EOL
> @@ -205,6 +206,16 @@ config_option: T_PROMPT T_WORD_QUOTE if_expr T_EOL
> printd(DEBUG_PARSE, "%s:%d:prompt\n", cur_filename, cur_lineno);
> };
>
> +config_option: T_TRANSITIONAL type T_EOL
> +{
> + if (current_entry->sym->type != S_UNKNOWN)
> + yyerror("transitional type cannot be set after symbol type is already defined");
> + menu_set_type($2);
> + current_entry->sym->transitional = true;
> + printd(DEBUG_PARSE, "%s:%d:transitional(%u)\n", cur_filename, cur_lineno,
> + $2);
> +};
> +
> config_option: default expr if_expr T_EOL
> {
> menu_add_expr(P_DEFAULT, $2, $3);
> @@ -482,6 +493,43 @@ assign_val:
>
> %%
>
> +/**
> + * transitional_check_sanity - check transitional symbols have no other
> + * properties
> + *
> + * @menu: menu of the potentially transitional symbol
> + *
> + * Return: -1 if an error is found, 0 otherwise.
> + */
> +static int transitional_check_sanity(const struct menu *menu)
> +{
> + struct property *prop;
> +
> + if (!menu->sym || !menu->sym->transitional)
> + return 0;
> +
> + /* Check for depends and visible conditions. */
> + if ((menu->dep && !expr_is_yes(menu->dep)) ||
> + (menu->visibility && !expr_is_yes(menu->visibility))) {
> + fprintf(stderr, "%s:%d: error: %s",
> + menu->filename, menu->lineno,
> + "transitional symbols can only have help sections\n");
> + return -1;
> + }
> +
> + /* Check for any property other than "help". */
> + for (prop = menu->sym->prop; prop; prop = prop->next) {
> + if (prop->type != P_COMMENT) {
> + fprintf(stderr, "%s:%d: error: %s",
> + prop->filename, prop->lineno,
> + "transitional symbols can only have help sections\n");
> + return -1;
> + }
> + }
> +
> + return 0;
> +}
> +
> /**
> * choice_check_sanity - check sanity of a choice member
> *
> @@ -558,6 +606,9 @@ void conf_parse(const char *name)
> if (menu->sym && sym_check_deps(menu->sym))
> yynerrs++;
>
> + if (transitional_check_sanity(menu))
> + yynerrs++;
> +
> if (menu->sym && sym_is_choice(menu->sym)) {
> menu_for_each_sub_entry(child, menu)
> if (child->sym && choice_check_sanity(child))
> diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
> index 26ab10c0fd76..b822c0c897e5 100644
> --- a/scripts/kconfig/symbol.c
> +++ b/scripts/kconfig/symbol.c
> @@ -447,6 +447,9 @@ void sym_calc_value(struct symbol *sym)
> if (sym->visible != no)
> sym->flags |= SYMBOL_WRITE;
>
> + /* Calculate usable flag */
> + sym->usable = (sym->visible != no || sym->transitional);
> +
> /* set default if recursively called */
> sym->curr = newval;
>
> @@ -459,13 +462,15 @@ void sym_calc_value(struct symbol *sym)
> sym_calc_choice(choice_menu);
> newval.tri = sym->curr.tri;
> } else {
> - if (sym->visible != no) {
> + if (sym->usable) {
> /* if the symbol is visible use the user value
> * if available, otherwise try the default value
> */
> if (sym_has_value(sym)) {
> + tristate value = sym->transitional ?
> + sym->def[S_DEF_USER].tri : sym->visible;
> newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri,
> - sym->visible);
> + value);
> goto calc_newval;
> }
> }
> @@ -497,7 +502,7 @@ void sym_calc_value(struct symbol *sym)
> case S_STRING:
> case S_HEX:
> case S_INT:
> - if (sym->visible != no && sym_has_value(sym)) {
> + if (sym->usable && sym_has_value(sym)) {
> newval.val = sym->def[S_DEF_USER].val;
> break;
> }
> diff --git a/Documentation/kbuild/kconfig-language.rst b/Documentation/kbuild/kconfig-language.rst
> index a91abb8f6840..345c334ce680 100644
> --- a/Documentation/kbuild/kconfig-language.rst
> +++ b/Documentation/kbuild/kconfig-language.rst
> @@ -232,6 +232,37 @@ applicable everywhere (see syntax).
> enables the third modular state for all config symbols.
> At most one symbol may have the "modules" option set.
>
> +- transitional attribute: "transitional"
> + This declares the symbol as transitional, meaning it should be processed
> + during configuration but omitted from newly written .config files.
> + Transitional symbols are useful for backward compatibility during config
> + option migrations - they allow olddefconfig to process existing .config
> + files while ensuring the old option doesn't appear in new configurations.
> +
> + A transitional symbol:
> + - Has no prompt (is not visible to users in menus)
> + - Is processed normally during configuration (values are read and used)
> + - Can be referenced in default expressions of other symbols
> + - Is not written to new .config files
> + - Cannot have any other properties (it is a pass-through option)
> +
> + Example migration from OLD_NAME to NEW_NAME::
> +
> + config NEW_NAME
> + bool "New option name"
> + default OLD_NAME
> + help
> + This replaces the old CONFIG_OLD_NAME option.
> +
> + config OLD_NAME
> + transitional bool
> + help
> + Transitional config for OLD_NAME to NEW_NAME migration.
> +
> + With this setup, existing .config files with "CONFIG_OLD_NAME=y" will
> + result in "CONFIG_NEW_NAME=y" being set, while CONFIG_OLD_NAME will be
> + omitted from newly written .config files.
> +
> Menu dependencies
> -----------------
--
Jani Nikula, Intel
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2] kconfig: Add transitional symbol attribute for migration support
2025-08-30 2:01 [PATCH v2] kconfig: Add transitional symbol attribute for migration support Kees Cook
2025-09-01 8:34 ` Vegard Nossum
2025-09-01 9:09 ` Jani Nikula
@ 2025-09-01 16:39 ` Randy Dunlap
2025-09-01 16:45 ` Kees Cook
2 siblings, 1 reply; 12+ messages in thread
From: Randy Dunlap @ 2025-09-01 16:39 UTC (permalink / raw)
To: Kees Cook, Nathan Chancellor
Cc: Nicolas Schier, Jonathan Corbet, Masahiro Yamada, Arnd Bergmann,
Krzysztof Kozlowski, linux-kbuild, linux-doc, Miguel Ojeda,
Stephen Brennan, Marco Bonelli, Petr Vorel, linux-kernel,
linux-hardening
Hi Kees,
On 8/29/25 7:01 PM, Kees Cook wrote:
> During kernel option migrations (e.g. CONFIG_CFI_CLANG to CONFIG_CFI),
> existing .config files need to maintain backward compatibility while
> preventing deprecated options from appearing in newly generated
> configurations. This is challenging with existing Kconfig mechanisms
> because:
>
> 1. Simply removing old options breaks existing .config files.
> 2. Manually listing an option as "deprecated" leaves it needlessly
> visible and still writes them to new .config files.
> 3. Using any method to remove visibility (.e.g no 'prompt', 'if n',
> etc) prevents the option from being processed at all.
>
> Add a "transitional" attribute that creates symbols which are:
> - Processed during configuration (can influence other symbols' defaults)
> - Hidden from user menus (no prompts appear)
> - Omitted from newly written .config files (gets migrated)
> - Restricted to only having help sections (no defaults, selects, etc)
> making it truly just a "prior value pass-through" option.
>
> The transitional syntax requires a type argument and prevents type
> redefinition:
>
> config OLD_OPTION
> transitional bool
> help
> Transitional config for OLD_OPTION migration.
>
> config NEW_OPTION
> bool "New option"
> default OLD_OPTION
>
> This allows seamless migration: olddefconfig processes existing
> CONFIG_OLD_OPTION=y settings to enable CONFIG_NEW_OPTION=y, while
> CONFIG_OLD_OPTION is omitted from newly generated .config files.
>
> Implementation details:
> - Parser validates transitional symbols can only have help sections
> - Symbol visibility logic updated: usable = (visible != no || transitional)
> - Transitional symbols preserve user values during configuration
> - Type safety enforced to prevent redefinition after transitional declaration
> - Used distinct struct members instead of new flags for readability
> - Documentation added to show the usage
>
> Signed-off-by: Kees Cook <kees@kernel.org>
> ---
> With help from Claude Code to show me how to navigate the kconfig parser.
Are you (implicitly?) saying that all previous attempts at transitional
kconfig symbols have failed? If so, I just wasn't aware of that.
Or is there some new prime directive that requires this?
Thanks.
--
~Randy
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2] kconfig: Add transitional symbol attribute for migration support
2025-09-01 16:39 ` Randy Dunlap
@ 2025-09-01 16:45 ` Kees Cook
2025-09-01 16:54 ` Randy Dunlap
0 siblings, 1 reply; 12+ messages in thread
From: Kees Cook @ 2025-09-01 16:45 UTC (permalink / raw)
To: Randy Dunlap
Cc: Nathan Chancellor, Nicolas Schier, Jonathan Corbet,
Masahiro Yamada, Arnd Bergmann, Krzysztof Kozlowski, linux-kbuild,
linux-doc, Miguel Ojeda, Stephen Brennan, Marco Bonelli,
Petr Vorel, linux-kernel, linux-hardening
On Mon, Sep 01, 2025 at 09:39:46AM -0700, Randy Dunlap wrote:
> Are you (implicitly?) saying that all previous attempts at transitional
> kconfig symbols have failed? If so, I just wasn't aware of that.
I haven't found any way to do a "proper" CONFIG transition. I looked
through past transitions and they all left stuff visible. Is there a way
to actually do this with existing kconfig?
--
Kees Cook
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2] kconfig: Add transitional symbol attribute for migration support
2025-09-01 9:09 ` Jani Nikula
@ 2025-09-01 16:48 ` Kees Cook
0 siblings, 0 replies; 12+ messages in thread
From: Kees Cook @ 2025-09-01 16:48 UTC (permalink / raw)
To: Jani Nikula
Cc: Nathan Chancellor, Nicolas Schier, Jonathan Corbet,
Masahiro Yamada, Randy Dunlap, Arnd Bergmann, Krzysztof Kozlowski,
linux-kbuild, linux-doc, Miguel Ojeda, Stephen Brennan,
Marco Bonelli, Petr Vorel, linux-kernel, linux-hardening
On Mon, Sep 01, 2025 at 12:09:14PM +0300, Jani Nikula wrote:
> On Fri, 29 Aug 2025, Kees Cook <kees@kernel.org> wrote:
> > The transitional syntax requires a type argument and prevents type
> > redefinition:
> >
> > config OLD_OPTION
> > transitional bool
> > help
> > Transitional config for OLD_OPTION migration.
>
> How long do you think we'll need to keep the transitional config options
> around? Forever?
As with the "manual" transitions, it'd probably be until the next LTS is
released.
--
Kees Cook
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2] kconfig: Add transitional symbol attribute for migration support
2025-09-01 16:45 ` Kees Cook
@ 2025-09-01 16:54 ` Randy Dunlap
0 siblings, 0 replies; 12+ messages in thread
From: Randy Dunlap @ 2025-09-01 16:54 UTC (permalink / raw)
To: Kees Cook
Cc: Nathan Chancellor, Nicolas Schier, Jonathan Corbet,
Masahiro Yamada, Arnd Bergmann, Krzysztof Kozlowski, linux-kbuild,
linux-doc, Miguel Ojeda, Stephen Brennan, Marco Bonelli,
Petr Vorel, linux-kernel, linux-hardening
On 9/1/25 9:45 AM, Kees Cook wrote:
> On Mon, Sep 01, 2025 at 09:39:46AM -0700, Randy Dunlap wrote:
>> Are you (implicitly?) saying that all previous attempts at transitional
>> kconfig symbols have failed? If so, I just wasn't aware of that.
>
> I haven't found any way to do a "proper" CONFIG transition. I looked
> through past transitions and they all left stuff visible. Is there a way
> to actually do this with existing kconfig?
>
I don't know. I haven't looked as hard at it as you have.
I just didn't realize that there had been significant failures
that required kconfig code changes.
I'm just trying to understand. Carry on.
--
~Randy
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2] kconfig: Add transitional symbol attribute for migration support
2025-09-01 8:34 ` Vegard Nossum
@ 2025-09-01 16:56 ` Kees Cook
2025-09-01 18:20 ` Vegard Nossum
0 siblings, 1 reply; 12+ messages in thread
From: Kees Cook @ 2025-09-01 16:56 UTC (permalink / raw)
To: Vegard Nossum
Cc: Nathan Chancellor, Nicolas Schier, Jonathan Corbet,
Masahiro Yamada, Randy Dunlap, Arnd Bergmann, Krzysztof Kozlowski,
linux-kbuild, linux-doc, Miguel Ojeda, Stephen Brennan,
Marco Bonelli, Petr Vorel, linux-kernel, linux-hardening
On Mon, Sep 01, 2025 at 10:34:19AM +0200, Vegard Nossum wrote:
> Drive-by review... consider it more as "here's some stuff that could be
> worth looking at" rather than blocking in any way.
Thanks for looking at it!
>
> On 30/08/2025 04:01, Kees Cook wrote:
> > During kernel option migrations (e.g. CONFIG_CFI_CLANG to CONFIG_CFI),
> > existing .config files need to maintain backward compatibility while
> > preventing deprecated options from appearing in newly generated
> > configurations. This is challenging with existing Kconfig mechanisms
> > because:
> >
> > 1. Simply removing old options breaks existing .config files.
> > 2. Manually listing an option as "deprecated" leaves it needlessly
> > visible and still writes them to new .config files.
> > 3. Using any method to remove visibility (.e.g no 'prompt', 'if n',
> > etc) prevents the option from being processed at all.
> >
> > Add a "transitional" attribute that creates symbols which are:
> > - Processed during configuration (can influence other symbols' defaults)
> > - Hidden from user menus (no prompts appear)
> > - Omitted from newly written .config files (gets migrated)
> > - Restricted to only having help sections (no defaults, selects, etc)
> > making it truly just a "prior value pass-through" option.
> >
> > The transitional syntax requires a type argument and prevents type
> > redefinition:
> >
> > config OLD_OPTION
> > transitional bool
> > help
> > Transitional config for OLD_OPTION migration.
> >
> > config NEW_OPTION
> > bool "New option"
> > default OLD_OPTION
>
> Can you add this to scripts/kconfig/tests/ + both positive and negative
> tests? Tests are run with 'make testconfig' but (AFAICT) doesn't
> actually recompile config/mconf/etc. before running the tests, so small
> gotcha there.
Yes, I will get that added if people are generally happy with this
feature idea. :)
> > diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h
> > index fe2231e0e6a4..be51574d6c77 100644
> > --- a/scripts/kconfig/expr.h
> > +++ b/scripts/kconfig/expr.h
> > @@ -127,6 +127,21 @@ struct symbol {
> > /* SYMBOL_* flags */
> > int flags;
> > + /*
> > + * Transitional symbol - processed during configuration but hidden from
> > + * user in menus and omitted from newly written .config files. Used for
> > + * backward compatibility during config option migrations (e.g.,
> > + * CFI_CLANG → CFI). Transitional symbols can still influence default
> > + * expressions of other symbols.
> > + */
> > + bool transitional:1;
> > +
> > + /*
> > + * Symbol usability - calculated as (visible != no || transitional).
> > + * Determines if symbol can be used in expressions.
> > + */
> > + bool usable:1;
> > +
>
> It's a bit of a "red flag" to see bitfield bools just after an "int
> flags;" member... should these be SYMBOL_ flags?
>
> Speaking of SYMBOL_ flags, there's apparently one that controls whether
> a given symbol should be written out to .config:
Yeah, I mentioned this in the commit log, and maybe I just have to make
this not as easily readable? But you have a point about "usable" below...
> scripts/kconfig/expr.h:#define SYMBOL_WRITE 0x0200 /* write symbol to
> file (KCONFIG_CONFIG) */
>
> This seems like something you'd like to use somehow -- maybe simply
> clear it in sym_calc_value() if it's transitional? Similar to how it's
> done for choice values:
>
> if (sym_is_choice(sym))
> sym->flags &= ~SYMBOL_WRITE;
This is actually handled naturally as part of this logic:
> > if (sym->visible != no)
> > sym->flags |= SYMBOL_WRITE;
i.e. "usable" doesn't change SYMBOL_WRITE getting set.
> > @@ -205,6 +206,16 @@ config_option: T_PROMPT T_WORD_QUOTE if_expr T_EOL
> > printd(DEBUG_PARSE, "%s:%d:prompt\n", cur_filename, cur_lineno);
> > };
> > +config_option: T_TRANSITIONAL type T_EOL
> > +{
> > + if (current_entry->sym->type != S_UNKNOWN)
> > + yyerror("transitional type cannot be set after symbol type is already defined");
> > + menu_set_type($2);
> > + current_entry->sym->transitional = true;
> > + printd(DEBUG_PARSE, "%s:%d:transitional(%u)\n", cur_filename, cur_lineno,
> > + $2);
> > +};
>
> You could also consider making this an attribute similar to the
> "modules" flags and simplify:
>
> config_option: T_TRANSITIONAL T_EOL
> {
> current_entry->sym->transitional = true;
> printd(DEBUG_PARSE, "%s:%d:transitional\n", cur_filename,
> cur_lineno);
> };
>
> ...it would mean the config options look this way:
>
> config OLD_OPTION
> bool
> transitional
>
> (If not, menu_set_type() does already contain a check for whether the
> type has already been set.)
I went back and forth on how I wanted it to look and ultimately decided
it was awkward to say "use transitional but only with a type that
doesn't have a prompt". Instead it seemed better to have the type
explicitly set.
menu_set_type() does check already, but it's a warning only.
> > @@ -558,6 +606,9 @@ void conf_parse(const char *name)
> > if (menu->sym && sym_check_deps(menu->sym))
> > yynerrs++;
> > + if (transitional_check_sanity(menu))
> > + yynerrs++;
> > +
> > if (menu->sym && sym_is_choice(menu->sym)) {
> > menu_for_each_sub_entry(child, menu)
> > if (child->sym && choice_check_sanity(child))
> > diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
> > index 26ab10c0fd76..b822c0c897e5 100644
> > --- a/scripts/kconfig/symbol.c
> > +++ b/scripts/kconfig/symbol.c
> > @@ -447,6 +447,9 @@ void sym_calc_value(struct symbol *sym)
> > if (sym->visible != no)
> > sym->flags |= SYMBOL_WRITE;
> > + /* Calculate usable flag */
> > + sym->usable = (sym->visible != no || sym->transitional);
> > +
>
> Is this actually ever used outside of this function? (IOW could this
> just be a local variable instead of a sym-> flag/member?) Or do we need
> to set it here because sym_calc_value() calls itself recursively? To me
> it looks like we only ever access sym->usable for the "sym" that was
> passed as an argument to the function.
Ah! It's not any more, no. I had an earlier version where I was
examining it elsewhere, but yeah, this is only needed here.
>
> > /* set default if recursively called */
> > sym->curr = newval;
> > @@ -459,13 +462,15 @@ void sym_calc_value(struct symbol *sym)
> > sym_calc_choice(choice_menu);
> > newval.tri = sym->curr.tri;
> > } else {
> > - if (sym->visible != no) {
> > + if (sym->usable) {
> > /* if the symbol is visible use the user value
> > * if available, otherwise try the default value
> > */
> > if (sym_has_value(sym)) {
> > + tristate value = sym->transitional ?
> > + sym->def[S_DEF_USER].tri : sym->visible;
> > newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri,
> > - sym->visible);
> > + value);
>
> This looks a bit odd to me. Just thinking out loud: your new logic is
> there to be able to use a value even though it's not visible. In the
> case where it's transitional you use the .config value instead of the
> condition that makes it visible.
>
> Could you simply change sym_calc_visibility() instead to always return
> 'yes' when the symbol is transitional? Wouldn't that simplify everything
> in sym_calc_value()?
It's a tristate, so "m" is also possible besides "y". (sym->visible is
also a tristate. :)
I will send a v3 with better bit fields.
-Kees
--
Kees Cook
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2] kconfig: Add transitional symbol attribute for migration support
2025-09-01 16:56 ` Kees Cook
@ 2025-09-01 18:20 ` Vegard Nossum
2025-09-01 18:31 ` Kees Cook
0 siblings, 1 reply; 12+ messages in thread
From: Vegard Nossum @ 2025-09-01 18:20 UTC (permalink / raw)
To: Kees Cook
Cc: Nathan Chancellor, Nicolas Schier, Jonathan Corbet,
Masahiro Yamada, Randy Dunlap, Arnd Bergmann, Krzysztof Kozlowski,
linux-kbuild, linux-doc, Miguel Ojeda, Stephen Brennan,
Marco Bonelli, Petr Vorel, linux-kernel, linux-hardening
On 01/09/2025 18:56, Kees Cook wrote:
>>> @@ -459,13 +462,15 @@ void sym_calc_value(struct symbol *sym)
>>> sym_calc_choice(choice_menu);
>>> newval.tri = sym->curr.tri;
>>> } else {
>>> - if (sym->visible != no) {
>>> + if (sym->usable) {
>>> /* if the symbol is visible use the user value
>>> * if available, otherwise try the default value
>>> */
>>> if (sym_has_value(sym)) {
>>> + tristate value = sym->transitional ?
>>> + sym->def[S_DEF_USER].tri : sym->visible;
>>> newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri,
>>> - sym->visible);
>>> + value);
>> This looks a bit odd to me. Just thinking out loud: your new logic is
>> there to be able to use a value even though it's not visible. In the
>> case where it's transitional you use the .config value instead of the
>> condition that makes it visible.
>>
>> Could you simply change sym_calc_visibility() instead to always return
>> 'yes' when the symbol is transitional? Wouldn't that simplify everything
>> in sym_calc_value()?
> It's a tristate, so "m" is also possible besides "y". (sym->visible is
> also a tristate. 🙂
That would be fine, right?
We'd pass the if (sym->visible != no) check... we'd do the
newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri, sym->visible);
EXPR_AND() is basically min() (with n=0, m=1, y=2), so effectively it
would end up doing
newval.tri = min(sym->def[S_DEF_USER].tri, 2);
which is the same as
newval.tri = sym->def[S_DEF_USER].tri;
That's what your code is currently doing too, but in a much more
roundabout way.
Vegard
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2] kconfig: Add transitional symbol attribute for migration support
2025-09-01 18:20 ` Vegard Nossum
@ 2025-09-01 18:31 ` Kees Cook
2025-09-01 18:44 ` Vegard Nossum
0 siblings, 1 reply; 12+ messages in thread
From: Kees Cook @ 2025-09-01 18:31 UTC (permalink / raw)
To: Vegard Nossum
Cc: Nathan Chancellor, Nicolas Schier, Jonathan Corbet,
Masahiro Yamada, Randy Dunlap, Arnd Bergmann, Krzysztof Kozlowski,
linux-kbuild, linux-doc, Miguel Ojeda, Stephen Brennan,
Marco Bonelli, Petr Vorel, linux-kernel, linux-hardening
On Mon, Sep 01, 2025 at 08:20:18PM +0200, Vegard Nossum wrote:
>
> On 01/09/2025 18:56, Kees Cook wrote:
> > > > @@ -459,13 +462,15 @@ void sym_calc_value(struct symbol *sym)
> > > > sym_calc_choice(choice_menu);
> > > > newval.tri = sym->curr.tri;
> > > > } else {
> > > > - if (sym->visible != no) {
> > > > + if (sym->usable) {
> > > > /* if the symbol is visible use the user value
> > > > * if available, otherwise try the default value
> > > > */
> > > > if (sym_has_value(sym)) {
> > > > + tristate value = sym->transitional ?
> > > > + sym->def[S_DEF_USER].tri : sym->visible;
> > > > newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri,
> > > > - sym->visible);
> > > > + value);
> > > This looks a bit odd to me. Just thinking out loud: your new logic is
> > > there to be able to use a value even though it's not visible. In the
> > > case where it's transitional you use the .config value instead of the
> > > condition that makes it visible.
> > >
> > > Could you simply change sym_calc_visibility() instead to always return
> > > 'yes' when the symbol is transitional? Wouldn't that simplify everything
> > > in sym_calc_value()?
> > It's a tristate, so "m" is also possible besides "y". (sym->visible is
> > also a tristate. 🙂
>
> That would be fine, right?
>
> We'd pass the if (sym->visible != no) check... we'd do the
>
> newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri, sym->visible);
>
> EXPR_AND() is basically min() (with n=0, m=1, y=2), so effectively it
> would end up doing
>
> newval.tri = min(sym->def[S_DEF_USER].tri, 2);
>
> which is the same as
>
> newval.tri = sym->def[S_DEF_USER].tri;
>
> That's what your code is currently doing too, but in a much more
> roundabout way.
Right, it was this:
newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri, sym->visible);
But I made it effectively:
if (sym->transitional)
newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri, sym->def[S_DEF_USER].tri);
else
newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri, sym->visible);
That first "if" is kind of pointless. I just sent the v3 before I saw
this email. :P
I was trying to avoid yet more indentation, but I could change it to:
if (sym->transitional)
newval.tri = sym->def[S_DEF_USER].tri;
else
newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri,
sym->visible);
?
--
Kees Cook
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2] kconfig: Add transitional symbol attribute for migration support
2025-09-01 18:31 ` Kees Cook
@ 2025-09-01 18:44 ` Vegard Nossum
2025-09-04 2:51 ` Kees Cook
0 siblings, 1 reply; 12+ messages in thread
From: Vegard Nossum @ 2025-09-01 18:44 UTC (permalink / raw)
To: Kees Cook
Cc: Nathan Chancellor, Nicolas Schier, Jonathan Corbet,
Masahiro Yamada, Randy Dunlap, Arnd Bergmann, Krzysztof Kozlowski,
linux-kbuild, linux-doc, Miguel Ojeda, Stephen Brennan,
Marco Bonelli, Petr Vorel, linux-kernel, linux-hardening
On 01/09/2025 20:31, Kees Cook wrote:
> On Mon, Sep 01, 2025 at 08:20:18PM +0200, Vegard Nossum wrote:
>>
>> On 01/09/2025 18:56, Kees Cook wrote:
>>>>> @@ -459,13 +462,15 @@ void sym_calc_value(struct symbol *sym)
>>>>> sym_calc_choice(choice_menu);
>>>>> newval.tri = sym->curr.tri;
>>>>> } else {
>>>>> - if (sym->visible != no) {
>>>>> + if (sym->usable) {
>>>>> /* if the symbol is visible use the user value
>>>>> * if available, otherwise try the default value
>>>>> */
>>>>> if (sym_has_value(sym)) {
>>>>> + tristate value = sym->transitional ?
>>>>> + sym->def[S_DEF_USER].tri : sym->visible;
>>>>> newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri,
>>>>> - sym->visible);
>>>>> + value);
>>>> This looks a bit odd to me. Just thinking out loud: your new logic is
>>>> there to be able to use a value even though it's not visible. In the
>>>> case where it's transitional you use the .config value instead of the
>>>> condition that makes it visible.
>>>>
>>>> Could you simply change sym_calc_visibility() instead to always return
>>>> 'yes' when the symbol is transitional? Wouldn't that simplify everything
>>>> in sym_calc_value()?
>>> It's a tristate, so "m" is also possible besides "y". (sym->visible is
>>> also a tristate. 🙂
>>
>> That would be fine, right?
>>
>> We'd pass the if (sym->visible != no) check... we'd do the
>>
>> newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri, sym->visible);
>>
>> EXPR_AND() is basically min() (with n=0, m=1, y=2), so effectively it
>> would end up doing
>>
>> newval.tri = min(sym->def[S_DEF_USER].tri, 2);
>>
>> which is the same as
>>
>> newval.tri = sym->def[S_DEF_USER].tri;
>>
>> That's what your code is currently doing too, but in a much more
>> roundabout way.
>
> Right, it was this:
>
> newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri, sym->visible);
>
> But I made it effectively:
>
> if (sym->transitional)
> newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri, sym->def[S_DEF_USER].tri);
> else
> newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri, sym->visible);
>
> That first "if" is kind of pointless. I just sent the v3 before I saw
> this email. :P
>
> I was trying to avoid yet more indentation, but I could change it to:
>
> if (sym->transitional)
> newval.tri = sym->def[S_DEF_USER].tri;
> else
> newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri,
> sym->visible);
>
> ?
>
If you change sym_calc_visibility() to always return 'yes' for
transitional values then I don't think you need to touch
sym_calc_value() at all.
Vegard
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v2] kconfig: Add transitional symbol attribute for migration support
2025-09-01 18:44 ` Vegard Nossum
@ 2025-09-04 2:51 ` Kees Cook
0 siblings, 0 replies; 12+ messages in thread
From: Kees Cook @ 2025-09-04 2:51 UTC (permalink / raw)
To: Vegard Nossum
Cc: Nathan Chancellor, Nicolas Schier, Jonathan Corbet,
Masahiro Yamada, Randy Dunlap, Arnd Bergmann, Krzysztof Kozlowski,
linux-kbuild, linux-doc, Miguel Ojeda, Stephen Brennan,
Marco Bonelli, Petr Vorel, linux-kernel, linux-hardening
On Mon, Sep 01, 2025 at 08:44:56PM +0200, Vegard Nossum wrote:
> If you change sym_calc_visibility() to always return 'yes' for
> transitional values then I don't think you need to touch
> sym_calc_value() at all.
Hm, it looks like sym_calc_visibility() doesn't strictly just look at
visibility. And visibility seems to "last"? And I think the "tri" still
can't just be "yes", don't we need the other stuff handled?
Do you see a way to do it how you're suggesting? And now I wrote the
regression tests so we can test any alternatives! ;)
--
Kees Cook
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2025-09-04 2:51 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-30 2:01 [PATCH v2] kconfig: Add transitional symbol attribute for migration support Kees Cook
2025-09-01 8:34 ` Vegard Nossum
2025-09-01 16:56 ` Kees Cook
2025-09-01 18:20 ` Vegard Nossum
2025-09-01 18:31 ` Kees Cook
2025-09-01 18:44 ` Vegard Nossum
2025-09-04 2:51 ` Kees Cook
2025-09-01 9:09 ` Jani Nikula
2025-09-01 16:48 ` Kees Cook
2025-09-01 16:39 ` Randy Dunlap
2025-09-01 16:45 ` Kees Cook
2025-09-01 16:54 ` Randy Dunlap
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).