cpu: Define attack vectors
Define 4 new attack vectors that are used for controlling CPU speculation
mitigations. These may be individually disabled as part of the
mitigations= command line. Attack vector controls are combined with global
options like 'auto' or 'auto,nosmt' like 'mitigations=auto,no_user_kernel'.
The global options come first in the mitigations= string.
Cross-thread mitigations can either remain enabled fully, including
potentially disabling SMT ('auto,nosmt'), remain enabled except for
disabling SMT ('auto'), or entirely disabled through the new
'no_cross_thread' attack vector option.
The default settings for these attack vectors are consistent with existing
kernel defaults, other than the automatic disabling of VM-based attack
vectors if KVM support is not present.
Signed-off-by: David Kaplan <david.kaplan@amd.com>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Link: https://lore.kernel.org/20250707183316.1349127-3-david.kaplan@amd.com
This commit is contained in:
1 parent
1caa1b0509
commit
19c24f7ee3
2 files changed
+140
-11
No files matched your search
+119
-11
@@ -37,6 +37,7 @@
|
||||
#include <linux/cpuset.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/cc_platform.h>
|
||||
#include <linux/parser.h>
|
||||
|
||||
#include <trace/events/power.h>
|
||||
#define CREATE_TRACE_POINTS
|
||||
@@ -3174,8 +3175,38 @@ void __init boot_cpu_hotplug_init(void)
|
||||
|
||||
#ifdef CONFIG_CPU_MITIGATIONS
|
||||
/*
|
||||
* These are used for a global "mitigations=" cmdline option for toggling
|
||||
* optional CPU mitigations.
|
||||
* All except the cross-thread attack vector are mitigated by default.
|
||||
* Cross-thread mitigation often requires disabling SMT which is expensive
|
||||
* so cross-thread mitigations are only partially enabled by default.
|
||||
*
|
||||
* Guest-to-Host and Guest-to-Guest vectors are only needed if KVM support is
|
||||
* present.
|
||||
*/
|
||||
static bool attack_vectors[NR_CPU_ATTACK_VECTORS] __ro_after_init = {
|
||||
[CPU_MITIGATE_USER_KERNEL] = true,
|
||||
[CPU_MITIGATE_USER_USER] = true,
|
||||
[CPU_MITIGATE_GUEST_HOST] = IS_ENABLED(CONFIG_KVM),
|
||||
[CPU_MITIGATE_GUEST_GUEST] = IS_ENABLED(CONFIG_KVM),
|
||||
};
|
||||
|
||||
bool cpu_attack_vector_mitigated(enum cpu_attack_vectors v)
|
||||
{
|
||||
if (v < NR_CPU_ATTACK_VECTORS)
|
||||
return attack_vectors[v];
|
||||
|
||||
WARN_ONCE(1, "Invalid attack vector %d\n", v);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* There are 3 global options, 'off', 'auto', 'auto,nosmt'. These may optionally
|
||||
* be combined with attack-vector disables which follow them.
|
||||
*
|
||||
* Examples:
|
||||
* mitigations=auto,no_user_kernel,no_user_user,no_cross_thread
|
||||
* mitigations=auto,nosmt,no_guest_host,no_guest_guest
|
||||
*
|
||||
* mitigations=off is equivalent to disabling all attack vectors.
|
||||
*/
|
||||
enum cpu_mitigations {
|
||||
CPU_MITIGATIONS_OFF,
|
||||
@@ -3183,19 +3214,96 @@ enum cpu_mitigations {
|
||||
CPU_MITIGATIONS_AUTO_NOSMT,
|
||||
};
|
||||
|
||||
enum {
|
||||
NO_USER_KERNEL,
|
||||
NO_USER_USER,
|
||||
NO_GUEST_HOST,
|
||||
NO_GUEST_GUEST,
|
||||
NO_CROSS_THREAD,
|
||||
NR_VECTOR_PARAMS,
|
||||
};
|
||||
|
||||
enum smt_mitigations smt_mitigations __ro_after_init = SMT_MITIGATIONS_AUTO;
|
||||
static enum cpu_mitigations cpu_mitigations __ro_after_init = CPU_MITIGATIONS_AUTO;
|
||||
|
||||
static const match_table_t global_mitigations = {
|
||||
{ CPU_MITIGATIONS_AUTO_NOSMT, "auto,nosmt"},
|
||||
{ CPU_MITIGATIONS_AUTO, "auto"},
|
||||
{ CPU_MITIGATIONS_OFF, "off"},
|
||||
};
|
||||
|
||||
static const match_table_t vector_mitigations = {
|
||||
{ NO_USER_KERNEL, "no_user_kernel"},
|
||||
{ NO_USER_USER, "no_user_user"},
|
||||
{ NO_GUEST_HOST, "no_guest_host"},
|
||||
{ NO_GUEST_GUEST, "no_guest_guest"},
|
||||
{ NO_CROSS_THREAD, "no_cross_thread"},
|
||||
{ NR_VECTOR_PARAMS, NULL},
|
||||
};
|
||||
|
||||
static int __init mitigations_parse_global_opt(char *arg)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(global_mitigations); i++) {
|
||||
const char *pattern = global_mitigations[i].pattern;
|
||||
|
||||
if (!strncmp(arg, pattern, strlen(pattern))) {
|
||||
cpu_mitigations = global_mitigations[i].token;
|
||||
return strlen(pattern);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init mitigations_parse_cmdline(char *arg)
|
||||
{
|
||||
if (!strcmp(arg, "off"))
|
||||
cpu_mitigations = CPU_MITIGATIONS_OFF;
|
||||
else if (!strcmp(arg, "auto"))
|
||||
cpu_mitigations = CPU_MITIGATIONS_AUTO;
|
||||
else if (!strcmp(arg, "auto,nosmt"))
|
||||
cpu_mitigations = CPU_MITIGATIONS_AUTO_NOSMT;
|
||||
else
|
||||
pr_crit("Unsupported mitigations=%s, system may still be vulnerable\n",
|
||||
arg);
|
||||
char *s, *p;
|
||||
int len;
|
||||
|
||||
len = mitigations_parse_global_opt(arg);
|
||||
|
||||
if (cpu_mitigations_off()) {
|
||||
memset(attack_vectors, 0, sizeof(attack_vectors));
|
||||
smt_mitigations = SMT_MITIGATIONS_OFF;
|
||||
} else if (cpu_mitigations_auto_nosmt()) {
|
||||
smt_mitigations = SMT_MITIGATIONS_ON;
|
||||
}
|
||||
|
||||
p = arg + len;
|
||||
|
||||
if (!*p)
|
||||
return 0;
|
||||
|
||||
/* Attack vector controls may come after the ',' */
|
||||
if (*p++ != ',' || !IS_ENABLED(CONFIG_ARCH_HAS_CPU_ATTACK_VECTORS)) {
|
||||
pr_crit("Unsupported mitigations=%s, system may still be vulnerable\n", arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while ((s = strsep(&p, ",")) != NULL) {
|
||||
switch (match_token(s, vector_mitigations, NULL)) {
|
||||
case NO_USER_KERNEL:
|
||||
attack_vectors[CPU_MITIGATE_USER_KERNEL] = false;
|
||||
break;
|
||||
case NO_USER_USER:
|
||||
attack_vectors[CPU_MITIGATE_USER_USER] = false;
|
||||
break;
|
||||
case NO_GUEST_HOST:
|
||||
attack_vectors[CPU_MITIGATE_GUEST_HOST] = false;
|
||||
break;
|
||||
case NO_GUEST_GUEST:
|
||||
attack_vectors[CPU_MITIGATE_GUEST_GUEST] = false;
|
||||
break;
|
||||
case NO_CROSS_THREAD:
|
||||
smt_mitigations = SMT_MITIGATIONS_OFF;
|
||||
break;
|
||||
default:
|
||||
pr_crit("Unsupported mitigations options %s\n", s);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user