From 7a3d1bf135b9ef3d9c26c5e48e9200efe932b555 Mon Sep 17 00:00:00 2001 From: Artem Savkov Date: Fri, 19 Jun 2020 11:30:09 +0200 Subject: [KPATCH RHEL-8.2 v4] kpatch adapted patch for CVE-2020-10767 and CVE-2020-10768 Kernels: 4.18.0-193.el8 4.18.0-193.1.2.el8_2 4.18.0-193.6.3.el8_2 Changes since last build: arches: x86_64 bugs.o: changed function: arch_prctl_spec_ctrl_get bugs.o: changed function: arch_prctl_spec_ctrl_set bugs.o: changed function: arch_seccomp_spec_mitigate bugs.o: changed function: ib_prctl_set.part.1 bugs.o: new function: kpatch_cve_2020_10767_pre_patch_callback --------------------------- Kernels: 4.18.0-193.el8 4.18.0-193.1.2.el8_2 4.18.0-193.6.3.el8_2 Modifications: - Dropped SPECTRE_V2_USER_STRICT_PREFERRED support as it is not a part of CVE fix and was only ported for patches to apply cleanly. - Added a pre-patch callback that would initialize spectre_v2_user_ibpb from scratch, parsing the command line and checking cpu capabilities. - spectre_v2_user_stibp is not renamed and is left as spectre_v2_user to limit the footprint of the patch. Testing: reproducer provided by security team commit eb2ce6c5ce9269a32474955bb0934359801c83fa Author: Waiman Long Date: Tue Jun 16 19:01:42 2020 -0400 [x86] x86/speculation: PR_SPEC_FORCE_DISABLE enforcement for indirect branches Message-id: <20200616190142.5674-6-longman@redhat.com> Patchwork-id: 320367 Patchwork-instance: patchwork O-Subject: [RHEL8.2.z PATCH 5/5] x86/speculation: PR_SPEC_FORCE_DISABLE enforcement for indirect branches. Bugzilla: 1847396 Z-Bugzilla: 1847395 CVE: CVE-2020-10768 RH-Acked-by: Rafael Aquini RH-Acked-by: Phil Auld Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1847395 CVE: CVE-2020-10768 commit 4d8df8cbb9156b0a0ab3f802b80cb5db57acc0bf Author: Anthony Steinhauser Date: Sun, 7 Jun 2020 05:44:19 -0700 x86/speculation: PR_SPEC_FORCE_DISABLE enforcement for indirect branches. Currently, it is possible to enable indirect branch speculation even after it was force-disabled using the PR_SPEC_FORCE_DISABLE option. Moreover, the PR_GET_SPECULATION_CTRL command gives afterwards an incorrect result (force-disabled when it is in fact enabled). This also is inconsistent vs. STIBP and the documention which cleary states that PR_SPEC_FORCE_DISABLE cannot be undone. Fix this by actually enforcing force-disabled indirect branch speculation. PR_SPEC_ENABLE called after PR_SPEC_FORCE_DISABLE now fails with -EPERM as described in the documentation. Fixes: 9137bb27e60e ("x86/speculation: Add prctl() control for indirect branch speculation") Signed-off-by: Anthony Steinhauser Signed-off-by: Thomas Gleixner Cc: stable@vger.kernel.org Signed-off-by: Waiman Long Signed-off-by: Bruno Meneguele commit b7620b4e8bfb015bf494d47152751b8f07b5b215 Author: Waiman Long Date: Tue Jun 16 19:01:40 2020 -0400 [x86] x86/speculation: Avoid force-disabling IBPB based on STIBP and enhanced IBRS Message-id: <20200616190142.5674-4-longman@redhat.com> Patchwork-id: 320366 Patchwork-instance: patchwork O-Subject: [RHEL8.2.z PATCH 3/5] x86/speculation: Avoid force-disabling IBPB based on STIBP and enhanced IBRS. Bugzilla: 1847379 Z-Bugzilla: 1847378 CVE: CVE-2020-10767 RH-Acked-by: Rafael Aquini RH-Acked-by: Phil Auld Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1847378 CVE: CVE-2020-10767 Conflicts: There is a minor fuzz in bugs.c due to missing the upstream commit e4f358916d52 ("x86, modpost: Replace last remnants of RETPOLINE with CONFIG_RETPOLINE"). However, backporting this commit at this stage will cause unexpected retpoline warning when loading 3rd party modules. commit 21998a351512eba4ed5969006f0c55882d995ada Author: Anthony Steinhauser Date: Tue, 19 May 2020 06:40:42 -0700 x86/speculation: Avoid force-disabling IBPB based on STIBP and enhanced IBRS. When STIBP is unavailable or enhanced IBRS is available, Linux force-disables the IBPB mitigation of Spectre-BTB even when simultaneous multithreading is disabled. While attempts to enable IBPB using prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, ...) fail with EPERM, the seccomp syscall (or its prctl(PR_SET_SECCOMP, ...) equivalent) which are used e.g. by Chromium or OpenSSH succeed with no errors but the application remains silently vulnerable to cross-process Spectre v2 attacks (classical BTB poisoning). At the same time the SYSFS reporting (/sys/devices/system/cpu/vulnerabilities/spectre_v2) displays that IBPB is conditionally enabled when in fact it is unconditionally disabled. STIBP is useful only when SMT is enabled. When SMT is disabled and STIBP is unavailable, it makes no sense to force-disable also IBPB, because IBPB protects against cross-process Spectre-BTB attacks regardless of the SMT state. At the same time since missing STIBP was only observed on AMD CPUs, AMD does not recommend using STIBP, but recommends using IBPB, so disabling IBPB because of missing STIBP goes directly against AMD's advice: https://developer.amd.com/wp-content/resources/Architecture_Guidelines_Update_Indirect_Branch_Control.pdf Similarly, enhanced IBRS is designed to protect cross-core BTB poisoning and BTB-poisoning attacks from user space against kernel (and BTB-poisoning attacks from guest against hypervisor), it is not designed to prevent cross-process (or cross-VM) BTB poisoning between processes (or VMs) running on the same core. Therefore, even with enhanced IBRS it is necessary to flush the BTB during context-switches, so there is no reason to force disable IBPB when enhanced IBRS is available. Enable the prctl control of IBPB even when STIBP is unavailable or enhanced IBRS is available. Fixes: 7cc765a67d8e ("x86/speculation: Enable prctl mode for spectre_v2_user") Signed-off-by: Anthony Steinhauser Signed-off-by: Thomas Gleixner Cc: stable@vger.kernel.org Signed-off-by: Waiman Long Signed-off-by: Bruno Meneguele Signed-off-by: Artem Savkov Acked-by: Julien Thierry Acked-by: Joe Lawrence --- arch/x86/kernel/cpu/bugs.c | 158 +++++++++++++++++++++++++++++++++---- 1 file changed, 144 insertions(+), 14 deletions(-) diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index 0316c7a04457..654c9a779caf 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -589,6 +589,9 @@ static enum spectre_v2_mitigation spectre_v2_enabled __ro_after_init = static enum spectre_v2_user_mitigation spectre_v2_user __ro_after_init = SPECTRE_V2_USER_NONE; +static enum spectre_v2_user_mitigation spectre_v2_user_ibpb = + SPECTRE_V2_USER_NONE; + #ifdef RETPOLINE static bool spectre_v2_bad_module; @@ -1291,13 +1294,17 @@ static int ib_prctl_set(struct task_struct *task, unsigned long ctrl) { switch (ctrl) { case PR_SPEC_ENABLE: - if (spectre_v2_user == SPECTRE_V2_USER_NONE) + if (spectre_v2_user_ibpb == SPECTRE_V2_USER_NONE && + spectre_v2_user == SPECTRE_V2_USER_NONE) return 0; /* * Indirect branch speculation is always disabled in strict - * mode. + * mode. It can neither be enabled if it was force-disabled + * by a previous prctl call. */ - if (spectre_v2_user == SPECTRE_V2_USER_STRICT) + if (spectre_v2_user_ibpb == SPECTRE_V2_USER_STRICT || + spectre_v2_user == SPECTRE_V2_USER_STRICT || + task_spec_ib_force_disable(task)) return -EPERM; task_clear_spec_ib_disable(task); task_update_spec_tif(task); @@ -1308,9 +1315,11 @@ static int ib_prctl_set(struct task_struct *task, unsigned long ctrl) * Indirect branch speculation is always allowed when * mitigation is force disabled. */ - if (spectre_v2_user == SPECTRE_V2_USER_NONE) + if (spectre_v2_user_ibpb == SPECTRE_V2_USER_NONE && + spectre_v2_user == SPECTRE_V2_USER_NONE) return -EPERM; - if (spectre_v2_user == SPECTRE_V2_USER_STRICT) + if (spectre_v2_user_ibpb == SPECTRE_V2_USER_STRICT || + spectre_v2_user == SPECTRE_V2_USER_STRICT) return 0; task_set_spec_ib_disable(task); if (ctrl == PR_SPEC_FORCE_DISABLE) @@ -1341,7 +1350,8 @@ void arch_seccomp_spec_mitigate(struct task_struct *task) { if (ssb_mode == SPEC_STORE_BYPASS_SECCOMP) ssb_prctl_set(task, PR_SPEC_FORCE_DISABLE); - if (spectre_v2_user == SPECTRE_V2_USER_SECCOMP) + if (spectre_v2_user_ibpb == SPECTRE_V2_USER_SECCOMP || + spectre_v2_user == SPECTRE_V2_USER_SECCOMP) ib_prctl_set(task, PR_SPEC_FORCE_DISABLE); } #endif @@ -1372,21 +1382,23 @@ static int ib_prctl_get(struct task_struct *task) if (!boot_cpu_has_bug(X86_BUG_SPECTRE_V2)) return PR_SPEC_NOT_AFFECTED; - switch (spectre_v2_user) { - case SPECTRE_V2_USER_NONE: + if (spectre_v2_user_ibpb == SPECTRE_V2_USER_NONE && + spectre_v2_user == SPECTRE_V2_USER_NONE) return PR_SPEC_ENABLE; - case SPECTRE_V2_USER_PRCTL: - case SPECTRE_V2_USER_SECCOMP: + else if (spectre_v2_user_ibpb == SPECTRE_V2_USER_STRICT || + spectre_v2_user == SPECTRE_V2_USER_STRICT) + return PR_SPEC_DISABLE; + else if (spectre_v2_user_ibpb == SPECTRE_V2_USER_PRCTL || + spectre_v2_user_ibpb == SPECTRE_V2_USER_SECCOMP || + spectre_v2_user == SPECTRE_V2_USER_PRCTL || + spectre_v2_user == SPECTRE_V2_USER_SECCOMP) { if (task_spec_ib_force_disable(task)) return PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE; if (task_spec_ib_disable(task)) return PR_SPEC_PRCTL | PR_SPEC_DISABLE; return PR_SPEC_PRCTL | PR_SPEC_ENABLE; - case SPECTRE_V2_USER_STRICT: - return PR_SPEC_DISABLE; - default: + } else return PR_SPEC_NOT_AFFECTED; - } } int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which) @@ -1755,3 +1767,121 @@ ssize_t cpu_show_srbds(struct device *dev, struct device_attribute *attr, char * return cpu_show_common(dev, attr, buf, X86_BUG_SRBDS); } #endif + +static inline bool kpatch_cve_2020_10767_match_option(const char *arg, int arglen, const char *opt) +{ + int len = strlen(opt); + + return len == arglen && !strncmp(arg, opt, len); +} + +static enum spectre_v2_mitigation_cmd kpatch_cve_2020_10767_spectre_v2_parse_cmdline(void) +{ + enum spectre_v2_mitigation_cmd cmd = SPECTRE_V2_CMD_AUTO; + char arg[20]; + int ret, i; + + if (cmdline_find_option_bool(boot_command_line, "nospectre_v2") || + cpu_mitigations_off()) + return SPECTRE_V2_CMD_NONE; + + ret = cmdline_find_option(boot_command_line, "spectre_v2", arg, sizeof(arg)); + if (ret < 0) + return SPECTRE_V2_CMD_AUTO; + + for (i = 0; i < ARRAY_SIZE(mitigation_options); i++) { + if (!kpatch_cve_2020_10767_match_option(arg, ret, mitigation_options[i].option)) + continue; + cmd = mitigation_options[i].cmd; + break; + } + + if (i >= ARRAY_SIZE(mitigation_options)) { + return SPECTRE_V2_CMD_AUTO; + } + + if ((cmd == SPECTRE_V2_CMD_RETPOLINE || + cmd == SPECTRE_V2_CMD_RETPOLINE_AMD || + cmd == SPECTRE_V2_CMD_RETPOLINE_GENERIC) && + !IS_ENABLED(CONFIG_RETPOLINE)) { + return SPECTRE_V2_CMD_AUTO; + } + + if (cmd == SPECTRE_V2_CMD_RETPOLINE_AMD && + boot_cpu_data.x86_vendor != X86_VENDOR_AMD) { + return SPECTRE_V2_CMD_AUTO; + } + + return cmd; +} + +static enum spectre_v2_user_cmd +kpatch_cve_2020_10767_spectre_v2_parse_user_cmdline(enum spectre_v2_mitigation_cmd v2_cmd) +{ + char arg[20]; + int ret, i; + + switch (v2_cmd) { + case SPECTRE_V2_CMD_NONE: + return SPECTRE_V2_USER_CMD_NONE; + case SPECTRE_V2_CMD_FORCE: + return SPECTRE_V2_USER_CMD_FORCE; + default: + break; + } + + ret = cmdline_find_option(boot_command_line, "spectre_v2_user", + arg, sizeof(arg)); + if (ret < 0) + return SPECTRE_V2_USER_CMD_AUTO; + + for (i = 0; i < ARRAY_SIZE(v2_user_options); i++) { + if (kpatch_cve_2020_10767_match_option(arg, ret, v2_user_options[i].option)) { + return v2_user_options[i].cmd; + } + } + + return SPECTRE_V2_USER_CMD_AUTO; +} + +static void kpatch_cve_2020_10767_spectre_v2_user_select_mitigation(void) +{ + enum spectre_v2_mitigation_cmd v2_cmd = kpatch_cve_2020_10767_spectre_v2_parse_cmdline(); + enum spectre_v2_user_mitigation mode = SPECTRE_V2_USER_NONE; + enum spectre_v2_user_cmd cmd; + + if (!boot_cpu_has(X86_FEATURE_IBPB)) + return; + + cmd = kpatch_cve_2020_10767_spectre_v2_parse_user_cmdline(v2_cmd); + switch (cmd) { + case SPECTRE_V2_USER_CMD_NONE: + return; + case SPECTRE_V2_USER_CMD_FORCE: + mode = SPECTRE_V2_USER_STRICT; + break; + case SPECTRE_V2_USER_CMD_PRCTL: + case SPECTRE_V2_USER_CMD_PRCTL_IBPB: + mode = SPECTRE_V2_USER_PRCTL; + break; + case SPECTRE_V2_USER_CMD_AUTO: + case SPECTRE_V2_USER_CMD_SECCOMP: + case SPECTRE_V2_USER_CMD_SECCOMP_IBPB: + if (IS_ENABLED(CONFIG_SECCOMP)) + mode = SPECTRE_V2_USER_SECCOMP; + else + mode = SPECTRE_V2_USER_PRCTL; + break; + } + + spectre_v2_user_ibpb = mode; +} + +#include "kpatch-macros.h" + +static int kpatch_cve_2020_10767_pre_patch_callback(struct klp_object *obj) +{ + kpatch_cve_2020_10767_spectre_v2_user_select_mitigation(); + return 0; +} +KPATCH_PRE_PATCH_CALLBACK(kpatch_cve_2020_10767_pre_patch_callback); -- 2.21.3