tools/x86/kcpuid: Fix error handling

[ Upstream commit 116edfe173d0c59ec2aa87fb91f2f31d477b61b3 ]

Error handling in kcpuid is unreliable.  On malloc() failures, the code
prints an error then just goes on.  The error messages are also printed
to standard output instead of standard error.

Use err() and errx() from <err.h> to direct all error messages to
standard error and automatically exit the program.  Use err() to include
the errno information, and errx() otherwise.  Use warnx() for warnings.

While at it, alphabetically reorder the header includes.

[ mingo: Fix capitalization in the help text while at it. ]

Fixes: c6b2f240bf ("tools/x86: Add a kcpuid tool to show raw CPU features")
Reported-by: Remington Brasga <rbrasga@uci.edu>
Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Link: https://lore.kernel.org/r/20250324142042.29010-2-darwi@linutronix.de
Closes: https://lkml.kernel.org/r/20240926223557.2048-1-rbrasga@uci.edu
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Ahmed S. Darwish
2025-03-24 15:20:22 +01:00
committed by Greg Kroah-Hartman
parent e9019e2214
commit cc5cd8a171

View File

@@ -1,11 +1,12 @@
// SPDX-License-Identifier: GPL-2.0
#define _GNU_SOURCE
#include <stdio.h>
#include <err.h>
#include <getopt.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#define min(a, b) (((a) < (b)) ? (a) : (b))
@@ -156,14 +157,14 @@ static bool cpuid_store(struct cpuid_range *range, u32 f, int subleaf,
if (!func->leafs) {
func->leafs = malloc(sizeof(struct subleaf));
if (!func->leafs)
perror("malloc func leaf");
err(EXIT_FAILURE, NULL);
func->nr = 1;
} else {
s = func->nr;
func->leafs = realloc(func->leafs, (s + 1) * sizeof(*leaf));
if (!func->leafs)
perror("realloc f->leafs");
err(EXIT_FAILURE, NULL);
func->nr++;
}
@@ -222,7 +223,7 @@ struct cpuid_range *setup_cpuid_range(u32 input_eax)
range = malloc(sizeof(struct cpuid_range));
if (!range)
perror("malloc range");
err(EXIT_FAILURE, NULL);
if (input_eax & 0x80000000)
range->is_ext = true;
@@ -231,7 +232,7 @@ struct cpuid_range *setup_cpuid_range(u32 input_eax)
range->funcs = malloc(sizeof(struct cpuid_func) * idx_func);
if (!range->funcs)
perror("malloc range->funcs");
err(EXIT_FAILURE, NULL);
range->nr = idx_func;
memset(range->funcs, 0, sizeof(struct cpuid_func) * idx_func);
@@ -387,8 +388,8 @@ static int parse_line(char *line)
return 0;
err_exit:
printf("Warning: wrong line format:\n");
printf("\tline[%d]: %s\n", flines, line);
warnx("Wrong line format:\n"
"\tline[%d]: %s", flines, line);
return -1;
}
@@ -410,10 +411,8 @@ static void parse_text(void)
file = fopen("./cpuid.csv", "r");
}
if (!file) {
printf("Fail to open '%s'\n", filename);
return;
}
if (!file)
err(EXIT_FAILURE, "%s", filename);
while (1) {
ret = getline(&line, &len, file);
@@ -521,7 +520,7 @@ static inline struct cpuid_func *index_to_func(u32 index)
func_idx = index & 0xffff;
if ((func_idx + 1) > (u32)range->nr) {
printf("ERR: invalid input index (0x%x)\n", index);
warnx("Invalid input index (0x%x)", index);
return NULL;
}
return &range->funcs[func_idx];
@@ -553,7 +552,7 @@ static void show_info(void)
return;
}
printf("ERR: invalid input subleaf (0x%x)\n", user_sub);
warnx("Invalid input subleaf (0x%x)", user_sub);
}
show_func(func);
@@ -584,15 +583,15 @@ static void setup_platform_cpuid(void)
static void usage(void)
{
printf("kcpuid [-abdfhr] [-l leaf] [-s subleaf]\n"
"\t-a|--all Show both bit flags and complex bit fields info\n"
"\t-b|--bitflags Show boolean flags only\n"
"\t-d|--detail Show details of the flag/fields (default)\n"
"\t-f|--flags Specify the cpuid csv file\n"
"\t-h|--help Show usage info\n"
"\t-l|--leaf=index Specify the leaf you want to check\n"
"\t-r|--raw Show raw cpuid data\n"
"\t-s|--subleaf=sub Specify the subleaf you want to check\n"
warnx("kcpuid [-abdfhr] [-l leaf] [-s subleaf]\n"
"\t-a|--all Show both bit flags and complex bit fields info\n"
"\t-b|--bitflags Show boolean flags only\n"
"\t-d|--detail Show details of the flag/fields (default)\n"
"\t-f|--flags Specify the CPUID CSV file\n"
"\t-h|--help Show usage info\n"
"\t-l|--leaf=index Specify the leaf you want to check\n"
"\t-r|--raw Show raw CPUID data\n"
"\t-s|--subleaf=sub Specify the subleaf you want to check"
);
}
@@ -643,7 +642,7 @@ static int parse_options(int argc, char *argv[])
user_sub = strtoul(optarg, NULL, 0);
break;
default:
printf("%s: Invalid option '%c'\n", argv[0], optopt);
warnx("Invalid option '%c'", optopt);
return -1;
}