Skip to content

Commit 19c24f7

Browse files
dkaplan2bp3tk0v
authored andcommitted
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 <[email protected]> Signed-off-by: Borislav Petkov (AMD) <[email protected]> Link: https://lore.kernel.org/[email protected]
1 parent 1caa1b0 commit 19c24f7

File tree

2 files changed

+140
-11
lines changed

2 files changed

+140
-11
lines changed

include/linux/cpu.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,9 +198,25 @@ void cpuhp_report_idle_dead(void);
198198
static inline void cpuhp_report_idle_dead(void) { }
199199
#endif /* #ifdef CONFIG_HOTPLUG_CPU */
200200

201+
enum cpu_attack_vectors {
202+
CPU_MITIGATE_USER_KERNEL,
203+
CPU_MITIGATE_USER_USER,
204+
CPU_MITIGATE_GUEST_HOST,
205+
CPU_MITIGATE_GUEST_GUEST,
206+
NR_CPU_ATTACK_VECTORS,
207+
};
208+
209+
enum smt_mitigations {
210+
SMT_MITIGATIONS_OFF,
211+
SMT_MITIGATIONS_AUTO,
212+
SMT_MITIGATIONS_ON,
213+
};
214+
201215
#ifdef CONFIG_CPU_MITIGATIONS
202216
extern bool cpu_mitigations_off(void);
203217
extern bool cpu_mitigations_auto_nosmt(void);
218+
extern bool cpu_attack_vector_mitigated(enum cpu_attack_vectors v);
219+
extern enum smt_mitigations smt_mitigations;
204220
#else
205221
static inline bool cpu_mitigations_off(void)
206222
{
@@ -210,6 +226,11 @@ static inline bool cpu_mitigations_auto_nosmt(void)
210226
{
211227
return false;
212228
}
229+
static inline bool cpu_attack_vector_mitigated(enum cpu_attack_vectors v)
230+
{
231+
return false;
232+
}
233+
#define smt_mitigations SMT_MITIGATIONS_OFF
213234
#endif
214235

215236
#endif /* _LINUX_CPU_H_ */

kernel/cpu.c

Lines changed: 119 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include <linux/cpuset.h>
3838
#include <linux/random.h>
3939
#include <linux/cc_platform.h>
40+
#include <linux/parser.h>
4041

4142
#include <trace/events/power.h>
4243
#define CREATE_TRACE_POINTS
@@ -3174,28 +3175,135 @@ void __init boot_cpu_hotplug_init(void)
31743175

31753176
#ifdef CONFIG_CPU_MITIGATIONS
31763177
/*
3177-
* These are used for a global "mitigations=" cmdline option for toggling
3178-
* optional CPU mitigations.
3178+
* All except the cross-thread attack vector are mitigated by default.
3179+
* Cross-thread mitigation often requires disabling SMT which is expensive
3180+
* so cross-thread mitigations are only partially enabled by default.
3181+
*
3182+
* Guest-to-Host and Guest-to-Guest vectors are only needed if KVM support is
3183+
* present.
3184+
*/
3185+
static bool attack_vectors[NR_CPU_ATTACK_VECTORS] __ro_after_init = {
3186+
[CPU_MITIGATE_USER_KERNEL] = true,
3187+
[CPU_MITIGATE_USER_USER] = true,
3188+
[CPU_MITIGATE_GUEST_HOST] = IS_ENABLED(CONFIG_KVM),
3189+
[CPU_MITIGATE_GUEST_GUEST] = IS_ENABLED(CONFIG_KVM),
3190+
};
3191+
3192+
bool cpu_attack_vector_mitigated(enum cpu_attack_vectors v)
3193+
{
3194+
if (v < NR_CPU_ATTACK_VECTORS)
3195+
return attack_vectors[v];
3196+
3197+
WARN_ONCE(1, "Invalid attack vector %d\n", v);
3198+
return false;
3199+
}
3200+
3201+
/*
3202+
* There are 3 global options, 'off', 'auto', 'auto,nosmt'. These may optionally
3203+
* be combined with attack-vector disables which follow them.
3204+
*
3205+
* Examples:
3206+
* mitigations=auto,no_user_kernel,no_user_user,no_cross_thread
3207+
* mitigations=auto,nosmt,no_guest_host,no_guest_guest
3208+
*
3209+
* mitigations=off is equivalent to disabling all attack vectors.
31793210
*/
31803211
enum cpu_mitigations {
31813212
CPU_MITIGATIONS_OFF,
31823213
CPU_MITIGATIONS_AUTO,
31833214
CPU_MITIGATIONS_AUTO_NOSMT,
31843215
};
31853216

3217+
enum {
3218+
NO_USER_KERNEL,
3219+
NO_USER_USER,
3220+
NO_GUEST_HOST,
3221+
NO_GUEST_GUEST,
3222+
NO_CROSS_THREAD,
3223+
NR_VECTOR_PARAMS,
3224+
};
3225+
3226+
enum smt_mitigations smt_mitigations __ro_after_init = SMT_MITIGATIONS_AUTO;
31863227
static enum cpu_mitigations cpu_mitigations __ro_after_init = CPU_MITIGATIONS_AUTO;
31873228

3229+
static const match_table_t global_mitigations = {
3230+
{ CPU_MITIGATIONS_AUTO_NOSMT, "auto,nosmt"},
3231+
{ CPU_MITIGATIONS_AUTO, "auto"},
3232+
{ CPU_MITIGATIONS_OFF, "off"},
3233+
};
3234+
3235+
static const match_table_t vector_mitigations = {
3236+
{ NO_USER_KERNEL, "no_user_kernel"},
3237+
{ NO_USER_USER, "no_user_user"},
3238+
{ NO_GUEST_HOST, "no_guest_host"},
3239+
{ NO_GUEST_GUEST, "no_guest_guest"},
3240+
{ NO_CROSS_THREAD, "no_cross_thread"},
3241+
{ NR_VECTOR_PARAMS, NULL},
3242+
};
3243+
3244+
static int __init mitigations_parse_global_opt(char *arg)
3245+
{
3246+
int i;
3247+
3248+
for (i = 0; i < ARRAY_SIZE(global_mitigations); i++) {
3249+
const char *pattern = global_mitigations[i].pattern;
3250+
3251+
if (!strncmp(arg, pattern, strlen(pattern))) {
3252+
cpu_mitigations = global_mitigations[i].token;
3253+
return strlen(pattern);
3254+
}
3255+
}
3256+
3257+
return 0;
3258+
}
3259+
31883260
static int __init mitigations_parse_cmdline(char *arg)
31893261
{
3190-
if (!strcmp(arg, "off"))
3191-
cpu_mitigations = CPU_MITIGATIONS_OFF;
3192-
else if (!strcmp(arg, "auto"))
3193-
cpu_mitigations = CPU_MITIGATIONS_AUTO;
3194-
else if (!strcmp(arg, "auto,nosmt"))
3195-
cpu_mitigations = CPU_MITIGATIONS_AUTO_NOSMT;
3196-
else
3197-
pr_crit("Unsupported mitigations=%s, system may still be vulnerable\n",
3198-
arg);
3262+
char *s, *p;
3263+
int len;
3264+
3265+
len = mitigations_parse_global_opt(arg);
3266+
3267+
if (cpu_mitigations_off()) {
3268+
memset(attack_vectors, 0, sizeof(attack_vectors));
3269+
smt_mitigations = SMT_MITIGATIONS_OFF;
3270+
} else if (cpu_mitigations_auto_nosmt()) {
3271+
smt_mitigations = SMT_MITIGATIONS_ON;
3272+
}
3273+
3274+
p = arg + len;
3275+
3276+
if (!*p)
3277+
return 0;
3278+
3279+
/* Attack vector controls may come after the ',' */
3280+
if (*p++ != ',' || !IS_ENABLED(CONFIG_ARCH_HAS_CPU_ATTACK_VECTORS)) {
3281+
pr_crit("Unsupported mitigations=%s, system may still be vulnerable\n", arg);
3282+
return 0;
3283+
}
3284+
3285+
while ((s = strsep(&p, ",")) != NULL) {
3286+
switch (match_token(s, vector_mitigations, NULL)) {
3287+
case NO_USER_KERNEL:
3288+
attack_vectors[CPU_MITIGATE_USER_KERNEL] = false;
3289+
break;
3290+
case NO_USER_USER:
3291+
attack_vectors[CPU_MITIGATE_USER_USER] = false;
3292+
break;
3293+
case NO_GUEST_HOST:
3294+
attack_vectors[CPU_MITIGATE_GUEST_HOST] = false;
3295+
break;
3296+
case NO_GUEST_GUEST:
3297+
attack_vectors[CPU_MITIGATE_GUEST_GUEST] = false;
3298+
break;
3299+
case NO_CROSS_THREAD:
3300+
smt_mitigations = SMT_MITIGATIONS_OFF;
3301+
break;
3302+
default:
3303+
pr_crit("Unsupported mitigations options %s\n", s);
3304+
return 0;
3305+
}
3306+
}
31993307

32003308
return 0;
32013309
}

0 commit comments

Comments
 (0)