Skip to content

Commit

Permalink
Set X86_FEATURE_INDIRECT_SAFE using a cmdline option instead
Browse files Browse the repository at this point in the history
Allow users to manually set this

Signed-off-by: hmtheboy154 <buingoc67@gmail.com>
  • Loading branch information
hmtheboy154 committed Oct 10, 2024
1 parent 6dcd555 commit 5648396
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 30 deletions.
31 changes: 1 addition & 30 deletions arch/x86/kernel/cpu/bugs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1669,15 +1669,6 @@ static void __init bhi_select_mitigation(void)
if (!IS_ENABLED(CONFIG_X86_64))
return;

/*
* There's no hardware mitigation in place, so mark indirect branches
* as unsafe.
*
* One could argue the SW loop makes indirect branches safe again, but
* Linus prefers it this way.
*/
setup_clear_cpu_cap(X86_FEATURE_INDIRECT_SAFE);

if (bhi_mitigation == BHI_MITIGATION_VMEXIT_ONLY) {
pr_info("Spectre BHI mitigation: SW BHB clearing on VM exit only\n");
setup_force_cpu_cap(X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT);
Expand All @@ -1694,21 +1685,6 @@ static void __init spectre_v2_select_mitigation(void)
enum spectre_v2_mitigation_cmd cmd = spectre_v2_parse_cmdline();
enum spectre_v2_mitigation mode = SPECTRE_V2_NONE;

/*
* X86_FEATURE_INDIRECT_SAFE indicates whether indirect calls can be
* considered safe. That means either:
*
* - the CPU isn't vulnerable to Spectre v2 or its variants;
*
* - a hardware mitigation is in place (e.g., IBRS, BHI_DIS_S); or
*
* - the user turned off mitigations altogether.
*
* Assume innocence until proven guilty: set the cap bit now, then
* clear it later if/when needed.
*/
setup_force_cpu_cap(X86_FEATURE_INDIRECT_SAFE);

/*
* If the CPU is not affected and the command line mode is NONE or AUTO
* then nothing to do.
Expand Down Expand Up @@ -1795,16 +1771,11 @@ static void __init spectre_v2_select_mitigation(void)
break;

case SPECTRE_V2_LFENCE:
setup_clear_cpu_cap(X86_FEATURE_INDIRECT_SAFE);
fallthrough;
case SPECTRE_V2_EIBRS_LFENCE:
setup_force_cpu_cap(X86_FEATURE_RETPOLINE_LFENCE);
setup_force_cpu_cap(X86_FEATURE_RETPOLINE);
break;
fallthrough;

case SPECTRE_V2_RETPOLINE:
setup_clear_cpu_cap(X86_FEATURE_INDIRECT_SAFE);
fallthrough;
case SPECTRE_V2_EIBRS_RETPOLINE:
setup_force_cpu_cap(X86_FEATURE_RETPOLINE);
break;
Expand Down
53 changes: 53 additions & 0 deletions arch/x86/kernel/cpu/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,39 @@ static int __init x86_noinvpcid_setup(char *s)
}
early_param("noinvpcid", x86_noinvpcid_setup);

enum syscall_hardening_switch {
SYSCALL_HARDENING_ON,
SYSCALL_HARDENING_OFF,
};

static enum syscall_hardening_switch syscall_hardening __ro_after_init = SYSCALL_HARDENING_ON;

static int __init syscall_hardening_parse_cmdline(char *str)
{
if (!str)
return -EINVAL;

if (!strcmp(str, "off"))
syscall_hardening = SYSCALL_HARDENING_OFF;
else if (!strcmp(str, "on"))
syscall_hardening = SYSCALL_HARDENING_ON;
else
pr_err("Ignoring unknown syscall_hardening option (%s)", str);

return 0;
}
early_param("syscall_hardening", syscall_hardening_parse_cmdline);

static void __init syscall_hardening_disable(void)
{
pr_info("syscall hardening function called \n");
if (syscall_hardening == SYSCALL_HARDENING_ON)
return;

setup_force_cpu_cap(X86_FEATURE_INDIRECT_SAFE);
pr_info("Syscall hardening is disabled to allow indirect calls !\n");
}

#ifdef CONFIG_X86_32
static int cachesize_override = -1;
static int disable_x86_serial_nr = 1;
Expand Down Expand Up @@ -2322,6 +2355,12 @@ void __init arch_cpu_finalize_init(void)

identify_boot_cpu();

/* Projects like KernelSU is relying on hooking indirect syscall which
* is being hardened by default on recent kernel. Allow disabling it
* if user specified in cmdline.
*/
syscall_hardening_disable();

select_idle_routine();

/*
Expand Down Expand Up @@ -2392,3 +2431,17 @@ void __init arch_cpu_finalize_init(void)
*/
mem_encrypt_init();
}

#ifdef CONFIG_SYSFS
static ssize_t syscall_hardening_show_state(char *buf)
{
if (boot_cpu_has(X86_FEATURE_INDIRECT_SAFE))
return sysfs_emit(buf, "Syscall hardening: Disabled\n");
return sysfs_emit(buf, "Syscall hardening: Enabled\n");
}

ssize_t cpu_show_syscall_hardening(struct device *dev, struct device_attribute *attr, char *buf)
{
return syscall_hardening_show_state(buf);
}
#endif
12 changes: 12 additions & 0 deletions drivers/base/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,15 @@ static ssize_t print_cpus_isolated(struct device *dev,
}
static DEVICE_ATTR(isolated, 0444, print_cpus_isolated, NULL);

#if defined(CONFIG_X86) || defined(CONFIG_X86_64)
ssize_t __weak cpu_show_syscall_hardening(struct device *dev,
struct device_attribute *attr, char *buf)
{
return sysfs_emit(buf, "Not available\n");
}
static DEVICE_ATTR(syscall_hardening, 0444, cpu_show_syscall_hardening, NULL);
#endif

#ifdef CONFIG_NO_HZ_FULL
static ssize_t print_cpus_nohz_full(struct device *dev,
struct device_attribute *attr, char *buf)
Expand Down Expand Up @@ -505,6 +514,9 @@ static struct attribute *cpu_root_attrs[] = {
&dev_attr_offline.attr,
&dev_attr_enabled.attr,
&dev_attr_isolated.attr,
#if defined(CONFIG_X86) || defined(CONFIG_X86_64)
&dev_attr_syscall_hardening.attr,
#endif
#ifdef CONFIG_NO_HZ_FULL
&dev_attr_nohz_full.attr,
#endif
Expand Down
4 changes: 4 additions & 0 deletions include/linux/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ extern ssize_t cpu_show_gds(struct device *dev,
struct device_attribute *attr, char *buf);
extern ssize_t cpu_show_reg_file_data_sampling(struct device *dev,
struct device_attribute *attr, char *buf);
#if defined(CONFIG_X86) || defined(CONFIG_X86_64)
extern ssize_t cpu_show_syscall_hardening(struct device *dev,
struct device_attribute *attr, char *buf);
#endif

extern __printf(4, 5)
struct device *cpu_device_create(struct device *parent, void *drvdata,
Expand Down

0 comments on commit 5648396

Please sign in to comment.