Blame SOURCES/kpatch-adapted-patch-for-CVE-2020-10767-and-CVE-2020-10768.patch

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