lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <7bca36d46dab04667aa595623fd0966385ee4658@intel.com>
Date: Mon, 01 Sep 2025 12:09:14 +0300
From: Jani Nikula <jani.nikula@...ux.intel.com>
To: Kees Cook <kees@...nel.org>, Nathan Chancellor <nathan@...nel.org>
Cc: Kees Cook <kees@...nel.org>, Nicolas Schier <nicolas.schier@...ux.dev>,
 Jonathan Corbet <corbet@....net>, Masahiro Yamada <masahiroy@...nel.org>,
 Randy Dunlap <rdunlap@...radead.org>, Arnd Bergmann <arnd@...db.de>,
 Krzysztof Kozlowski <krzysztof.kozlowski@...aro.org>,
 linux-kbuild@...r.kernel.org, linux-doc@...r.kernel.org, Miguel Ojeda
 <ojeda@...nel.org>, Stephen Brennan <stephen.s.brennan@...cle.com>, Marco
 Bonelli <marco@...eim.net>, Petr Vorel <pvorel@...e.cz>,
 linux-kernel@...r.kernel.org, linux-hardening@...r.kernel.org
Subject: Re: [PATCH v2] kconfig: Add transitional symbol attribute for
 migration support

On Fri, 29 Aug 2025, Kees Cook <kees@...nel.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@...nel.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@...nel.org>
> Cc: Nicolas Schier <nicolas.schier@...ux.dev>
> Cc: Jonathan Corbet <corbet@....net>
> Cc: Masahiro Yamada <masahiroy@...nel.org>
> Cc: Randy Dunlap <rdunlap@...radead.org>
> Cc: Arnd Bergmann <arnd@...db.de>
> Cc: Krzysztof Kozlowski <krzysztof.kozlowski@...aro.org>
> Cc: <linux-kbuild@...r.kernel.org>
> Cc: <linux-doc@...r.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

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ