From 7a3d1bf135b9ef3d9c26c5e48e9200efe932b555 Mon Sep 17 00:00:00 2001
From: Artem Savkov <asavkov@redhat.com>
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 <longman@redhat.com>
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 <aquini@redhat.com>
RH-Acked-by: Phil Auld <pauld@redhat.com>
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1847395
CVE: CVE-2020-10768
commit 4d8df8cbb9156b0a0ab3f802b80cb5db57acc0bf
Author: Anthony Steinhauser <asteinhauser@google.com>
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 <asteinhauser@google.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: stable@vger.kernel.org
Signed-off-by: Waiman Long <longman@redhat.com>
Signed-off-by: Bruno Meneguele <bmeneg@redhat.com>
commit b7620b4e8bfb015bf494d47152751b8f07b5b215
Author: Waiman Long <longman@redhat.com>
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 <aquini@redhat.com>
RH-Acked-by: Phil Auld <pauld@redhat.com>
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 <asteinhauser@google.com>
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 <asteinhauser@google.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: stable@vger.kernel.org
Signed-off-by: Waiman Long <longman@redhat.com>
Signed-off-by: Bruno Meneguele <bmeneg@redhat.com>
Signed-off-by: Artem Savkov <asavkov@redhat.com>
Acked-by: Julien Thierry <jthierry@redhat.com>
Acked-by: Joe Lawrence <joe.lawrence@redhat.com>
---
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