2024-03-29 02:13:03

by Chang S. Bae

[permalink] [raw]
Subject: [PATCH v9 11/14] x86/cpu/keylocker: Check Register File Data Sampling mitigation

The Register File Data Sampling vulnerability may allow malicious
userspace programs to infer stale kernel register data, potentially
exposing sensitive key values, including AES keys.

To address this vulnerability, a microcode update needs to be applied to
the CPU, which modifies the VERW instruction to flush the affected CPU
buffers.

The kernel already has a facility to flush CPU buffers before returning
to userspace, which is indicated by the X86_FEATURE_CLEAR_CPU_BUF flag.

Ensure the mitigation before enabling Key Locker. Do not enable the
feature on CPUs affected by the vulnerability but lacks mitigation.

Signed-off-by: Chang S. Bae <[email protected]>
Cc: Dave Hansen <[email protected]>
Cc: Pawan Gupta <[email protected]>
---
Change from v8:
* Add as a new patch.

Note that the code change follows the mitigation guidance [1]:
"Software loading Key Locker keys using LOADIWKEY should execute a VERW
to clear registers before transitioning to untrusted code to prevent
later software from inferring the loaded key."

[1] https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/advisory-guidance/register-file-data-sampling.html
---
arch/x86/kernel/keylocker.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)

diff --git a/arch/x86/kernel/keylocker.c b/arch/x86/kernel/keylocker.c
index d4f3aa65ea8a..6e805c4da76d 100644
--- a/arch/x86/kernel/keylocker.c
+++ b/arch/x86/kernel/keylocker.c
@@ -135,12 +135,29 @@ static bool __init have_gds_mitigation(void)
return false;
}

+/*
+ * IA32_ARCH_CAPABILITIES MSR is retrieved during the setting of
+ * X86_BUG_RFDS. Ensure that the mitigation is applied to flush CPU
+ * buffers by checking the flag.
+ */
+static bool __init have_rfds_mitigation(void)
+{
+ if (boot_cpu_has(X86_FEATURE_CLEAR_CPU_BUF))
+ return true;
+
+ pr_warn("x86/keylocker: Susceptible to the RFDS vulnerability.\n");
+ return false;
+}
+
/* Check if Key Locker is secure enough to be used. */
static bool __init secure_keylocker(void)
{
if (boot_cpu_has_bug(X86_BUG_GDS) && !have_gds_mitigation())
return false;

+ if (boot_cpu_has_bug(X86_BUG_RFDS) && !have_rfds_mitigation())
+ return false;
+
return true;
}

--
2.34.1



2024-03-29 06:21:23

by Pawan Gupta

[permalink] [raw]
Subject: Re: [PATCH v9 11/14] x86/cpu/keylocker: Check Register File Data Sampling mitigation

On Thu, Mar 28, 2024 at 06:53:43PM -0700, Chang S. Bae wrote:
> The Register File Data Sampling vulnerability may allow malicious
> userspace programs to infer stale kernel register data, potentially
> exposing sensitive key values, including AES keys.
>
> To address this vulnerability, a microcode update needs to be applied to
> the CPU, which modifies the VERW instruction to flush the affected CPU
> buffers.
>
> The kernel already has a facility to flush CPU buffers before returning
> to userspace, which is indicated by the X86_FEATURE_CLEAR_CPU_BUF flag.
>
> Ensure the mitigation before enabling Key Locker. Do not enable the
> feature on CPUs affected by the vulnerability but lacks mitigation.
>
> Signed-off-by: Chang S. Bae <[email protected]>
> Cc: Dave Hansen <[email protected]>
> Cc: Pawan Gupta <[email protected]>
> ---
> Change from v8:
> * Add as a new patch.
>
> Note that the code change follows the mitigation guidance [1]:
> "Software loading Key Locker keys using LOADIWKEY should execute a VERW
> to clear registers before transitioning to untrusted code to prevent
> later software from inferring the loaded key."
>
> [1] https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/advisory-guidance/register-file-data-sampling.html
> ---
> arch/x86/kernel/keylocker.c | 17 +++++++++++++++++
> 1 file changed, 17 insertions(+)
>
> diff --git a/arch/x86/kernel/keylocker.c b/arch/x86/kernel/keylocker.c
> index d4f3aa65ea8a..6e805c4da76d 100644
> --- a/arch/x86/kernel/keylocker.c
> +++ b/arch/x86/kernel/keylocker.c
> @@ -135,12 +135,29 @@ static bool __init have_gds_mitigation(void)
> return false;
> }
>
> +/*
> + * IA32_ARCH_CAPABILITIES MSR is retrieved during the setting of
> + * X86_BUG_RFDS. Ensure that the mitigation is applied to flush CPU
> + * buffers by checking the flag.
> + */
> +static bool __init have_rfds_mitigation(void)
> +{
> + if (boot_cpu_has(X86_FEATURE_CLEAR_CPU_BUF))
> + return true;

X86_FEATURE_CLEAR_CPU_BUF is also set by other VERW based mitigations
like MDS. The feature flag does not guarantee that the microcode
required to mitigate RFDS is loaded.

A more robust check would be:

if (rfds_mitigation == RFDS_MITIGATION_VERW)
return true;

And it would be apt to move this function to arch/x86/kernel/cpu/bugs.c

> +
> + pr_warn("x86/keylocker: Susceptible to the RFDS vulnerability.\n");
> + return false;
> +}
> +
> /* Check if Key Locker is secure enough to be used. */
> static bool __init secure_keylocker(void)
> {
> if (boot_cpu_has_bug(X86_BUG_GDS) && !have_gds_mitigation())
> return false;
>
> + if (boot_cpu_has_bug(X86_BUG_RFDS) && !have_rfds_mitigation())
> + return false;
> +
> return true;
> }

2024-04-07 23:20:48

by Chang S. Bae

[permalink] [raw]
Subject: [PATCH v9a 11/14] x86/cpu/keylocker: Check Register File Data Sampling mitigation

The Register File Data Sampling vulnerability may allow malicious
userspace programs to infer stale kernel register data, potentially
exposing sensitive key values, including AES keys.

To address this vulnerability, a microcode update needs to be applied to
the CPU, which modifies the VERW instruction to flush the affected CPU
buffers.

Reference the 'rfds_mitigation' variable to check the mitigation status.
Do not enable Key Locker on CPUs affected by the vulnerability but
lacking mitigation.

Signed-off-by: Chang S. Bae <[email protected]>
Cc: Dave Hansen <[email protected]>
Cc: Pawan Gupta <[email protected]>
---
Changes from v9:
* Remove the helper function and simplify the code by directly reading
the status variable. (Pawan Gupta)

Note that this code change aligns with mitigation guidance, which
recommends:
"Software loading Key Locker keys using LOADIWKEY should execute a VERW
to clear registers before transitioning to untrusted code to prevent
later software from inferring the loaded key."

For more information, refer to Intel's guidance on Register File Data
Sampling:
https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/advisory-guidance/register-file-data-sampling.html
---
arch/x86/include/asm/processor.h | 8 ++++++++
arch/x86/kernel/cpu/bugs.c | 8 +-------
arch/x86/kernel/keylocker.c | 3 +++
3 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 74eaa3a2b85b..b823163f4786 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -728,6 +728,14 @@ enum mitigation_info {

extern bool gds_ucode_mitigated(enum mitigation_info mitg);

+enum rfds_mitigations {
+ RFDS_MITIGATION_OFF,
+ RFDS_MITIGATION_VERW,
+ RFDS_MITIGATION_UCODE_NEEDED,
+};
+
+extern enum rfds_mitigations rfds_mitigation;
+
/*
* Make previous memory operations globally visible before
* a WRMSR.
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index 80f6e70619cb..a2ba1a0ef872 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -483,14 +483,8 @@ early_param("mmio_stale_data", mmio_stale_data_parse_cmdline);
#undef pr_fmt
#define pr_fmt(fmt) "Register File Data Sampling: " fmt

-enum rfds_mitigations {
- RFDS_MITIGATION_OFF,
- RFDS_MITIGATION_VERW,
- RFDS_MITIGATION_UCODE_NEEDED,
-};
-
/* Default mitigation for Register File Data Sampling */
-static enum rfds_mitigations rfds_mitigation __ro_after_init =
+enum rfds_mitigations rfds_mitigation __ro_after_init =
IS_ENABLED(CONFIG_MITIGATION_RFDS) ? RFDS_MITIGATION_VERW : RFDS_MITIGATION_OFF;

static const char * const rfds_strings[] = {
diff --git a/arch/x86/kernel/keylocker.c b/arch/x86/kernel/keylocker.c
index 23cf4a235f11..09876693414c 100644
--- a/arch/x86/kernel/keylocker.c
+++ b/arch/x86/kernel/keylocker.c
@@ -119,6 +119,9 @@ static bool __init secure_keylocker(void)
if (boot_cpu_has_bug(X86_BUG_GDS) && !gds_ucode_mitigated(MITG_LOCKED))
return false;

+ if (boot_cpu_has_bug(X86_BUG_RFDS) && rfds_mitigation != RFDS_MITIGATION_VERW)
+ return false;
+
return true;
}

--
2.40.1