From 77ce01fb93219990b4229ab20ddc010d93b18ce3 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Mon, 18 May 2026 08:58:09 +0200 Subject: [PATCH] x86/mwait-idle: Add C-states validation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add validation for C-states specified via the "table=" module parameter. Treat this module parameter as untrusted input and validate it thoroughly. Signed-off-by: Artem Bityutskiy Link: https://patch.msgid.link/20251216080402.156988-4-dedekind1@gmail.com Signed-off-by: Rafael J. Wysocki Origin: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git be6a150829b3 Add __init to validate_cmdline_cstate(). Other adjustments to fit our env. Signed-off-by: Jan Beulich Acked-by: Roger Pau Monné Release-Acked-by: Oleksii Kurochko --- xen/arch/x86/cpu/mwait-idle.c | 55 +++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/xen/arch/x86/cpu/mwait-idle.c b/xen/arch/x86/cpu/mwait-idle.c index 4d5223d9d5..735ba961a9 100644 --- a/xen/arch/x86/cpu/mwait-idle.c +++ b/xen/arch/x86/cpu/mwait-idle.c @@ -72,6 +72,11 @@ boolean_param("mwait-idle", opt_mwait_idle); /* The maximum allowed length for the 'table' module parameter */ #define MAX_CMDLINE_TABLE_LEN 256 +/* Maximum allowed C-state latency */ +#define MAX_CMDLINE_LATENCY_US (5 * 1000 /* USEC_PER_MSEC */) +/* Maximum allowed C-state target residency */ +#define MAX_CMDLINE_RESIDENCY_US (100 * 1000 /* USEC_PER_MSEC */) + static char cmdline_table_str[MAX_CMDLINE_TABLE_LEN] __initdata; string_param("mwait-idle.table", cmdline_table_str); @@ -1589,6 +1594,41 @@ static char *__init get_cmdline_field(char *args, char **field, char sep) return args + i + 1; } +/** + * validate_cmdline_cstate - Validate a C-state from cmdline. + * @state: The C-state to validate. + * @prev_state: The previous C-state in the table or NULL. + * + * Return: 0 if the C-state is valid or -EINVAL otherwise. + */ +static int __init validate_cmdline_cstate(const struct cpuidle_state *state, + const struct cpuidle_state *prev_state) +{ + if (state->exit_latency == 0) + /* Exit latency 0 can only be used for the POLL state */ + return -EINVAL; + + if (state->exit_latency > MAX_CMDLINE_LATENCY_US) + return -EINVAL; + + if (state->target_residency > MAX_CMDLINE_RESIDENCY_US) + return -EINVAL; + + if (state->target_residency < state->exit_latency) + return -EINVAL; + + if (!prev_state) + return 0; + + if (state->exit_latency <= prev_state->exit_latency) + return -EINVAL; + + if (state->target_residency <= prev_state->target_residency) + return -EINVAL; + + return 0; +} + /** * cmdline_table_adjust - Adjust the C-states table with data from cmdline. * @@ -1697,6 +1737,21 @@ static void __init cmdline_table_adjust(void) state->name, state->exit_latency, state->target_residency); } + /* Validate the adjusted C-states */ + for (i = 0; i < state_count; i++) { + const struct cpuidle_state *prev_state; + + state = &cmdline_states[i]; + prev_state = i ? &cmdline_states[i - 1] : NULL; + + if (validate_cmdline_cstate(state, prev_state)) { + printk(XENLOG_ERR PREFIX + "C-state '%s' validation failed\n", + state->name); + goto error; + } + } + /* Copy the adjusted C-states table back */ for (i = 0; i < state_count; i++) icpu.state_table[i] = cmdline_states[i];