[PATCH v6 2/3] x86/cpu: Check if feature string is non-zero

Maciej Wieczor-Retman posted 3 patches 1 month, 1 week ago
There is a newer version of this series
[PATCH v6 2/3] x86/cpu: Check if feature string is non-zero
Posted by Maciej Wieczor-Retman 1 month, 1 week ago
From: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>

In filter_cpuid_features, x86_cap_flags[] is read, but it's not verified
whether the string is non-zero which could lead to unwanted output.

In two more places there are open coded paths that try to retrieve a
feature string, and if there isn't one, the feature word and bit are
returned instead. While correcting filter_cpuid_features() with a helper
it's trivial to also clean up these open coded cases.

Signed-off-by: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
---
Changelog v6:
- Remove parts of the patch message that are redundant and just copy
  what's visible in the diff.
- Redo the helper to use an external char buffer instead of a local
  static string.

 arch/x86/kernel/cpu/common.c     | 26 +++++++++++++++++++++-----
 arch/x86/kernel/cpu/cpuid-deps.c | 20 +++-----------------
 include/linux/cpu.h              |  2 ++
 3 files changed, 26 insertions(+), 22 deletions(-)

diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 8d12c5722245..44ae2f936395 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -675,6 +675,7 @@ cpuid_dependent_features[] = {
 static void filter_cpuid_features(struct cpuinfo_x86 *c, bool warn)
 {
 	const struct cpuid_dependent_feature *df;
+	char feature_buf[16];
 
 	for (df = cpuid_dependent_features; df->feature; df++) {
 
@@ -697,7 +698,7 @@ static void filter_cpuid_features(struct cpuinfo_x86 *c, bool warn)
 			continue;
 
 		pr_warn("CPU: CPU feature %s disabled, no CPUID level 0x%x\n",
-			x86_cap_flags[df->feature], df->level);
+			x86_cap_name(df->feature, feature_buf), df->level);
 	}
 }
 
@@ -1631,6 +1632,7 @@ static inline bool parse_set_clear_cpuid(char *arg, bool set)
 
 	while (arg) {
 		bool found __maybe_unused = false;
+		char name_buf[16];
 		unsigned int bit;
 
 		opt = strsep(&arg, ",");
@@ -1651,10 +1653,7 @@ static inline bool parse_set_clear_cpuid(char *arg, bool set)
 					setup_clear_cpu_cap(bit);
 				}
 				/* empty-string, i.e., ""-defined feature flags */
-				if (!x86_cap_flags[bit])
-					pr_cont(" %d:%d\n", bit >> 5, bit & 31);
-				else
-					pr_cont(" %s\n", x86_cap_flags[bit]);
+				pr_cont(" %s\n", x86_cap_name(bit, name_buf));
 
 				taint++;
 			}
@@ -1972,6 +1971,23 @@ static void generic_identify(struct cpuinfo_x86 *c)
 #endif
 }
 
+const char *x86_cap_name(unsigned int bit, char *buf)
+{
+	unsigned int word = bit >> 5;
+	const char *name = NULL;
+
+	if (likely(word < NCAPINTS))
+		name = x86_cap_flags[bit];
+	else if (likely(word < NCAPINTS + NBUGINTS))
+		name = x86_bug_flags[bit - 32 * NCAPINTS];
+
+	if (name)
+		return name;
+
+	snprintf(buf, sizeof(buf), "%u:%u", word, bit & 31);
+	return buf;
+}
+
 /*
  * This does the hard work of actually picking apart the CPU stuff...
  */
diff --git a/arch/x86/kernel/cpu/cpuid-deps.c b/arch/x86/kernel/cpu/cpuid-deps.c
index 146f6f8b0650..7fad18e7d2eb 100644
--- a/arch/x86/kernel/cpu/cpuid-deps.c
+++ b/arch/x86/kernel/cpu/cpuid-deps.c
@@ -2,6 +2,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/cpu.h>
 #include <asm/cpufeature.h>
 
 struct cpuid_dep {
@@ -156,21 +157,6 @@ void setup_clear_cpu_cap(unsigned int feature)
 	do_clear_cpu_cap(NULL, feature);
 }
 
-/*
- * Return the feature "name" if available, otherwise return
- * the X86_FEATURE_* numerals to make it easier to identify
- * the feature.
- */
-static const char *x86_feature_name(unsigned int feature, char *buf)
-{
-	if (x86_cap_flags[feature])
-		return x86_cap_flags[feature];
-
-	snprintf(buf, 16, "%d*32+%2d", feature / 32, feature % 32);
-
-	return buf;
-}
-
 void check_cpufeature_deps(struct cpuinfo_x86 *c)
 {
 	char feature_buf[16], depends_buf[16];
@@ -185,8 +171,8 @@ void check_cpufeature_deps(struct cpuinfo_x86 *c)
 			 */
 			pr_warn_once("x86 CPU feature dependency check failure: CPU%d has '%s' enabled but '%s' disabled. Kernel might be fine, but no guarantees.\n",
 				     smp_processor_id(),
-				     x86_feature_name(d->feature, feature_buf),
-				     x86_feature_name(d->depends, depends_buf));
+				     x86_cap_name(d->feature, feature_buf),
+				     x86_cap_name(d->depends, depends_buf));
 		}
 	}
 }
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index 487b3bf2e1ea..30e5a92430da 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -229,4 +229,6 @@ static inline bool cpu_attack_vector_mitigated(enum cpu_attack_vectors v)
 #define smt_mitigations SMT_MITIGATIONS_OFF
 #endif
 
+const char *x86_cap_name(unsigned int bit, char *buf);
+
 #endif /* _LINUX_CPU_H_ */
-- 
2.53.0
Re: [PATCH v6 2/3] x86/cpu: Check if feature string is non-zero
Posted by kernel test robot 1 month, 1 week ago
Hi Maciej,

kernel test robot noticed the following build warnings:

[auto build test WARNING on tip/x86/core]
[also build test WARNING on tip/smp/core v6.19]
[cannot apply to peterz-queue/sched/core linus/master next-20260220]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Maciej-Wieczor-Retman/x86-cpu-Clear-feature-bits-disabled-at-compile-time/20260220-204916
base:   tip/x86/core
patch link:    https://lore.kernel.org/r/bc0eebc8310acfae28a73e3780a67d721c739b89.1771590895.git.m.wieczorretman%40pm.me
patch subject: [PATCH v6 2/3] x86/cpu: Check if feature string is non-zero
config: x86_64-randconfig-r051-20260221 (https://download.01.org/0day-ci/archive/20260221/202602210429.MpUz6J91-lkp@intel.com/config)
compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202602210429.MpUz6J91-lkp@intel.com/

cocci warnings: (new ones prefixed by >>)
>> arch/x86/kernel/cpu/common.c:1987:15-21: ERROR: application of sizeof to pointer

vim +1987 arch/x86/kernel/cpu/common.c

  1973	
  1974	const char *x86_cap_name(unsigned int bit, char *buf)
  1975	{
  1976		unsigned int word = bit >> 5;
  1977		const char *name = NULL;
  1978	
  1979		if (likely(word < NCAPINTS))
  1980			name = x86_cap_flags[bit];
  1981		else if (likely(word < NCAPINTS + NBUGINTS))
  1982			name = x86_bug_flags[bit - 32 * NCAPINTS];
  1983	
  1984		if (name)
  1985			return name;
  1986	
> 1987		snprintf(buf, sizeof(buf), "%u:%u", word, bit & 31);
  1988		return buf;
  1989	}
  1990	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Re: [PATCH v6 2/3] x86/cpu: Check if feature string is non-zero
Posted by kernel test robot 1 month, 1 week ago
Hi Maciej,

kernel test robot noticed the following build warnings:

[auto build test WARNING on tip/x86/core]
[also build test WARNING on tip/smp/core v6.19]
[cannot apply to peterz-queue/sched/core linus/master next-20260219]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Maciej-Wieczor-Retman/x86-cpu-Clear-feature-bits-disabled-at-compile-time/20260220-204916
base:   tip/x86/core
patch link:    https://lore.kernel.org/r/bc0eebc8310acfae28a73e3780a67d721c739b89.1771590895.git.m.wieczorretman%40pm.me
patch subject: [PATCH v6 2/3] x86/cpu: Check if feature string is non-zero
config: x86_64-randconfig-003-20260220 (https://download.01.org/0day-ci/archive/20260221/202602210027.MJpPrtwD-lkp@intel.com/config)
compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260221/202602210027.MJpPrtwD-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202602210027.MJpPrtwD-lkp@intel.com/

All warnings (new ones prefixed by >>):

   arch/x86/kernel/cpu/common.c: In function 'x86_cap_name':
>> arch/x86/kernel/cpu/common.c:1987:29: warning: argument to 'sizeof' in 'snprintf' call is the same expression as the destination; did you mean to provide an explicit length? [-Wsizeof-pointer-memaccess]
    1987 |         snprintf(buf, sizeof(buf), "%u:%u", word, bit & 31);
         |                             ^
>> arch/x86/kernel/cpu/common.c:1987:37: warning: '%u' directive output may be truncated writing between 1 and 9 bytes into a region of size 8 [-Wformat-truncation=]
    1987 |         snprintf(buf, sizeof(buf), "%u:%u", word, bit & 31);
         |                                     ^~
   arch/x86/kernel/cpu/common.c:1987:36: note: directive argument in the range [0, 134217727]
    1987 |         snprintf(buf, sizeof(buf), "%u:%u", word, bit & 31);
         |                                    ^~~~~~~
   arch/x86/kernel/cpu/common.c:1987:36: note: directive argument in the range [0, 31]
   arch/x86/kernel/cpu/common.c:1987:9: note: 'snprintf' output between 4 and 13 bytes into a destination of size 8
    1987 |         snprintf(buf, sizeof(buf), "%u:%u", word, bit & 31);
         |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


vim +1987 arch/x86/kernel/cpu/common.c

  1973	
  1974	const char *x86_cap_name(unsigned int bit, char *buf)
  1975	{
  1976		unsigned int word = bit >> 5;
  1977		const char *name = NULL;
  1978	
  1979		if (likely(word < NCAPINTS))
  1980			name = x86_cap_flags[bit];
  1981		else if (likely(word < NCAPINTS + NBUGINTS))
  1982			name = x86_bug_flags[bit - 32 * NCAPINTS];
  1983	
  1984		if (name)
  1985			return name;
  1986	
> 1987		snprintf(buf, sizeof(buf), "%u:%u", word, bit & 31);
  1988		return buf;
  1989	}
  1990	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Re: [PATCH v6 2/3] x86/cpu: Check if feature string is non-zero
Posted by Maciej Wieczor-Retman 1 month, 1 week ago
I'll replace the sizeof(buf) with 16 for the next version.

-- 
Kind regards
Maciej Wieczór-Retman

On 2026-02-21 at 00:19:59 +0800, kernel test robot wrote:
>Hi Maciej,
>
>kernel test robot noticed the following build warnings:
>
>[auto build test WARNING on tip/x86/core]
>[also build test WARNING on tip/smp/core v6.19]
>[cannot apply to peterz-queue/sched/core linus/master next-20260219]
>[If your patch is applied to the wrong git tree, kindly drop us a note.
>And when submitting patch, we suggest to use '--base' as documented in
>https://git-scm.com/docs/git-format-patch#_base_tree_information]
>
>url:    https://github.com/intel-lab-lkp/linux/commits/Maciej-Wieczor-Retman/x86-cpu-Clear-feature-bits-disabled-at-compile-time/20260220-204916
>base:   tip/x86/core
>patch link:    https://lore.kernel.org/r/bc0eebc8310acfae28a73e3780a67d721c739b89.1771590895.git.m.wieczorretman%40pm.me
>patch subject: [PATCH v6 2/3] x86/cpu: Check if feature string is non-zero
>config: x86_64-randconfig-003-20260220 (https://download.01.org/0day-ci/archive/20260221/202602210027.MJpPrtwD-lkp@intel.com/config)
>compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
>reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260221/202602210027.MJpPrtwD-lkp@intel.com/reproduce)
>
>If you fix the issue in a separate patch/commit (i.e. not just a new version of
>the same patch/commit), kindly add following tags
>| Reported-by: kernel test robot <lkp@intel.com>
>| Closes: https://lore.kernel.org/oe-kbuild-all/202602210027.MJpPrtwD-lkp@intel.com/
>
>All warnings (new ones prefixed by >>):
>
>   arch/x86/kernel/cpu/common.c: In function 'x86_cap_name':
>>> arch/x86/kernel/cpu/common.c:1987:29: warning: argument to 'sizeof' in 'snprintf' call is the same expression as the destination; did you mean to provide an explicit length? [-Wsizeof-pointer-memaccess]
>    1987 |         snprintf(buf, sizeof(buf), "%u:%u", word, bit & 31);
>         |                             ^
>>> arch/x86/kernel/cpu/common.c:1987:37: warning: '%u' directive output may be truncated writing between 1 and 9 bytes into a region of size 8 [-Wformat-truncation=]
>    1987 |         snprintf(buf, sizeof(buf), "%u:%u", word, bit & 31);
>         |                                     ^~
>   arch/x86/kernel/cpu/common.c:1987:36: note: directive argument in the range [0, 134217727]
>    1987 |         snprintf(buf, sizeof(buf), "%u:%u", word, bit & 31);
>         |                                    ^~~~~~~
>   arch/x86/kernel/cpu/common.c:1987:36: note: directive argument in the range [0, 31]
>   arch/x86/kernel/cpu/common.c:1987:9: note: 'snprintf' output between 4 and 13 bytes into a destination of size 8
>    1987 |         snprintf(buf, sizeof(buf), "%u:%u", word, bit & 31);
>         |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>
>
>vim +1987 arch/x86/kernel/cpu/common.c
>
>  1973
>  1974	const char *x86_cap_name(unsigned int bit, char *buf)
>  1975	{
>  1976		unsigned int word = bit >> 5;
>  1977		const char *name = NULL;
>  1978
>  1979		if (likely(word < NCAPINTS))
>  1980			name = x86_cap_flags[bit];
>  1981		else if (likely(word < NCAPINTS + NBUGINTS))
>  1982			name = x86_bug_flags[bit - 32 * NCAPINTS];
>  1983
>  1984		if (name)
>  1985			return name;
>  1986
>> 1987		snprintf(buf, sizeof(buf), "%u:%u", word, bit & 31);
>  1988		return buf;
>  1989	}
>  1990
>
>--
>0-DAY CI Kernel Test Service
>https://github.com/intel/lkp-tests/wiki