From: Artem Bityutskiy <[email protected]> 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 <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Rafael J. Wysocki <[email protected]> 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 <[email protected]> --- 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_id /* 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(ch } /** + * 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(struct cpuidle_state *state, + 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. * * Adjust the C-states table with data from the 'mwait-idle.table' parameter @@ -1696,6 +1736,21 @@ static void __init cmdline_table_adjust( state->name, state->exit_latency, state->target_residency); } + /* Validate the adjusted C-states */ + for (i = 0; i < state_count; i++) { + 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];
