From 0f2a83859cec182c7c504ffe286a58e35b9dffb7 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 5 May 2020 02:07:33 +0100 Subject: [PATCH 01/17] [x86] Add support for mitigation of SRBDS (CVE-2020-0543) Apply the current version of the backport to 4.19. --- debian/changelog | 13 + ...steppings-field-to-struct-x86_cpu_id.patch | 120 ++++++ ...pu-Add-table-argument-to-cpu_matches.patch | 92 +++++ ...Add-Special-Register-Buffer-Data-Sam.patch | 383 ++++++++++++++++++ ...Add-SRBDS-vulnerability-and-mitigati.patch | 185 +++++++++ ...tion-Add-Ivy-Bridge-to-affected-list.patch | 39 ++ debian/patches/series | 5 + 7 files changed, 837 insertions(+) create mode 100644 debian/patches/bugfix/x86/srbds/0001-x86-cpu-Add-a-steppings-field-to-struct-x86_cpu_id.patch create mode 100644 debian/patches/bugfix/x86/srbds/0002-x86-cpu-Add-table-argument-to-cpu_matches.patch create mode 100644 debian/patches/bugfix/x86/srbds/0003-x86-speculation-Add-Special-Register-Buffer-Data-Sam.patch create mode 100644 debian/patches/bugfix/x86/srbds/0004-x86-speculation-Add-SRBDS-vulnerability-and-mitigati.patch create mode 100644 debian/patches/bugfix/x86/srbds/0005-x86-speculation-Add-Ivy-Bridge-to-affected-list.patch diff --git a/debian/changelog b/debian/changelog index 6cac52587..01ded5bde 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,16 @@ +linux (4.19.118-2+deb10u1) UNRELEASED; urgency=medium + + * [x86] Add support for mitigation of Special Register Buffer Data Sampling + (SRBDS) (CVE-2020-0543): + - x86/cpu: Add a steppings field to struct x86_cpu_id + - x86/cpu: Add 'table' argument to cpu_matches() + - x86/speculation: Add Special Register Buffer Data Sampling (SRBDS) + mitigation + - x86/speculation: Add SRBDS vulnerability and mitigation documentation + - x86/speculation: Add Ivy Bridge to affected list + + -- Ben Hutchings Tue, 05 May 2020 02:03:59 +0100 + linux (4.19.118-2) buster; urgency=medium * Merge changes from 4.19.67-2+deb10u2 to include all security fixes from diff --git a/debian/patches/bugfix/x86/srbds/0001-x86-cpu-Add-a-steppings-field-to-struct-x86_cpu_id.patch b/debian/patches/bugfix/x86/srbds/0001-x86-cpu-Add-a-steppings-field-to-struct-x86_cpu_id.patch new file mode 100644 index 000000000..dcbbf2f29 --- /dev/null +++ b/debian/patches/bugfix/x86/srbds/0001-x86-cpu-Add-a-steppings-field-to-struct-x86_cpu_id.patch @@ -0,0 +1,120 @@ +From: Mark Gross +Date: Thu, 16 Apr 2020 17:23:10 +0200 +Subject: [1/5] x86/cpu: Add a steppings field to struct x86_cpu_id +Origin: https://git.kernel.org/linus/e9d7144597b10ff13ff2264c059f7d4a7fbc89ac +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2020-0543 + +Intel uses the same family/model for several CPUs. Sometimes the +stepping must be checked to tell them apart. + +On x86 there can be at most 16 steppings. Add a steppings bitmask to +x86_cpu_id and a X86_MATCH_VENDOR_FAMILY_MODEL_STEPPING_FEATURE macro +and support for matching against family/model/stepping. + + [ bp: Massage. + tglx: Lightweight variant for backporting ] + +Signed-off-by: Mark Gross +Signed-off-by: Borislav Petkov +Signed-off-by: Thomas Gleixner +Reviewed-by: Tony Luck +Reviewed-by: Josh Poimboeuf +--- + arch/x86/include/asm/cpu_device_id.h | 27 +++++++++++++++++++++++++++ + arch/x86/kernel/cpu/match.c | 7 ++++++- + include/linux/mod_devicetable.h | 6 ++++++ + 3 files changed, 39 insertions(+), 1 deletion(-) + +diff --git a/arch/x86/include/asm/cpu_device_id.h b/arch/x86/include/asm/cpu_device_id.h +index baeba0567126..884466592943 100644 +--- a/arch/x86/include/asm/cpu_device_id.h ++++ b/arch/x86/include/asm/cpu_device_id.h +@@ -9,6 +9,33 @@ + + #include + ++#define X86_STEPPINGS(mins, maxs) GENMASK(maxs, mins) ++ ++/** ++ * X86_MATCH_VENDOR_FAM_MODEL_STEPPINGS_FEATURE - Base macro for CPU matching ++ * @_vendor: The vendor name, e.g. INTEL, AMD, HYGON, ..., ANY ++ * The name is expanded to X86_VENDOR_@_vendor ++ * @_family: The family number or X86_FAMILY_ANY ++ * @_model: The model number, model constant or X86_MODEL_ANY ++ * @_steppings: Bitmask for steppings, stepping constant or X86_STEPPING_ANY ++ * @_feature: A X86_FEATURE bit or X86_FEATURE_ANY ++ * @_data: Driver specific data or NULL. The internal storage ++ * format is unsigned long. The supplied value, pointer ++ * etc. is casted to unsigned long internally. ++ * ++ * Backport version to keep the SRBDS pile consistant. No shorter variants ++ * required for this. ++ */ ++#define X86_MATCH_VENDOR_FAM_MODEL_STEPPINGS_FEATURE(_vendor, _family, _model, \ ++ _steppings, _feature, _data) { \ ++ .vendor = X86_VENDOR_##_vendor, \ ++ .family = _family, \ ++ .model = _model, \ ++ .steppings = _steppings, \ ++ .feature = _feature, \ ++ .driver_data = (unsigned long) _data \ ++} ++ + extern const struct x86_cpu_id *x86_match_cpu(const struct x86_cpu_id *match); + + #endif +diff --git a/arch/x86/kernel/cpu/match.c b/arch/x86/kernel/cpu/match.c +index 3fed38812eea..751e59057466 100644 +--- a/arch/x86/kernel/cpu/match.c ++++ b/arch/x86/kernel/cpu/match.c +@@ -34,13 +34,18 @@ const struct x86_cpu_id *x86_match_cpu(const struct x86_cpu_id *match) + const struct x86_cpu_id *m; + struct cpuinfo_x86 *c = &boot_cpu_data; + +- for (m = match; m->vendor | m->family | m->model | m->feature; m++) { ++ for (m = match; ++ m->vendor | m->family | m->model | m->steppings | m->feature; ++ m++) { + if (m->vendor != X86_VENDOR_ANY && c->x86_vendor != m->vendor) + continue; + if (m->family != X86_FAMILY_ANY && c->x86 != m->family) + continue; + if (m->model != X86_MODEL_ANY && c->x86_model != m->model) + continue; ++ if (m->steppings != X86_STEPPING_ANY && ++ !(BIT(c->x86_stepping) & m->steppings)) ++ continue; + if (m->feature != X86_FEATURE_ANY && !cpu_has(c, m->feature)) + continue; + return m; +diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h +index 867db9b9384c..84e4e20352d9 100644 +--- a/include/linux/mod_devicetable.h ++++ b/include/linux/mod_devicetable.h +@@ -621,6 +621,10 @@ struct mips_cdmm_device_id { + /* + * MODULE_DEVICE_TABLE expects this struct to be called x86cpu_device_id. + * Although gcc seems to ignore this error, clang fails without this define. ++ * ++ * Note: The ordering of the struct is different from upstream because the ++ * static initializers in kernels < 5.7 still use C89 style while upstream ++ * has been converted to proper C99 initializers. + */ + #define x86cpu_device_id x86_cpu_id + struct x86_cpu_id { +@@ -629,6 +633,7 @@ struct x86_cpu_id { + __u16 model; + __u16 feature; /* bit index */ + kernel_ulong_t driver_data; ++ __u16 steppings; + }; + + #define X86_FEATURE_MATCH(x) \ +@@ -637,6 +642,7 @@ struct x86_cpu_id { + #define X86_VENDOR_ANY 0xffff + #define X86_FAMILY_ANY 0 + #define X86_MODEL_ANY 0 ++#define X86_STEPPING_ANY 0 + #define X86_FEATURE_ANY 0 /* Same as FPU, you can't test for that */ + + /* diff --git a/debian/patches/bugfix/x86/srbds/0002-x86-cpu-Add-table-argument-to-cpu_matches.patch b/debian/patches/bugfix/x86/srbds/0002-x86-cpu-Add-table-argument-to-cpu_matches.patch new file mode 100644 index 000000000..fe960c37d --- /dev/null +++ b/debian/patches/bugfix/x86/srbds/0002-x86-cpu-Add-table-argument-to-cpu_matches.patch @@ -0,0 +1,92 @@ +From: Mark Gross +Date: Thu, 16 Apr 2020 17:32:42 +0200 +Subject: [2/5] x86/cpu: Add 'table' argument to cpu_matches() +Origin: https://git.kernel.org/linus/93920f61c2ad7edb01e63323832585796af75fc9 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2020-0543 + +To make cpu_matches() reusable for other matching tables, have it take a +pointer to a x86_cpu_id table as an argument. + + [ bp: Flip arguments order. ] + +Signed-off-by: Mark Gross +Signed-off-by: Borislav Petkov +Signed-off-by: Thomas Gleixner +Reviewed-by: Josh Poimboeuf +--- + arch/x86/kernel/cpu/common.c | 23 +++++++++++++---------- + 1 file changed, 13 insertions(+), 10 deletions(-) + +diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c +index 7f43eba8d0c1..375e1d459b68 100644 +--- a/arch/x86/kernel/cpu/common.c ++++ b/arch/x86/kernel/cpu/common.c +@@ -1013,9 +1013,9 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = { + {} + }; + +-static bool __init cpu_matches(unsigned long which) ++static bool __init cpu_matches(const struct x86_cpu_id *table, unsigned long which) + { +- const struct x86_cpu_id *m = x86_match_cpu(cpu_vuln_whitelist); ++ const struct x86_cpu_id *m = x86_match_cpu(table); + + return m && !!(m->driver_data & which); + } +@@ -1035,29 +1035,32 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c) + u64 ia32_cap = x86_read_arch_cap_msr(); + + /* Set ITLB_MULTIHIT bug if cpu is not in the whitelist and not mitigated */ +- if (!cpu_matches(NO_ITLB_MULTIHIT) && !(ia32_cap & ARCH_CAP_PSCHANGE_MC_NO)) ++ if (!cpu_matches(cpu_vuln_whitelist, NO_ITLB_MULTIHIT) && ++ !(ia32_cap & ARCH_CAP_PSCHANGE_MC_NO)) + setup_force_cpu_bug(X86_BUG_ITLB_MULTIHIT); + +- if (cpu_matches(NO_SPECULATION)) ++ if (cpu_matches(cpu_vuln_whitelist, NO_SPECULATION)) + return; + + setup_force_cpu_bug(X86_BUG_SPECTRE_V1); + setup_force_cpu_bug(X86_BUG_SPECTRE_V2); + +- if (!cpu_matches(NO_SSB) && !(ia32_cap & ARCH_CAP_SSB_NO) && ++ if (!cpu_matches(cpu_vuln_whitelist, NO_SSB) && ++ !(ia32_cap & ARCH_CAP_SSB_NO) && + !cpu_has(c, X86_FEATURE_AMD_SSB_NO)) + setup_force_cpu_bug(X86_BUG_SPEC_STORE_BYPASS); + + if (ia32_cap & ARCH_CAP_IBRS_ALL) + setup_force_cpu_cap(X86_FEATURE_IBRS_ENHANCED); + +- if (!cpu_matches(NO_MDS) && !(ia32_cap & ARCH_CAP_MDS_NO)) { ++ if (!cpu_matches(cpu_vuln_whitelist, NO_MDS) && ++ !(ia32_cap & ARCH_CAP_MDS_NO)) { + setup_force_cpu_bug(X86_BUG_MDS); +- if (cpu_matches(MSBDS_ONLY)) ++ if (cpu_matches(cpu_vuln_whitelist, MSBDS_ONLY)) + setup_force_cpu_bug(X86_BUG_MSBDS_ONLY); + } + +- if (!cpu_matches(NO_SWAPGS)) ++ if (!cpu_matches(cpu_vuln_whitelist, NO_SWAPGS)) + setup_force_cpu_bug(X86_BUG_SWAPGS); + + /* +@@ -1075,7 +1078,7 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c) + (ia32_cap & ARCH_CAP_TSX_CTRL_MSR))) + setup_force_cpu_bug(X86_BUG_TAA); + +- if (cpu_matches(NO_MELTDOWN)) ++ if (cpu_matches(cpu_vuln_whitelist, NO_MELTDOWN)) + return; + + /* Rogue Data Cache Load? No! */ +@@ -1084,7 +1087,7 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c) + + setup_force_cpu_bug(X86_BUG_CPU_MELTDOWN); + +- if (cpu_matches(NO_L1TF)) ++ if (cpu_matches(cpu_vuln_whitelist, NO_L1TF)) + return; + + setup_force_cpu_bug(X86_BUG_L1TF); diff --git a/debian/patches/bugfix/x86/srbds/0003-x86-speculation-Add-Special-Register-Buffer-Data-Sam.patch b/debian/patches/bugfix/x86/srbds/0003-x86-speculation-Add-Special-Register-Buffer-Data-Sam.patch new file mode 100644 index 000000000..f15d9b200 --- /dev/null +++ b/debian/patches/bugfix/x86/srbds/0003-x86-speculation-Add-Special-Register-Buffer-Data-Sam.patch @@ -0,0 +1,383 @@ +From: Mark Gross +Date: Thu, 16 Apr 2020 17:54:04 +0200 +Subject: [3/5] x86/speculation: Add Special Register Buffer Data Sampling + (SRBDS) mitigation +Origin: https://git.kernel.org/linus/7e5b3c267d256822407a22fdce6afdf9cd13f9fb +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2020-0543 + +SRBDS is an MDS-like speculative side channel that can leak bits from the +random number generator (RNG) across cores and threads. New microcode +serializes the processor access during the execution of RDRAND and +RDSEED. This ensures that the shared buffer is overwritten before it is +released for reuse. + +While it is present on all affected CPU models, the microcode mitigation +is not needed on models that enumerate ARCH_CAPABILITIES[MDS_NO] in the +cases where TSX is not supported or has been disabled with TSX_CTRL. + +The mitigation is activated by default on affected processors and it +increases latency for RDRAND and RDSEED instructions. Among other +effects this will reduce throughput from /dev/urandom. + +* Enable administrator to configure the mitigation off when desired using + either mitigations=off or srbds=off. + +* Export vulnerability status via sysfs + +* Rename file-scoped macros to apply for non-whitelist table initializations. + + [ bp: Massage, + - s/VULNBL_INTEL_STEPPING/VULNBL_INTEL_STEPPINGS/g, + - do not read arch cap MSR a second time in tsx_fused_off() - just pass it in, + - flip check in cpu_set_bug_bits() to save an indentation level, + - reflow comments. + jpoimboe: s/Mitigated/Mitigation/ in user-visible strings + tglx: Dropped the fused off magic for now + ] + +Signed-off-by: Mark Gross +Signed-off-by: Borislav Petkov +Signed-off-by: Thomas Gleixner +Reviewed-by: Tony Luck +Reviewed-by: Pawan Gupta +Reviewed-by: Josh Poimboeuf +Tested-by: Neelima Krishnan +--- + .../ABI/testing/sysfs-devices-system-cpu | 1 + + .../admin-guide/kernel-parameters.txt | 20 ++++ + arch/x86/include/asm/cpufeatures.h | 2 + + arch/x86/include/asm/msr-index.h | 4 + + arch/x86/kernel/cpu/bugs.c | 106 ++++++++++++++++++ + arch/x86/kernel/cpu/common.c | 31 +++++ + arch/x86/kernel/cpu/cpu.h | 1 + + drivers/base/cpu.c | 8 ++ + 8 files changed, 173 insertions(+) + +diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu b/Documentation/ABI/testing/sysfs-devices-system-cpu +index b492fb6057c9..b9c14c11efc5 100644 +--- a/Documentation/ABI/testing/sysfs-devices-system-cpu ++++ b/Documentation/ABI/testing/sysfs-devices-system-cpu +@@ -478,6 +478,7 @@ What: /sys/devices/system/cpu/vulnerabilities + /sys/devices/system/cpu/vulnerabilities/spec_store_bypass + /sys/devices/system/cpu/vulnerabilities/l1tf + /sys/devices/system/cpu/vulnerabilities/mds ++ /sys/devices/system/cpu/vulnerabilities/srbds + /sys/devices/system/cpu/vulnerabilities/tsx_async_abort + /sys/devices/system/cpu/vulnerabilities/itlb_multihit + Date: January 2018 +diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt +index 1a5101b7e853..30752db57587 100644 +--- a/Documentation/admin-guide/kernel-parameters.txt ++++ b/Documentation/admin-guide/kernel-parameters.txt +@@ -4415,6 +4415,26 @@ + spia_pedr= + spia_peddr= + ++ srbds= [X86,INTEL] ++ Control the Special Register Buffer Data Sampling ++ (SRBDS) mitigation. ++ ++ Certain CPUs are vulnerable to an MDS-like ++ exploit which can leak bits from the random ++ number generator. ++ ++ By default, this issue is mitigated by ++ microcode. However, the microcode fix can cause ++ the RDRAND and RDSEED instructions to become ++ much slower. Among other effects, this will ++ result in reduced throughput from /dev/urandom. ++ ++ The microcode mitigation can be disabled with ++ the following option: ++ ++ off: Disable mitigation and remove ++ performance impact to RDRAND and RDSEED ++ + srcutree.counter_wrap_check [KNL] + Specifies how frequently to check for + grace-period sequence counter wrap for the +diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h +index 8c13b99b9507..9f03ac233566 100644 +--- a/arch/x86/include/asm/cpufeatures.h ++++ b/arch/x86/include/asm/cpufeatures.h +@@ -347,6 +347,7 @@ + /* Intel-defined CPU features, CPUID level 0x00000007:0 (EDX), word 18 */ + #define X86_FEATURE_AVX512_4VNNIW (18*32+ 2) /* AVX-512 Neural Network Instructions */ + #define X86_FEATURE_AVX512_4FMAPS (18*32+ 3) /* AVX-512 Multiply Accumulation Single precision */ ++#define X86_FEATURE_SRBDS_CTRL (18*32+ 9) /* "" SRBDS mitigation MSR available */ + #define X86_FEATURE_TSX_FORCE_ABORT (18*32+13) /* "" TSX_FORCE_ABORT */ + #define X86_FEATURE_MD_CLEAR (18*32+10) /* VERW clears CPU buffers */ + #define X86_FEATURE_PCONFIG (18*32+18) /* Intel PCONFIG */ +@@ -391,5 +392,6 @@ + #define X86_BUG_SWAPGS X86_BUG(21) /* CPU is affected by speculation through SWAPGS */ + #define X86_BUG_TAA X86_BUG(22) /* CPU is affected by TSX Async Abort(TAA) */ + #define X86_BUG_ITLB_MULTIHIT X86_BUG(23) /* CPU may incur MCE during certain page attribute changes */ ++#define X86_BUG_SRBDS X86_BUG(24) /* CPU may leak RNG bits if not mitigated */ + + #endif /* _ASM_X86_CPUFEATURES_H */ +diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h +index d2c25a13e1ce..5bb11a8c245e 100644 +--- a/arch/x86/include/asm/msr-index.h ++++ b/arch/x86/include/asm/msr-index.h +@@ -110,6 +110,10 @@ + #define TSX_CTRL_RTM_DISABLE BIT(0) /* Disable RTM feature */ + #define TSX_CTRL_CPUID_CLEAR BIT(1) /* Disable TSX enumeration */ + ++/* SRBDS support */ ++#define MSR_IA32_MCU_OPT_CTRL 0x00000123 ++#define RNGDS_MITG_DIS BIT(0) ++ + #define MSR_IA32_SYSENTER_CS 0x00000174 + #define MSR_IA32_SYSENTER_ESP 0x00000175 + #define MSR_IA32_SYSENTER_EIP 0x00000176 +diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c +index 2d23a448e72d..cf07437cd106 100644 +--- a/arch/x86/kernel/cpu/bugs.c ++++ b/arch/x86/kernel/cpu/bugs.c +@@ -41,6 +41,7 @@ static void __init l1tf_select_mitigation(void); + static void __init mds_select_mitigation(void); + static void __init mds_print_mitigation(void); + static void __init taa_select_mitigation(void); ++static void __init srbds_select_mitigation(void); + + /* The base value of the SPEC_CTRL MSR that always has to be preserved. */ + u64 x86_spec_ctrl_base; +@@ -108,6 +109,7 @@ void __init check_bugs(void) + l1tf_select_mitigation(); + mds_select_mitigation(); + taa_select_mitigation(); ++ srbds_select_mitigation(); + + /* + * As MDS and TAA mitigations are inter-related, print MDS +@@ -390,6 +392,97 @@ static int __init tsx_async_abort_parse_cmdline(char *str) + } + early_param("tsx_async_abort", tsx_async_abort_parse_cmdline); + ++#undef pr_fmt ++#define pr_fmt(fmt) "SRBDS: " fmt ++ ++enum srbds_mitigations { ++ SRBDS_MITIGATION_OFF, ++ SRBDS_MITIGATION_UCODE_NEEDED, ++ SRBDS_MITIGATION_FULL, ++ SRBDS_MITIGATION_TSX_OFF, ++ SRBDS_MITIGATION_HYPERVISOR, ++}; ++ ++static enum srbds_mitigations srbds_mitigation __ro_after_init = SRBDS_MITIGATION_FULL; ++ ++static const char * const srbds_strings[] = { ++ [SRBDS_MITIGATION_OFF] = "Vulnerable", ++ [SRBDS_MITIGATION_UCODE_NEEDED] = "Vulnerable: No microcode", ++ [SRBDS_MITIGATION_FULL] = "Mitigation: Microcode", ++ [SRBDS_MITIGATION_TSX_OFF] = "Mitigation: TSX disabled", ++ [SRBDS_MITIGATION_HYPERVISOR] = "Unknown: Dependent on hypervisor status", ++}; ++ ++static bool srbds_off; ++ ++void update_srbds_msr(void) ++{ ++ u64 mcu_ctrl; ++ ++ if (!boot_cpu_has_bug(X86_BUG_SRBDS)) ++ return; ++ ++ if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) ++ return; ++ ++ if (srbds_mitigation == SRBDS_MITIGATION_UCODE_NEEDED) ++ return; ++ ++ rdmsrl(MSR_IA32_MCU_OPT_CTRL, mcu_ctrl); ++ ++ switch (srbds_mitigation) { ++ case SRBDS_MITIGATION_OFF: ++ case SRBDS_MITIGATION_TSX_OFF: ++ mcu_ctrl |= RNGDS_MITG_DIS; ++ break; ++ case SRBDS_MITIGATION_FULL: ++ mcu_ctrl &= ~RNGDS_MITG_DIS; ++ break; ++ default: ++ break; ++ } ++ ++ wrmsrl(MSR_IA32_MCU_OPT_CTRL, mcu_ctrl); ++} ++ ++static void __init srbds_select_mitigation(void) ++{ ++ u64 ia32_cap; ++ ++ if (!boot_cpu_has_bug(X86_BUG_SRBDS)) ++ return; ++ ++ /* ++ * Check to see if this is one of the MDS_NO systems supporting ++ * TSX that are only exposed to SRBDS when TSX is enabled. ++ */ ++ ia32_cap = x86_read_arch_cap_msr(); ++ if ((ia32_cap & ARCH_CAP_MDS_NO) && !boot_cpu_has(X86_FEATURE_RTM)) ++ srbds_mitigation = SRBDS_MITIGATION_TSX_OFF; ++ else if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) ++ srbds_mitigation = SRBDS_MITIGATION_HYPERVISOR; ++ else if (!boot_cpu_has(X86_FEATURE_SRBDS_CTRL)) ++ srbds_mitigation = SRBDS_MITIGATION_UCODE_NEEDED; ++ else if (cpu_mitigations_off() || srbds_off) ++ srbds_mitigation = SRBDS_MITIGATION_OFF; ++ ++ update_srbds_msr(); ++ pr_info("%s\n", srbds_strings[srbds_mitigation]); ++} ++ ++static int __init srbds_parse_cmdline(char *str) ++{ ++ if (!str) ++ return -EINVAL; ++ ++ if (!boot_cpu_has_bug(X86_BUG_SRBDS)) ++ return 0; ++ ++ srbds_off = !strcmp(str, "off"); ++ return 0; ++} ++early_param("srbds", srbds_parse_cmdline); ++ + #undef pr_fmt + #define pr_fmt(fmt) "Spectre V1 : " fmt + +@@ -1491,6 +1584,11 @@ static char *ibpb_state(void) + return ""; + } + ++static ssize_t srbds_show_state(char *buf) ++{ ++ return sprintf(buf, "%s\n", srbds_strings[srbds_mitigation]); ++} ++ + static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr, + char *buf, unsigned int bug) + { +@@ -1535,6 +1633,9 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr + case X86_BUG_ITLB_MULTIHIT: + return itlb_multihit_show_state(buf); + ++ case X86_BUG_SRBDS: ++ return srbds_show_state(buf); ++ + default: + break; + } +@@ -1581,4 +1682,9 @@ ssize_t cpu_show_itlb_multihit(struct device *dev, struct device_attribute *attr + { + return cpu_show_common(dev, attr, buf, X86_BUG_ITLB_MULTIHIT); + } ++ ++ssize_t cpu_show_srbds(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ return cpu_show_common(dev, attr, buf, X86_BUG_SRBDS); ++} + #endif +diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c +index 375e1d459b68..2058e8c0e61d 100644 +--- a/arch/x86/kernel/cpu/common.c ++++ b/arch/x86/kernel/cpu/common.c +@@ -1013,6 +1013,27 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = { + {} + }; + ++#define VULNBL_INTEL_STEPPINGS(model, steppings, issues) \ ++ X86_MATCH_VENDOR_FAM_MODEL_STEPPINGS_FEATURE(INTEL, 6, \ ++ INTEL_FAM6_##model, steppings, \ ++ X86_FEATURE_ANY, issues) ++ ++#define SRBDS BIT(0) ++ ++static const struct x86_cpu_id cpu_vuln_blacklist[] __initconst = { ++ VULNBL_INTEL_STEPPINGS(IVYBRIDGE, X86_STEPPING_ANY, SRBDS), ++ VULNBL_INTEL_STEPPINGS(HASWELL_CORE, X86_STEPPING_ANY, SRBDS), ++ VULNBL_INTEL_STEPPINGS(HASWELL_ULT, X86_STEPPING_ANY, SRBDS), ++ VULNBL_INTEL_STEPPINGS(HASWELL_GT3E, X86_STEPPING_ANY, SRBDS), ++ VULNBL_INTEL_STEPPINGS(BROADWELL_GT3E, X86_STEPPING_ANY, SRBDS), ++ VULNBL_INTEL_STEPPINGS(BROADWELL_CORE, X86_STEPPING_ANY, SRBDS), ++ VULNBL_INTEL_STEPPINGS(SKYLAKE_MOBILE, X86_STEPPING_ANY, SRBDS), ++ VULNBL_INTEL_STEPPINGS(SKYLAKE_DESKTOP, X86_STEPPING_ANY, SRBDS), ++ VULNBL_INTEL_STEPPINGS(KABYLAKE_MOBILE, X86_STEPPINGS(0x0, 0xC), SRBDS), ++ VULNBL_INTEL_STEPPINGS(KABYLAKE_DESKTOP,X86_STEPPINGS(0x0, 0xD), SRBDS), ++ {} ++}; ++ + static bool __init cpu_matches(const struct x86_cpu_id *table, unsigned long which) + { + const struct x86_cpu_id *m = x86_match_cpu(table); +@@ -1078,6 +1099,15 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c) + (ia32_cap & ARCH_CAP_TSX_CTRL_MSR))) + setup_force_cpu_bug(X86_BUG_TAA); + ++ /* ++ * SRBDS affects CPUs which support RDRAND or RDSEED and are listed ++ * in the vulnerability blacklist. ++ */ ++ if ((cpu_has(c, X86_FEATURE_RDRAND) || ++ cpu_has(c, X86_FEATURE_RDSEED)) && ++ cpu_matches(cpu_vuln_blacklist, SRBDS)) ++ setup_force_cpu_bug(X86_BUG_SRBDS); ++ + if (cpu_matches(cpu_vuln_whitelist, NO_MELTDOWN)) + return; + +@@ -1522,6 +1552,7 @@ void identify_secondary_cpu(struct cpuinfo_x86 *c) + mtrr_ap_init(); + validate_apic_and_package_id(c); + x86_spec_ctrl_setup_ap(); ++ update_srbds_msr(); + } + + static __init int setup_noclflush(char *arg) +diff --git a/arch/x86/kernel/cpu/cpu.h b/arch/x86/kernel/cpu/cpu.h +index 236582c90d3f..e89602d2aff5 100644 +--- a/arch/x86/kernel/cpu/cpu.h ++++ b/arch/x86/kernel/cpu/cpu.h +@@ -80,6 +80,7 @@ extern void detect_ht(struct cpuinfo_x86 *c); + unsigned int aperfmperf_get_khz(int cpu); + + extern void x86_spec_ctrl_setup_ap(void); ++extern void update_srbds_msr(void); + + extern u64 x86_read_arch_cap_msr(void); + +diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c +index f3ecf7418ed4..1df057486176 100644 +--- a/drivers/base/cpu.c ++++ b/drivers/base/cpu.c +@@ -565,6 +565,12 @@ ssize_t __weak cpu_show_itlb_multihit(struct device *dev, + return sprintf(buf, "Not affected\n"); + } + ++ssize_t __weak cpu_show_srbds(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ return sprintf(buf, "Not affected\n"); ++} ++ + static DEVICE_ATTR(meltdown, 0444, cpu_show_meltdown, NULL); + static DEVICE_ATTR(spectre_v1, 0444, cpu_show_spectre_v1, NULL); + static DEVICE_ATTR(spectre_v2, 0444, cpu_show_spectre_v2, NULL); +@@ -573,6 +579,7 @@ static DEVICE_ATTR(l1tf, 0444, cpu_show_l1tf, NULL); + static DEVICE_ATTR(mds, 0444, cpu_show_mds, NULL); + static DEVICE_ATTR(tsx_async_abort, 0444, cpu_show_tsx_async_abort, NULL); + static DEVICE_ATTR(itlb_multihit, 0444, cpu_show_itlb_multihit, NULL); ++static DEVICE_ATTR(srbds, 0444, cpu_show_srbds, NULL); + + static struct attribute *cpu_root_vulnerabilities_attrs[] = { + &dev_attr_meltdown.attr, +@@ -583,6 +590,7 @@ static struct attribute *cpu_root_vulnerabilities_attrs[] = { + &dev_attr_mds.attr, + &dev_attr_tsx_async_abort.attr, + &dev_attr_itlb_multihit.attr, ++ &dev_attr_srbds.attr, + NULL + }; + diff --git a/debian/patches/bugfix/x86/srbds/0004-x86-speculation-Add-SRBDS-vulnerability-and-mitigati.patch b/debian/patches/bugfix/x86/srbds/0004-x86-speculation-Add-SRBDS-vulnerability-and-mitigati.patch new file mode 100644 index 000000000..08adbaa12 --- /dev/null +++ b/debian/patches/bugfix/x86/srbds/0004-x86-speculation-Add-SRBDS-vulnerability-and-mitigati.patch @@ -0,0 +1,185 @@ +From: Mark Gross +Date: Thu, 16 Apr 2020 18:21:51 +0200 +Subject: [4/5] x86/speculation: Add SRBDS vulnerability and mitigation + documentation +Origin: https://git.kernel.org/linus/7222a1b5b87417f22265c92deea76a6aecd0fb0f +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2020-0543 + +Add documentation for the SRBDS vulnerability and its mitigation. + + [ bp: Massage. + jpoimboe: sysfs table strings. ] + +Signed-off-by: Mark Gross +Signed-off-by: Borislav Petkov +Reviewed-by: Tony Luck +Reviewed-by: Josh Poimboeuf +--- + Documentation/admin-guide/hw-vuln/index.rst | 1 + + .../special-register-buffer-data-sampling.rst | 148 ++++++++++++++++++ + 2 files changed, 149 insertions(+) + create mode 100644 Documentation/admin-guide/hw-vuln/special-register-buffer-data-sampling.rst + +diff --git a/Documentation/admin-guide/hw-vuln/index.rst b/Documentation/admin-guide/hw-vuln/index.rst +index 0795e3c2643f..ca4dbdd9016d 100644 +--- a/Documentation/admin-guide/hw-vuln/index.rst ++++ b/Documentation/admin-guide/hw-vuln/index.rst +@@ -14,3 +14,4 @@ are configurable at compile, boot or run time. + mds + tsx_async_abort + multihit.rst ++ special-register-buffer-data-sampling.rst +diff --git a/Documentation/admin-guide/hw-vuln/special-register-buffer-data-sampling.rst b/Documentation/admin-guide/hw-vuln/special-register-buffer-data-sampling.rst +new file mode 100644 +index 000000000000..6a473da80b62 +--- /dev/null ++++ b/Documentation/admin-guide/hw-vuln/special-register-buffer-data-sampling.rst +@@ -0,0 +1,148 @@ ++.. SPDX-License-Identifier: GPL-2.0 ++ ++SRBDS - Special Register Buffer Data Sampling ++============================================= ++ ++SRBDS is a hardware vulnerability that allows MDS :doc:`mds` techniques to ++infer values returned from special register accesses. Special register ++accesses are accesses to off core registers. According to Intel's evaluation, ++the special register reads that have a security expectation of privacy are ++RDRAND, RDSEED and SGX EGETKEY. ++ ++When RDRAND, RDSEED and EGETKEY instructions are used, the data is moved ++to the core through the special register mechanism that is susceptible ++to MDS attacks. ++ ++Affected processors ++-------------------- ++Core models (desktop, mobile, Xeon-E3) that implement RDRAND and/or RDSEED may ++be affected. ++ ++A processor is affected by SRBDS if its Family_Model and stepping is ++in the following list, with the exception of the listed processors ++exporting MDS_NO while Intel TSX is available yet not enabled. The ++latter class of processors are only affected when Intel TSX is enabled ++by software using TSX_CTRL_MSR otherwise they are not affected. ++ ++ ============= ============ ======== ++ common name Family_Model Stepping ++ ============= ============ ======== ++ Haswell 06_3CH All ++ Haswell_L 06_45H All ++ Haswell_G 06_46H All ++ ++ Broadwell_G 06_47H All ++ Broadwell 06_3DH All ++ ++ Skylake_L 06_4EH All ++ Skylake 06_5EH All ++ ++ Kabylake_L 06_8EH <=0xC ++ ++ Kabylake 06_9EH <=0xD ++ ============= ============ ======== ++ ++Related CVEs ++------------ ++ ++The following CVE entry is related to this SRBDS issue: ++ ++ ============== ===== ===================================== ++ CVE-2020-0543 SRBDS Special Register Buffer Data Sampling ++ ============== ===== ===================================== ++ ++Attack scenarios ++---------------- ++An unprivileged user can extract values returned from RDRAND and RDSEED ++executed on another core or sibling thread using MDS techniques. ++ ++ ++Mitigation mechanism ++------------------- ++Intel will release microcode updates that modify the RDRAND, RDSEED, and ++EGETKEY instructions to overwrite secret special register data in the shared ++staging buffer before the secret data can be accessed by another logical ++processor. ++ ++During execution of the RDRAND, RDSEED, or EGETKEY instructions, off-core ++accesses from other logical processors will be delayed until the special ++register read is complete and the secret data in the shared staging buffer is ++overwritten. ++ ++This has three effects on performance: ++ ++#. RDRAND, RDSEED, or EGETKEY instructions have higher latency. ++ ++#. Executing RDRAND at the same time on multiple logical processors will be ++ serialized, resulting in an overall reduction in the maximum RDRAND ++ bandwidth. ++ ++#. Executing RDRAND, RDSEED or EGETKEY will delay memory accesses from other ++ logical processors that miss their core caches, with an impact similar to ++ legacy locked cache-line-split accesses. ++ ++The microcode updates provide an opt-out mechanism (RNGDS_MITG_DIS) to disable ++the mitigation for RDRAND and RDSEED instructions executed outside of Intel ++Software Guard Extensions (Intel SGX) enclaves. On logical processors that ++disable the mitigation using this opt-out mechanism, RDRAND and RDSEED do not ++take longer to execute and do not impact performance of sibling logical ++processors memory accesses. The opt-out mechanism does not affect Intel SGX ++enclaves (including execution of RDRAND or RDSEED inside an enclave, as well ++as EGETKEY execution). ++ ++IA32_MCU_OPT_CTRL MSR Definition ++-------------------------------- ++Along with the mitigation for this issue, Intel added a new thread-scope ++IA32_MCU_OPT_CTRL MSR, (address 0x123). The presence of this MSR and ++RNGDS_MITG_DIS (bit 0) is enumerated by CPUID.(EAX=07H,ECX=0).EDX[SRBDS_CTRL = ++9]==1. This MSR is introduced through the microcode update. ++ ++Setting IA32_MCU_OPT_CTRL[0] (RNGDS_MITG_DIS) to 1 for a logical processor ++disables the mitigation for RDRAND and RDSEED executed outside of an Intel SGX ++enclave on that logical processor. Opting out of the mitigation for a ++particular logical processor does not affect the RDRAND and RDSEED mitigations ++for other logical processors. ++ ++Note that inside of an Intel SGX enclave, the mitigation is applied regardless ++of the value of RNGDS_MITG_DS. ++ ++Mitigation control on the kernel command line ++--------------------------------------------- ++The kernel command line allows control over the SRBDS mitigation at boot time ++with the option "srbds=". The option for this is: ++ ++ ============= ============================================================= ++ off This option disables SRBDS mitigation for RDRAND and RDSEED on ++ affected platforms. ++ ============= ============================================================= ++ ++SRBDS System Information ++----------------------- ++The Linux kernel provides vulnerability status information through sysfs. For ++SRBDS this can be accessed by the following sysfs file: ++/sys/devices/system/cpu/vulnerabilities/srbds ++ ++The possible values contained in this file are: ++ ++ ============================== ============================================= ++ Not affected Processor not vulnerable ++ Vulnerable Processor vulnerable and mitigation disabled ++ Vulnerable: No microcode Processor vulnerable and microcode is missing ++ mitigation ++ Mitigation: Microcode Processor is vulnerable and mitigation is in ++ effect. ++ Mitigation: TSX disabled Processor is only vulnerable when TSX is ++ enabled while this system was booted with TSX ++ disabled. ++ Unknown: Dependent on ++ hypervisor status Running on virtual guest processor that is ++ affected but with no way to know if host ++ processor is mitigated or vulnerable. ++ ============================== ============================================= ++ ++SRBDS Default mitigation ++------------------------ ++This new microcode serializes processor access during execution of RDRAND, ++RDSEED ensures that the shared buffer is overwritten before it is released for ++reuse. Use the "srbds=off" kernel command line to disable the mitigation for ++RDRAND and RDSEED. diff --git a/debian/patches/bugfix/x86/srbds/0005-x86-speculation-Add-Ivy-Bridge-to-affected-list.patch b/debian/patches/bugfix/x86/srbds/0005-x86-speculation-Add-Ivy-Bridge-to-affected-list.patch new file mode 100644 index 000000000..42bd1823f --- /dev/null +++ b/debian/patches/bugfix/x86/srbds/0005-x86-speculation-Add-Ivy-Bridge-to-affected-list.patch @@ -0,0 +1,39 @@ +From: Josh Poimboeuf +Date: Mon, 27 Apr 2020 20:46:13 +0200 +Subject: [5/5] x86/speculation: Add Ivy Bridge to affected list +Origin: https://git.kernel.org/linus/3798cc4d106e91382bfe016caa2edada27c2bb3f +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2020-0543 + +Make the docs match the code. + +Signed-off-by: Josh Poimboeuf +Signed-off-by: Thomas Gleixner +--- + .../hw-vuln/special-register-buffer-data-sampling.rst | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/Documentation/admin-guide/hw-vuln/special-register-buffer-data-sampling.rst b/Documentation/admin-guide/hw-vuln/special-register-buffer-data-sampling.rst +index 6a473da80b62..47b1b3afac99 100644 +--- a/Documentation/admin-guide/hw-vuln/special-register-buffer-data-sampling.rst ++++ b/Documentation/admin-guide/hw-vuln/special-register-buffer-data-sampling.rst +@@ -27,6 +27,8 @@ by software using TSX_CTRL_MSR otherwise they are not affected. + ============= ============ ======== + common name Family_Model Stepping + ============= ============ ======== ++ IvyBridge 06_3AH All ++ + Haswell 06_3CH All + Haswell_L 06_45H All + Haswell_G 06_46H All +@@ -37,9 +39,8 @@ by software using TSX_CTRL_MSR otherwise they are not affected. + Skylake_L 06_4EH All + Skylake 06_5EH All + +- Kabylake_L 06_8EH <=0xC +- +- Kabylake 06_9EH <=0xD ++ Kabylake_L 06_8EH <= 0xC ++ Kabylake 06_9EH <= 0xD + ============= ============ ======== + + Related CVEs diff --git a/debian/patches/series b/debian/patches/series index c4eedde94..03e6594de 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -300,5 +300,10 @@ bugfix/all/net-ipv6_stub-use-ip6_dst_lookup_flow-instead-of-ip6.patch bugfix/all/blktrace-protect-q-blk_trace-with-rcu.patch bugfix/all/blktrace-fix-dereference-after-null-check.patch bugfix/s390x/s390-mm-fix-page-table-upgrade-vs-2ndary-address-mod.patch +bugfix/x86/srbds/0001-x86-cpu-Add-a-steppings-field-to-struct-x86_cpu_id.patch +bugfix/x86/srbds/0002-x86-cpu-Add-table-argument-to-cpu_matches.patch +bugfix/x86/srbds/0003-x86-speculation-Add-Special-Register-Buffer-Data-Sam.patch +bugfix/x86/srbds/0004-x86-speculation-Add-SRBDS-vulnerability-and-mitigati.patch +bugfix/x86/srbds/0005-x86-speculation-Add-Ivy-Bridge-to-affected-list.patch # ABI maintenance From 195b1745c4b5c7ac61d35228485d4f548d9ad3a2 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 5 May 2020 02:21:33 +0100 Subject: [PATCH 02/17] Avoid an ABI change for SRBDS Adding the x86_cpu_id::steppings field is an ABI change. It doesn't seem worth the trouble of another ABI bump just to be able to report some potential future CPU steppings as invulnerable. Until we have other change that require an ABI bump, we'll match the affected models regardless of stepping. Keep the reverted patch in the queue so that the reverting patch will continue to be applied when we rebase onto a new stable update. --- debian/changelog | 2 +- ...steppings-field-to-struct-x86_cpu_id.patch | 99 +++++++++++++++++++ ...6-speculation-do-not-match-steppings.patch | 27 +++++ debian/patches/series | 2 + 4 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 debian/patches/debian/abi/revert-x86-cpu-add-a-steppings-field-to-struct-x86_cpu_id.patch create mode 100644 debian/patches/debian/abi/x86-speculation-do-not-match-steppings.patch diff --git a/debian/changelog b/debian/changelog index 01ded5bde..ec8f7f3bd 100644 --- a/debian/changelog +++ b/debian/changelog @@ -2,12 +2,12 @@ linux (4.19.118-2+deb10u1) UNRELEASED; urgency=medium * [x86] Add support for mitigation of Special Register Buffer Data Sampling (SRBDS) (CVE-2020-0543): - - x86/cpu: Add a steppings field to struct x86_cpu_id - x86/cpu: Add 'table' argument to cpu_matches() - x86/speculation: Add Special Register Buffer Data Sampling (SRBDS) mitigation - x86/speculation: Add SRBDS vulnerability and mitigation documentation - x86/speculation: Add Ivy Bridge to affected list + * [x86] speculation: Do not match steppings, to avoid an ABI change -- Ben Hutchings Tue, 05 May 2020 02:03:59 +0100 diff --git a/debian/patches/debian/abi/revert-x86-cpu-add-a-steppings-field-to-struct-x86_cpu_id.patch b/debian/patches/debian/abi/revert-x86-cpu-add-a-steppings-field-to-struct-x86_cpu_id.patch new file mode 100644 index 000000000..12a76dd4d --- /dev/null +++ b/debian/patches/debian/abi/revert-x86-cpu-add-a-steppings-field-to-struct-x86_cpu_id.patch @@ -0,0 +1,99 @@ +From: Ben Hutchings +Date: Tue, 05 May 2020 02:19:23 +0100 +Subject: Revert "x86/cpu: Add a steppings field to struct x86_cpu_id" +Forwarded: not-needed + +Adding the x86_cpu_id::steppings field is an ABI change. It doesn't +seem worth the trouble of another ABI bump just to be able to report +some potential future CPU steppings as invulnerable. Until we have +other change that require an ABI bump, we'll match the affected models +regardless of stepping. + +--- +--- a/arch/x86/include/asm/cpu_device_id.h ++++ b/arch/x86/include/asm/cpu_device_id.h +@@ -9,33 +9,6 @@ + + #include + +-#define X86_STEPPINGS(mins, maxs) GENMASK(maxs, mins) +- +-/** +- * X86_MATCH_VENDOR_FAM_MODEL_STEPPINGS_FEATURE - Base macro for CPU matching +- * @_vendor: The vendor name, e.g. INTEL, AMD, HYGON, ..., ANY +- * The name is expanded to X86_VENDOR_@_vendor +- * @_family: The family number or X86_FAMILY_ANY +- * @_model: The model number, model constant or X86_MODEL_ANY +- * @_steppings: Bitmask for steppings, stepping constant or X86_STEPPING_ANY +- * @_feature: A X86_FEATURE bit or X86_FEATURE_ANY +- * @_data: Driver specific data or NULL. The internal storage +- * format is unsigned long. The supplied value, pointer +- * etc. is casted to unsigned long internally. +- * +- * Backport version to keep the SRBDS pile consistant. No shorter variants +- * required for this. +- */ +-#define X86_MATCH_VENDOR_FAM_MODEL_STEPPINGS_FEATURE(_vendor, _family, _model, \ +- _steppings, _feature, _data) { \ +- .vendor = X86_VENDOR_##_vendor, \ +- .family = _family, \ +- .model = _model, \ +- .steppings = _steppings, \ +- .feature = _feature, \ +- .driver_data = (unsigned long) _data \ +-} +- + extern const struct x86_cpu_id *x86_match_cpu(const struct x86_cpu_id *match); + + #endif +--- a/arch/x86/kernel/cpu/match.c ++++ b/arch/x86/kernel/cpu/match.c +@@ -34,18 +34,13 @@ const struct x86_cpu_id *x86_match_cpu(c + const struct x86_cpu_id *m; + struct cpuinfo_x86 *c = &boot_cpu_data; + +- for (m = match; +- m->vendor | m->family | m->model | m->steppings | m->feature; +- m++) { ++ for (m = match; m->vendor | m->family | m->model | m->feature; m++) { + if (m->vendor != X86_VENDOR_ANY && c->x86_vendor != m->vendor) + continue; + if (m->family != X86_FAMILY_ANY && c->x86 != m->family) + continue; + if (m->model != X86_MODEL_ANY && c->x86_model != m->model) + continue; +- if (m->steppings != X86_STEPPING_ANY && +- !(BIT(c->x86_stepping) & m->steppings)) +- continue; + if (m->feature != X86_FEATURE_ANY && !cpu_has(c, m->feature)) + continue; + return m; +--- a/include/linux/mod_devicetable.h ++++ b/include/linux/mod_devicetable.h +@@ -621,10 +621,6 @@ struct mips_cdmm_device_id { + /* + * MODULE_DEVICE_TABLE expects this struct to be called x86cpu_device_id. + * Although gcc seems to ignore this error, clang fails without this define. +- * +- * Note: The ordering of the struct is different from upstream because the +- * static initializers in kernels < 5.7 still use C89 style while upstream +- * has been converted to proper C99 initializers. + */ + #define x86cpu_device_id x86_cpu_id + struct x86_cpu_id { +@@ -633,7 +629,6 @@ struct x86_cpu_id { + __u16 model; + __u16 feature; /* bit index */ + kernel_ulong_t driver_data; +- __u16 steppings; + }; + + #define X86_FEATURE_MATCH(x) \ +@@ -642,7 +637,6 @@ struct x86_cpu_id { + #define X86_VENDOR_ANY 0xffff + #define X86_FAMILY_ANY 0 + #define X86_MODEL_ANY 0 +-#define X86_STEPPING_ANY 0 + #define X86_FEATURE_ANY 0 /* Same as FPU, you can't test for that */ + + /* diff --git a/debian/patches/debian/abi/x86-speculation-do-not-match-steppings.patch b/debian/patches/debian/abi/x86-speculation-do-not-match-steppings.patch new file mode 100644 index 000000000..a0cc5f521 --- /dev/null +++ b/debian/patches/debian/abi/x86-speculation-do-not-match-steppings.patch @@ -0,0 +1,27 @@ +From: Ben Hutchings +Date: Tue, 05 May 2020 02:09:56 +0100 +Subject: x86/speculation: Do not match steppings +Forwarded: not-needed + +Adding the x86_cpu_id::steppings field is an ABI change. It doesn't +seem worth the trouble of another ABI bump just to be able to report +some potential future CPU steppings as invulnerable. Until we have +other change that require an ABI bump, match the affected models +regardless of stepping. + +--- +--- a/arch/x86/kernel/cpu/common.c ++++ b/arch/x86/kernel/cpu/common.c +@@ -1013,10 +1013,8 @@ static const __initconst struct x86_cpu_ + {} + }; + +-#define VULNBL_INTEL_STEPPINGS(model, steppings, issues) \ +- X86_MATCH_VENDOR_FAM_MODEL_STEPPINGS_FEATURE(INTEL, 6, \ +- INTEL_FAM6_##model, steppings, \ +- X86_FEATURE_ANY, issues) ++#define VULNBL_INTEL_STEPPINGS(model, steppings, issues) \ ++ VULNWL_INTEL(model, issues) + + #define SRBDS BIT(0) + diff --git a/debian/patches/series b/debian/patches/series index 03e6594de..e06a570ba 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -307,3 +307,5 @@ bugfix/x86/srbds/0004-x86-speculation-Add-SRBDS-vulnerability-and-mitigati.patch bugfix/x86/srbds/0005-x86-speculation-Add-Ivy-Bridge-to-affected-list.patch # ABI maintenance +debian/abi/x86-speculation-do-not-match-steppings.patch +debian/abi/revert-x86-cpu-add-a-steppings-field-to-struct-x86_cpu_id.patch From b3b40efebddc33ba98f9193d07206adb6026457a Mon Sep 17 00:00:00 2001 From: Salvatore Bonaccorso Date: Thu, 28 May 2020 23:00:17 +0200 Subject: [PATCH 03/17] selinux: properly handle multiple messages in selinux_netlink_send() (CVE-2020-10751) --- debian/changelog | 7 ++ ...-handle-multiple-messages-in-selinux.patch | 112 ++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 120 insertions(+) create mode 100644 debian/patches/bugfix/all/selinux-properly-handle-multiple-messages-in-selinux.patch diff --git a/debian/changelog b/debian/changelog index 6cac52587..c98562377 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +linux (4.19.118-2+deb10u1) UNRELEASED; urgency=medium + + * selinux: properly handle multiple messages in selinux_netlink_send() + (CVE-2020-10751) + + -- Salvatore Bonaccorso Thu, 28 May 2020 23:02:30 +0200 + linux (4.19.118-2) buster; urgency=medium * Merge changes from 4.19.67-2+deb10u2 to include all security fixes from diff --git a/debian/patches/bugfix/all/selinux-properly-handle-multiple-messages-in-selinux.patch b/debian/patches/bugfix/all/selinux-properly-handle-multiple-messages-in-selinux.patch new file mode 100644 index 000000000..7857d0db8 --- /dev/null +++ b/debian/patches/bugfix/all/selinux-properly-handle-multiple-messages-in-selinux.patch @@ -0,0 +1,112 @@ +From: Paul Moore +Date: Tue, 28 Apr 2020 09:59:02 -0400 +Subject: selinux: properly handle multiple messages in selinux_netlink_send() +Origin: https://git.kernel.org/linus/fb73974172ffaaf57a7c42f35424d9aece1a5af6 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2020-10751 + +Fix the SELinux netlink_send hook to properly handle multiple netlink +messages in a single sk_buff; each message is parsed and subject to +SELinux access control. Prior to this patch, SELinux only inspected +the first message in the sk_buff. + +Cc: stable@vger.kernel.org +Reported-by: Dmitry Vyukov +Reviewed-by: Stephen Smalley +Signed-off-by: Paul Moore +--- + security/selinux/hooks.c | 70 ++++++++++++++++++++++++++-------------- + 1 file changed, 45 insertions(+), 25 deletions(-) + +diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c +index c574285966f9..452254fd89f8 100644 +--- a/security/selinux/hooks.c ++++ b/security/selinux/hooks.c +@@ -5595,40 +5595,60 @@ static int selinux_tun_dev_open(void *security) + + static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) + { +- int err = 0; +- u32 perm; ++ int rc = 0; ++ unsigned int msg_len; ++ unsigned int data_len = skb->len; ++ unsigned char *data = skb->data; + struct nlmsghdr *nlh; + struct sk_security_struct *sksec = sk->sk_security; ++ u16 sclass = sksec->sclass; ++ u32 perm; + +- if (skb->len < NLMSG_HDRLEN) { +- err = -EINVAL; +- goto out; +- } +- nlh = nlmsg_hdr(skb); ++ while (data_len >= nlmsg_total_size(0)) { ++ nlh = (struct nlmsghdr *)data; ++ ++ /* NOTE: the nlmsg_len field isn't reliably set by some netlink ++ * users which means we can't reject skb's with bogus ++ * length fields; our solution is to follow what ++ * netlink_rcv_skb() does and simply skip processing at ++ * messages with length fields that are clearly junk ++ */ ++ if (nlh->nlmsg_len < NLMSG_HDRLEN || nlh->nlmsg_len > data_len) ++ return 0; + +- err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm); +- if (err) { +- if (err == -EINVAL) { ++ rc = selinux_nlmsg_lookup(sclass, nlh->nlmsg_type, &perm); ++ if (rc == 0) { ++ rc = sock_has_perm(sk, perm); ++ if (rc) ++ return rc; ++ } else if (rc == -EINVAL) { ++ /* -EINVAL is a missing msg/perm mapping */ + pr_warn_ratelimited("SELinux: unrecognized netlink" +- " message: protocol=%hu nlmsg_type=%hu sclass=%s" +- " pig=%d comm=%s\n", +- sk->sk_protocol, nlh->nlmsg_type, +- secclass_map[sksec->sclass - 1].name, +- task_pid_nr(current), current->comm); +- if (!enforcing_enabled(&selinux_state) || +- security_get_allow_unknown(&selinux_state)) +- err = 0; ++ " message: protocol=%hu nlmsg_type=%hu sclass=%s" ++ " pid=%d comm=%s\n", ++ sk->sk_protocol, nlh->nlmsg_type, ++ secclass_map[sclass - 1].name, ++ task_pid_nr(current), current->comm); ++ if (enforcing_enabled(&selinux_state) && ++ !security_get_allow_unknown(&selinux_state)) ++ return rc; ++ rc = 0; ++ } else if (rc == -ENOENT) { ++ /* -ENOENT is a missing socket/class mapping, ignore */ ++ rc = 0; ++ } else { ++ return rc; + } + +- /* Ignore */ +- if (err == -ENOENT) +- err = 0; +- goto out; ++ /* move to the next message after applying netlink padding */ ++ msg_len = NLMSG_ALIGN(nlh->nlmsg_len); ++ if (msg_len >= data_len) ++ return 0; ++ data_len -= msg_len; ++ data += msg_len; + } + +- err = sock_has_perm(sk, perm); +-out: +- return err; ++ return rc; + } + + #ifdef CONFIG_NETFILTER +-- +2.27.0.rc0 + diff --git a/debian/patches/series b/debian/patches/series index c4eedde94..ee50e4c72 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -300,5 +300,6 @@ bugfix/all/net-ipv6_stub-use-ip6_dst_lookup_flow-instead-of-ip6.patch bugfix/all/blktrace-protect-q-blk_trace-with-rcu.patch bugfix/all/blktrace-fix-dereference-after-null-check.patch bugfix/s390x/s390-mm-fix-page-table-upgrade-vs-2ndary-address-mod.patch +bugfix/all/selinux-properly-handle-multiple-messages-in-selinux.patch # ABI maintenance From 34284455a6241f0b657f9824971df140a8b829cf Mon Sep 17 00:00:00 2001 From: Salvatore Bonaccorso Date: Thu, 28 May 2020 23:33:22 +0200 Subject: [PATCH 04/17] fs/namespace.c: fix mountpoint reference counter race (CVE-2020-12114) --- debian/changelog | 1 + ...ix-mountpoint-reference-counter-race.patch | 48 +++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 50 insertions(+) create mode 100644 debian/patches/bugfix/all/fs-namespace.c-fix-mountpoint-reference-counter-race.patch diff --git a/debian/changelog b/debian/changelog index c98562377..f165190e3 100644 --- a/debian/changelog +++ b/debian/changelog @@ -2,6 +2,7 @@ linux (4.19.118-2+deb10u1) UNRELEASED; urgency=medium * selinux: properly handle multiple messages in selinux_netlink_send() (CVE-2020-10751) + * fs/namespace.c: fix mountpoint reference counter race (CVE-2020-12114) -- Salvatore Bonaccorso Thu, 28 May 2020 23:02:30 +0200 diff --git a/debian/patches/bugfix/all/fs-namespace.c-fix-mountpoint-reference-counter-race.patch b/debian/patches/bugfix/all/fs-namespace.c-fix-mountpoint-reference-counter-race.patch new file mode 100644 index 000000000..70e9d44a4 --- /dev/null +++ b/debian/patches/bugfix/all/fs-namespace.c-fix-mountpoint-reference-counter-race.patch @@ -0,0 +1,48 @@ +From: Piotr Krysiuk +Date: Mon, 27 Apr 2020 11:34:12 +0100 +Subject: fs/namespace.c: fix mountpoint reference counter race +Origin: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=f511dc75d22e0c000fc70b54f670c2c17f5fba9a +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2020-12114 + +A race condition between threads updating mountpoint reference counter +affects longterm releases 4.4.220, 4.9.220, 4.14.177 and 4.19.118. + +The mountpoint reference counter corruption may occur when: +* one thread increments m_count member of struct mountpoint + [under namespace_sem, but not holding mount_lock] + pivot_root() +* another thread simultaneously decrements the same m_count + [under mount_lock, but not holding namespace_sem] + put_mountpoint() + unhash_mnt() + umount_mnt() + mntput_no_expire() + +To fix this race condition, grab mount_lock before updating m_count in +pivot_root(). + +Reference: CVE-2020-12114 +Cc: Al Viro +Signed-off-by: Piotr Krysiuk +Signed-off-by: Greg Kroah-Hartman +--- + fs/namespace.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/namespace.c b/fs/namespace.c +index 1fce41ba3535..741f40cd955e 100644 +--- a/fs/namespace.c ++++ b/fs/namespace.c +@@ -3142,8 +3142,8 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, + /* make certain new is below the root */ + if (!is_path_reachable(new_mnt, new.dentry, &root)) + goto out4; +- root_mp->m_count++; /* pin it so it won't go away */ + lock_mount_hash(); ++ root_mp->m_count++; /* pin it so it won't go away */ + detach_mnt(new_mnt, &parent_path); + detach_mnt(root_mnt, &root_parent); + if (root_mnt->mnt.mnt_flags & MNT_LOCKED) { +-- +2.27.0.rc0 + diff --git a/debian/patches/series b/debian/patches/series index ee50e4c72..4cd693801 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -301,5 +301,6 @@ bugfix/all/blktrace-protect-q-blk_trace-with-rcu.patch bugfix/all/blktrace-fix-dereference-after-null-check.patch bugfix/s390x/s390-mm-fix-page-table-upgrade-vs-2ndary-address-mod.patch bugfix/all/selinux-properly-handle-multiple-messages-in-selinux.patch +bugfix/all/fs-namespace.c-fix-mountpoint-reference-counter-race.patch # ABI maintenance From 2fe68e87e7adaf80024bc3a08f7fbd10ca849d41 Mon Sep 17 00:00:00 2001 From: Salvatore Bonaccorso Date: Fri, 29 May 2020 13:46:50 +0200 Subject: [PATCH 05/17] USB: core: Fix free-while-in-use bug in the USB S-Glibrary (CVE-2020-12464) --- debian/changelog | 2 + ...e-while-in-use-bug-in-the-usb-s-glib.patch | 92 +++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 95 insertions(+) create mode 100644 debian/patches/bugfix/all/usb-core-fix-free-while-in-use-bug-in-the-usb-s-glib.patch diff --git a/debian/changelog b/debian/changelog index f165190e3..dfd6ab4e4 100644 --- a/debian/changelog +++ b/debian/changelog @@ -3,6 +3,8 @@ linux (4.19.118-2+deb10u1) UNRELEASED; urgency=medium * selinux: properly handle multiple messages in selinux_netlink_send() (CVE-2020-10751) * fs/namespace.c: fix mountpoint reference counter race (CVE-2020-12114) + * USB: core: Fix free-while-in-use bug in the USB S-Glibrary + (CVE-2020-12464) -- Salvatore Bonaccorso Thu, 28 May 2020 23:02:30 +0200 diff --git a/debian/patches/bugfix/all/usb-core-fix-free-while-in-use-bug-in-the-usb-s-glib.patch b/debian/patches/bugfix/all/usb-core-fix-free-while-in-use-bug-in-the-usb-s-glib.patch new file mode 100644 index 000000000..62e0909cd --- /dev/null +++ b/debian/patches/bugfix/all/usb-core-fix-free-while-in-use-bug-in-the-usb-s-glib.patch @@ -0,0 +1,92 @@ +From: Alan Stern +Date: Sat, 28 Mar 2020 16:18:11 -0400 +Subject: USB: core: Fix free-while-in-use bug in the USB S-Glibrary +Origin: https://git.kernel.org/linus/056ad39ee9253873522f6469c3364964a322912b +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2020-12464 + +FuzzUSB (a variant of syzkaller) found a free-while-still-in-use bug +in the USB scatter-gather library: + +BUG: KASAN: use-after-free in atomic_read +include/asm-generic/atomic-instrumented.h:26 [inline] +BUG: KASAN: use-after-free in usb_hcd_unlink_urb+0x5f/0x170 +drivers/usb/core/hcd.c:1607 +Read of size 4 at addr ffff888065379610 by task kworker/u4:1/27 + +CPU: 1 PID: 27 Comm: kworker/u4:1 Not tainted 5.5.11 #2 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS +1.10.2-1ubuntu1 04/01/2014 +Workqueue: scsi_tmf_2 scmd_eh_abort_handler +Call Trace: + __dump_stack lib/dump_stack.c:77 [inline] + dump_stack+0xce/0x128 lib/dump_stack.c:118 + print_address_description.constprop.4+0x21/0x3c0 mm/kasan/report.c:374 + __kasan_report+0x153/0x1cb mm/kasan/report.c:506 + kasan_report+0x12/0x20 mm/kasan/common.c:639 + check_memory_region_inline mm/kasan/generic.c:185 [inline] + check_memory_region+0x152/0x1b0 mm/kasan/generic.c:192 + __kasan_check_read+0x11/0x20 mm/kasan/common.c:95 + atomic_read include/asm-generic/atomic-instrumented.h:26 [inline] + usb_hcd_unlink_urb+0x5f/0x170 drivers/usb/core/hcd.c:1607 + usb_unlink_urb+0x72/0xb0 drivers/usb/core/urb.c:657 + usb_sg_cancel+0x14e/0x290 drivers/usb/core/message.c:602 + usb_stor_stop_transport+0x5e/0xa0 drivers/usb/storage/transport.c:937 + +This bug occurs when cancellation of the S-G transfer races with +transfer completion. When that happens, usb_sg_cancel() may continue +to access the transfer's URBs after usb_sg_wait() has freed them. + +The bug is caused by the fact that usb_sg_cancel() does not take any +sort of reference to the transfer, and so there is nothing to prevent +the URBs from being deallocated while the routine is trying to use +them. The fix is to take such a reference by incrementing the +transfer's io->count field while the cancellation is in progres and +decrementing it afterward. The transfer's URBs are not deallocated +until io->complete is triggered, which happens when io->count reaches +zero. + +Signed-off-by: Alan Stern +Reported-and-tested-by: Kyungtae Kim +CC: + +Link: https://lore.kernel.org/r/Pine.LNX.4.44L0.2003281615140.14837-100000@netrider.rowland.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/core/message.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c +index d5f834f16993..a48678a0c83a 100644 +--- a/drivers/usb/core/message.c ++++ b/drivers/usb/core/message.c +@@ -589,12 +589,13 @@ void usb_sg_cancel(struct usb_sg_request *io) + int i, retval; + + spin_lock_irqsave(&io->lock, flags); +- if (io->status) { ++ if (io->status || io->count == 0) { + spin_unlock_irqrestore(&io->lock, flags); + return; + } + /* shut everything down */ + io->status = -ECONNRESET; ++ io->count++; /* Keep the request alive until we're done */ + spin_unlock_irqrestore(&io->lock, flags); + + for (i = io->entries - 1; i >= 0; --i) { +@@ -608,6 +609,12 @@ void usb_sg_cancel(struct usb_sg_request *io) + dev_warn(&io->dev->dev, "%s, unlink --> %d\n", + __func__, retval); + } ++ ++ spin_lock_irqsave(&io->lock, flags); ++ io->count--; ++ if (!io->count) ++ complete(&io->complete); ++ spin_unlock_irqrestore(&io->lock, flags); + } + EXPORT_SYMBOL_GPL(usb_sg_cancel); + +-- +2.27.0.rc0 + diff --git a/debian/patches/series b/debian/patches/series index 4cd693801..c3e7b0010 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -302,5 +302,6 @@ bugfix/all/blktrace-fix-dereference-after-null-check.patch bugfix/s390x/s390-mm-fix-page-table-upgrade-vs-2ndary-address-mod.patch bugfix/all/selinux-properly-handle-multiple-messages-in-selinux.patch bugfix/all/fs-namespace.c-fix-mountpoint-reference-counter-race.patch +bugfix/all/usb-core-fix-free-while-in-use-bug-in-the-usb-s-glib.patch # ABI maintenance From 92ed2f689a9329be074d6c74013b65be697cd876 Mon Sep 17 00:00:00 2001 From: Salvatore Bonaccorso Date: Fri, 29 May 2020 14:02:45 +0200 Subject: [PATCH 06/17] [x86] KVM: SVM: Fix potential memory leak in svm_cpu_init() (CVE-2020-12768) --- debian/changelog | 2 + ...otential-memory-leak-in-svm_cpu_init.patch | 65 +++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 68 insertions(+) create mode 100644 debian/patches/bugfix/x86/kvm-svm-fix-potential-memory-leak-in-svm_cpu_init.patch diff --git a/debian/changelog b/debian/changelog index dfd6ab4e4..724da7be6 100644 --- a/debian/changelog +++ b/debian/changelog @@ -5,6 +5,8 @@ linux (4.19.118-2+deb10u1) UNRELEASED; urgency=medium * fs/namespace.c: fix mountpoint reference counter race (CVE-2020-12114) * USB: core: Fix free-while-in-use bug in the USB S-Glibrary (CVE-2020-12464) + * [x86] KVM: SVM: Fix potential memory leak in svm_cpu_init() + (CVE-2020-12768) -- Salvatore Bonaccorso Thu, 28 May 2020 23:02:30 +0200 diff --git a/debian/patches/bugfix/x86/kvm-svm-fix-potential-memory-leak-in-svm_cpu_init.patch b/debian/patches/bugfix/x86/kvm-svm-fix-potential-memory-leak-in-svm_cpu_init.patch new file mode 100644 index 000000000..5e0cd3ca9 --- /dev/null +++ b/debian/patches/bugfix/x86/kvm-svm-fix-potential-memory-leak-in-svm_cpu_init.patch @@ -0,0 +1,65 @@ +From: Miaohe Lin +Date: Sat, 4 Jan 2020 16:56:49 +0800 +Subject: KVM: SVM: Fix potential memory leak in svm_cpu_init() +Origin: https://git.kernel.org/linus/d80b64ff297e40c2b6f7d7abc1b3eba70d22a068 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2020-12768 + +When kmalloc memory for sd->sev_vmcbs failed, we forget to free the page +held by sd->save_area. Also get rid of the var r as '-ENOMEM' is actually +the only possible outcome here. + +Reviewed-by: Liran Alon +Reviewed-by: Vitaly Kuznetsov +Signed-off-by: Miaohe Lin +Signed-off-by: Paolo Bonzini +--- + arch/x86/kvm/svm.c | 13 ++++++------- + 1 file changed, 6 insertions(+), 7 deletions(-) + +diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c +index 8787a123b8e7..ff02aeb23616 100644 +--- a/arch/x86/kvm/svm.c ++++ b/arch/x86/kvm/svm.c +@@ -1005,33 +1005,32 @@ static void svm_cpu_uninit(int cpu) + static int svm_cpu_init(int cpu) + { + struct svm_cpu_data *sd; +- int r; + + sd = kzalloc(sizeof(struct svm_cpu_data), GFP_KERNEL); + if (!sd) + return -ENOMEM; + sd->cpu = cpu; +- r = -ENOMEM; + sd->save_area = alloc_page(GFP_KERNEL); + if (!sd->save_area) +- goto err_1; ++ goto free_cpu_data; + + if (svm_sev_enabled()) { +- r = -ENOMEM; + sd->sev_vmcbs = kmalloc_array(max_sev_asid + 1, + sizeof(void *), + GFP_KERNEL); + if (!sd->sev_vmcbs) +- goto err_1; ++ goto free_save_area; + } + + per_cpu(svm_data, cpu) = sd; + + return 0; + +-err_1: ++free_save_area: ++ __free_page(sd->save_area); ++free_cpu_data: + kfree(sd); +- return r; ++ return -ENOMEM; + + } + +-- +2.27.0.rc0 + diff --git a/debian/patches/series b/debian/patches/series index c3e7b0010..610328ed5 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -303,5 +303,6 @@ bugfix/s390x/s390-mm-fix-page-table-upgrade-vs-2ndary-address-mod.patch bugfix/all/selinux-properly-handle-multiple-messages-in-selinux.patch bugfix/all/fs-namespace.c-fix-mountpoint-reference-counter-race.patch bugfix/all/usb-core-fix-free-while-in-use-bug-in-the-usb-s-glib.patch +bugfix/x86/kvm-svm-fix-potential-memory-leak-in-svm_cpu_init.patch # ABI maintenance From aefd886eef3d1789f514e3e564f0df0d9f790635 Mon Sep 17 00:00:00 2001 From: Salvatore Bonaccorso Date: Fri, 29 May 2020 21:20:44 +0200 Subject: [PATCH 07/17] scsi: sg: add sg_remove_request in sg_write (CVE-2020-12770) --- debian/changelog | 1 + ...sg-add-sg_remove_request-in-sg_write.patch | 42 +++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 44 insertions(+) create mode 100644 debian/patches/bugfix/all/scsi-sg-add-sg_remove_request-in-sg_write.patch diff --git a/debian/changelog b/debian/changelog index 724da7be6..61883698c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -7,6 +7,7 @@ linux (4.19.118-2+deb10u1) UNRELEASED; urgency=medium (CVE-2020-12464) * [x86] KVM: SVM: Fix potential memory leak in svm_cpu_init() (CVE-2020-12768) + * scsi: sg: add sg_remove_request in sg_write (CVE-2020-12770) -- Salvatore Bonaccorso Thu, 28 May 2020 23:02:30 +0200 diff --git a/debian/patches/bugfix/all/scsi-sg-add-sg_remove_request-in-sg_write.patch b/debian/patches/bugfix/all/scsi-sg-add-sg_remove_request-in-sg_write.patch new file mode 100644 index 000000000..6d9c96f1f --- /dev/null +++ b/debian/patches/bugfix/all/scsi-sg-add-sg_remove_request-in-sg_write.patch @@ -0,0 +1,42 @@ +From: Wu Bo +Date: Tue, 14 Apr 2020 10:13:28 +0800 +Subject: scsi: sg: add sg_remove_request in sg_write +Origin: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/commit?id=34fcb4291e234468f9bf9d4b851c9f522f3bbb13 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2020-12770 + +commit 83c6f2390040f188cc25b270b4befeb5628c1aee upstream. + +If the __copy_from_user function failed we need to call sg_remove_request +in sg_write. + +Link: https://lore.kernel.org/r/610618d9-e983-fd56-ed0f-639428343af7@huawei.com +Acked-by: Douglas Gilbert +Signed-off-by: Wu Bo +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +[groeck: Backport to v5.4.y and older kernels] +Signed-off-by: Guenter Roeck +Signed-off-by: Greg Kroah-Hartman +--- + drivers/scsi/sg.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c +index ac8535d2b41a..6bb45ae19d58 100644 +--- a/drivers/scsi/sg.c ++++ b/drivers/scsi/sg.c +@@ -694,8 +694,10 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) + hp->flags = input_size; /* structure abuse ... */ + hp->pack_id = old_hdr.pack_id; + hp->usr_ptr = NULL; +- if (__copy_from_user(cmnd, buf, cmd_size)) ++ if (__copy_from_user(cmnd, buf, cmd_size)) { ++ sg_remove_request(sfp, srp); + return -EFAULT; ++ } + /* + * SG_DXFER_TO_FROM_DEV is functionally equivalent to SG_DXFER_FROM_DEV, + * but is is possible that the app intended SG_DXFER_TO_DEV, because there +-- +2.27.0.rc0 + diff --git a/debian/patches/series b/debian/patches/series index 610328ed5..67efa3575 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -304,5 +304,6 @@ bugfix/all/selinux-properly-handle-multiple-messages-in-selinux.patch bugfix/all/fs-namespace.c-fix-mountpoint-reference-counter-race.patch bugfix/all/usb-core-fix-free-while-in-use-bug-in-the-usb-s-glib.patch bugfix/x86/kvm-svm-fix-potential-memory-leak-in-svm_cpu_init.patch +bugfix/all/scsi-sg-add-sg_remove_request-in-sg_write.patch # ABI maintenance From 888eb1f799fe93de090818cc5282a5655a67a147 Mon Sep 17 00:00:00 2001 From: Salvatore Bonaccorso Date: Fri, 29 May 2020 21:34:00 +0200 Subject: [PATCH 08/17] USB: gadget: fix illegal array access in binding with UDC (CVE-2020-13143) --- debian/changelog | 1 + ...llegal-array-access-in-binding-with-.patch | 78 +++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 80 insertions(+) create mode 100644 debian/patches/bugfix/all/usb-gadget-fix-illegal-array-access-in-binding-with-.patch diff --git a/debian/changelog b/debian/changelog index 61883698c..f6b86fee4 100644 --- a/debian/changelog +++ b/debian/changelog @@ -8,6 +8,7 @@ linux (4.19.118-2+deb10u1) UNRELEASED; urgency=medium * [x86] KVM: SVM: Fix potential memory leak in svm_cpu_init() (CVE-2020-12768) * scsi: sg: add sg_remove_request in sg_write (CVE-2020-12770) + * USB: gadget: fix illegal array access in binding with UDC (CVE-2020-13143) -- Salvatore Bonaccorso Thu, 28 May 2020 23:02:30 +0200 diff --git a/debian/patches/bugfix/all/usb-gadget-fix-illegal-array-access-in-binding-with-.patch b/debian/patches/bugfix/all/usb-gadget-fix-illegal-array-access-in-binding-with-.patch new file mode 100644 index 000000000..3a21b6391 --- /dev/null +++ b/debian/patches/bugfix/all/usb-gadget-fix-illegal-array-access-in-binding-with-.patch @@ -0,0 +1,78 @@ +From: Kyungtae Kim +Date: Sun, 10 May 2020 05:43:34 +0000 +Subject: USB: gadget: fix illegal array access in binding with UDC +Origin: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/commit?id=a105bb549252e3e8bd9db0bdd81cdd6a853e4238 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2020-13143 + +commit 15753588bcd4bbffae1cca33c8ced5722477fe1f upstream. + +FuzzUSB (a variant of syzkaller) found an illegal array access +using an incorrect index while binding a gadget with UDC. + +Reference: https://www.spinics.net/lists/linux-usb/msg194331.html + +This bug occurs when a size variable used for a buffer +is misused to access its strcpy-ed buffer. +Given a buffer along with its size variable (taken from user input), +from which, a new buffer is created using kstrdup(). +Due to the original buffer containing 0 value in the middle, +the size of the kstrdup-ed buffer becomes smaller than that of the original. +So accessing the kstrdup-ed buffer with the same size variable +triggers memory access violation. + +The fix makes sure no zero value in the buffer, +by comparing the strlen() of the orignal buffer with the size variable, +so that the access to the kstrdup-ed buffer is safe. + +BUG: KASAN: slab-out-of-bounds in gadget_dev_desc_UDC_store+0x1ba/0x200 +drivers/usb/gadget/configfs.c:266 +Read of size 1 at addr ffff88806a55dd7e by task syz-executor.0/17208 + +CPU: 2 PID: 17208 Comm: syz-executor.0 Not tainted 5.6.8 #1 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 +Call Trace: + __dump_stack lib/dump_stack.c:77 [inline] + dump_stack+0xce/0x128 lib/dump_stack.c:118 + print_address_description.constprop.4+0x21/0x3c0 mm/kasan/report.c:374 + __kasan_report+0x131/0x1b0 mm/kasan/report.c:506 + kasan_report+0x12/0x20 mm/kasan/common.c:641 + __asan_report_load1_noabort+0x14/0x20 mm/kasan/generic_report.c:132 + gadget_dev_desc_UDC_store+0x1ba/0x200 drivers/usb/gadget/configfs.c:266 + flush_write_buffer fs/configfs/file.c:251 [inline] + configfs_write_file+0x2f1/0x4c0 fs/configfs/file.c:283 + __vfs_write+0x85/0x110 fs/read_write.c:494 + vfs_write+0x1cd/0x510 fs/read_write.c:558 + ksys_write+0x18a/0x220 fs/read_write.c:611 + __do_sys_write fs/read_write.c:623 [inline] + __se_sys_write fs/read_write.c:620 [inline] + __x64_sys_write+0x73/0xb0 fs/read_write.c:620 + do_syscall_64+0x9e/0x510 arch/x86/entry/common.c:294 + entry_SYSCALL_64_after_hwframe+0x49/0xbe + +Signed-off-by: Kyungtae Kim +Reported-and-tested-by: Kyungtae Kim +Cc: Felipe Balbi +Cc: stable +Link: https://lore.kernel.org/r/20200510054326.GA19198@pizza01 +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/gadget/configfs.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c +index ab9ac48a751a..a7709d126b29 100644 +--- a/drivers/usb/gadget/configfs.c ++++ b/drivers/usb/gadget/configfs.c +@@ -260,6 +260,9 @@ static ssize_t gadget_dev_desc_UDC_store(struct config_item *item, + char *name; + int ret; + ++ if (strlen(page) < len) ++ return -EOVERFLOW; ++ + name = kstrdup(page, GFP_KERNEL); + if (!name) + return -ENOMEM; +-- +2.27.0.rc0 + diff --git a/debian/patches/series b/debian/patches/series index 67efa3575..0968e27e7 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -305,5 +305,6 @@ bugfix/all/fs-namespace.c-fix-mountpoint-reference-counter-race.patch bugfix/all/usb-core-fix-free-while-in-use-bug-in-the-usb-s-glib.patch bugfix/x86/kvm-svm-fix-potential-memory-leak-in-svm_cpu_init.patch bugfix/all/scsi-sg-add-sg_remove_request-in-sg_write.patch +bugfix/all/usb-gadget-fix-illegal-array-access-in-binding-with-.patch # ABI maintenance From 2222852cc19cba2a0356a15d544a0420ccbfa8d4 Mon Sep 17 00:00:00 2001 From: Salvatore Bonaccorso Date: Tue, 2 Jun 2020 20:27:09 +0200 Subject: [PATCH 09/17] netlabel: cope with NULL catmap (CVE-2020-10711) --- debian/changelog | 1 + .../all/netlabel-cope-with-NULL-catmap.patch | 92 +++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 94 insertions(+) create mode 100644 debian/patches/bugfix/all/netlabel-cope-with-NULL-catmap.patch diff --git a/debian/changelog b/debian/changelog index f6b86fee4..b3b67d37b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -9,6 +9,7 @@ linux (4.19.118-2+deb10u1) UNRELEASED; urgency=medium (CVE-2020-12768) * scsi: sg: add sg_remove_request in sg_write (CVE-2020-12770) * USB: gadget: fix illegal array access in binding with UDC (CVE-2020-13143) + * netlabel: cope with NULL catmap (CVE-2020-10711) -- Salvatore Bonaccorso Thu, 28 May 2020 23:02:30 +0200 diff --git a/debian/patches/bugfix/all/netlabel-cope-with-NULL-catmap.patch b/debian/patches/bugfix/all/netlabel-cope-with-NULL-catmap.patch new file mode 100644 index 000000000..8aa633a1a --- /dev/null +++ b/debian/patches/bugfix/all/netlabel-cope-with-NULL-catmap.patch @@ -0,0 +1,92 @@ +From: Paolo Abeni +Date: Tue, 12 May 2020 14:43:14 +0200 +Subject: netlabel: cope with NULL catmap +Origin: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/commit?id=caf6c20c6421ca687751d27b96c8021c655e56e6 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2020-10711 + +[ Upstream commit eead1c2ea2509fd754c6da893a94f0e69e83ebe4 ] + +The cipso and calipso code can set the MLS_CAT attribute on +successful parsing, even if the corresponding catmap has +not been allocated, as per current configuration and external +input. + +Later, selinux code tries to access the catmap if the MLS_CAT flag +is present via netlbl_catmap_getlong(). That may cause null ptr +dereference while processing incoming network traffic. + +Address the issue setting the MLS_CAT flag only if the catmap is +really allocated. Additionally let netlbl_catmap_getlong() cope +with NULL catmap. + +Reported-by: Matthew Sheets +Fixes: 4b8feff251da ("netlabel: fix the horribly broken catmap functions") +Fixes: ceba1832b1b2 ("calipso: Set the calipso socket label to match the secattr.") +Signed-off-by: Paolo Abeni +Acked-by: Paul Moore +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/cipso_ipv4.c | 6 ++++-- + net/ipv6/calipso.c | 3 ++- + net/netlabel/netlabel_kapi.c | 6 ++++++ + 3 files changed, 12 insertions(+), 3 deletions(-) + +diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c +index 1c21dc5d6dd4..5535b722f66d 100644 +--- a/net/ipv4/cipso_ipv4.c ++++ b/net/ipv4/cipso_ipv4.c +@@ -1272,7 +1272,8 @@ static int cipso_v4_parsetag_rbm(const struct cipso_v4_doi *doi_def, + return ret_val; + } + +- secattr->flags |= NETLBL_SECATTR_MLS_CAT; ++ if (secattr->attr.mls.cat) ++ secattr->flags |= NETLBL_SECATTR_MLS_CAT; + } + + return 0; +@@ -1453,7 +1454,8 @@ static int cipso_v4_parsetag_rng(const struct cipso_v4_doi *doi_def, + return ret_val; + } + +- secattr->flags |= NETLBL_SECATTR_MLS_CAT; ++ if (secattr->attr.mls.cat) ++ secattr->flags |= NETLBL_SECATTR_MLS_CAT; + } + + return 0; +diff --git a/net/ipv6/calipso.c b/net/ipv6/calipso.c +index 1c0bb9fb76e6..70611784c071 100644 +--- a/net/ipv6/calipso.c ++++ b/net/ipv6/calipso.c +@@ -1061,7 +1061,8 @@ static int calipso_opt_getattr(const unsigned char *calipso, + goto getattr_return; + } + +- secattr->flags |= NETLBL_SECATTR_MLS_CAT; ++ if (secattr->attr.mls.cat) ++ secattr->flags |= NETLBL_SECATTR_MLS_CAT; + } + + secattr->type = NETLBL_NLTYPE_CALIPSO; +diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c +index ee3e5b6471a6..15fe2120b310 100644 +--- a/net/netlabel/netlabel_kapi.c ++++ b/net/netlabel/netlabel_kapi.c +@@ -748,6 +748,12 @@ int netlbl_catmap_getlong(struct netlbl_lsm_catmap *catmap, + if ((off & (BITS_PER_LONG - 1)) != 0) + return -EINVAL; + ++ /* a null catmap is equivalent to an empty one */ ++ if (!catmap) { ++ *offset = (u32)-1; ++ return 0; ++ } ++ + if (off < catmap->startbit) { + off = catmap->startbit; + *offset = off; +-- +2.27.0.rc0 + diff --git a/debian/patches/series b/debian/patches/series index 0968e27e7..a7b82e3b0 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -306,5 +306,6 @@ bugfix/all/usb-core-fix-free-while-in-use-bug-in-the-usb-s-glib.patch bugfix/x86/kvm-svm-fix-potential-memory-leak-in-svm_cpu_init.patch bugfix/all/scsi-sg-add-sg_remove_request-in-sg_write.patch bugfix/all/usb-gadget-fix-illegal-array-access-in-binding-with-.patch +bugfix/all/netlabel-cope-with-NULL-catmap.patch # ABI maintenance From 7fc7c96d6e3ccc791b459d8689aae32e11860bac Mon Sep 17 00:00:00 2001 From: Salvatore Bonaccorso Date: Wed, 3 Jun 2020 07:41:02 +0200 Subject: [PATCH 10/17] fs/binfmt_elf.c: allocate initialized memory in fill_thread_core_info() (CVE-2020-10732) --- debian/changelog | 2 + ...allocate-initialized-memory-in-fill_.patch | 41 +++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 44 insertions(+) create mode 100644 debian/patches/bugfix/all/fs-binfmt_elf.c-allocate-initialized-memory-in-fill_.patch diff --git a/debian/changelog b/debian/changelog index b3b67d37b..e969253ab 100644 --- a/debian/changelog +++ b/debian/changelog @@ -10,6 +10,8 @@ linux (4.19.118-2+deb10u1) UNRELEASED; urgency=medium * scsi: sg: add sg_remove_request in sg_write (CVE-2020-12770) * USB: gadget: fix illegal array access in binding with UDC (CVE-2020-13143) * netlabel: cope with NULL catmap (CVE-2020-10711) + * fs/binfmt_elf.c: allocate initialized memory in fill_thread_core_info() + (CVE-2020-10732) -- Salvatore Bonaccorso Thu, 28 May 2020 23:02:30 +0200 diff --git a/debian/patches/bugfix/all/fs-binfmt_elf.c-allocate-initialized-memory-in-fill_.patch b/debian/patches/bugfix/all/fs-binfmt_elf.c-allocate-initialized-memory-in-fill_.patch new file mode 100644 index 000000000..fc4ac93cb --- /dev/null +++ b/debian/patches/bugfix/all/fs-binfmt_elf.c-allocate-initialized-memory-in-fill_.patch @@ -0,0 +1,41 @@ +From: Alexander Potapenko +Date: Wed, 27 May 2020 22:20:52 -0700 +Subject: fs/binfmt_elf.c: allocate initialized memory in + fill_thread_core_info() +Origin: https://git.kernel.org/linus/1d605416fb7175e1adf094251466caa52093b413 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2020-10732 + +KMSAN reported uninitialized data being written to disk when dumping +core. As a result, several kilobytes of kmalloc memory may be written +to the core file and then read by a non-privileged user. + +Reported-by: sam +Signed-off-by: Alexander Potapenko +Signed-off-by: Andrew Morton +Acked-by: Kees Cook +Cc: Al Viro +Cc: Alexey Dobriyan +Cc: +Link: http://lkml.kernel.org/r/20200419100848.63472-1-glider@google.com +Link: https://github.com/google/kmsan/issues/76 +Signed-off-by: Linus Torvalds +--- + fs/binfmt_elf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c +index 13f25e241ac4..25d489bc9453 100644 +--- a/fs/binfmt_elf.c ++++ b/fs/binfmt_elf.c +@@ -1733,7 +1733,7 @@ static int fill_thread_core_info(struct elf_thread_core_info *t, + (!regset->active || regset->active(t->task, regset) > 0)) { + int ret; + size_t size = regset_size(t->task, regset); +- void *data = kmalloc(size, GFP_KERNEL); ++ void *data = kzalloc(size, GFP_KERNEL); + if (unlikely(!data)) + return 0; + ret = regset->get(t->task, regset, +-- +2.27.0.rc0 + diff --git a/debian/patches/series b/debian/patches/series index a7b82e3b0..10d611c8a 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -307,5 +307,6 @@ bugfix/x86/kvm-svm-fix-potential-memory-leak-in-svm_cpu_init.patch bugfix/all/scsi-sg-add-sg_remove_request-in-sg_write.patch bugfix/all/usb-gadget-fix-illegal-array-access-in-binding-with-.patch bugfix/all/netlabel-cope-with-NULL-catmap.patch +bugfix/all/fs-binfmt_elf.c-allocate-initialized-memory-in-fill_.patch # ABI maintenance From 50bf5b3b3def0070e6e16dbffbdcf53dbc3cd6d0 Mon Sep 17 00:00:00 2001 From: Salvatore Bonaccorso Date: Fri, 5 Jun 2020 12:29:55 +0200 Subject: [PATCH 11/17] kernel/relay.c: handle alloc_percpu returning NULL in relay_open (CVE-2019-19462) --- debian/changelog | 2 + ...andle-alloc_percpu-returning-NULL-in.patch | 71 +++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 74 insertions(+) create mode 100644 debian/patches/bugfix/all/kernel-relay.c-handle-alloc_percpu-returning-NULL-in.patch diff --git a/debian/changelog b/debian/changelog index e969253ab..13ca538b3 100644 --- a/debian/changelog +++ b/debian/changelog @@ -12,6 +12,8 @@ linux (4.19.118-2+deb10u1) UNRELEASED; urgency=medium * netlabel: cope with NULL catmap (CVE-2020-10711) * fs/binfmt_elf.c: allocate initialized memory in fill_thread_core_info() (CVE-2020-10732) + * kernel/relay.c: handle alloc_percpu returning NULL in relay_open + (CVE-2019-19462) -- Salvatore Bonaccorso Thu, 28 May 2020 23:02:30 +0200 diff --git a/debian/patches/bugfix/all/kernel-relay.c-handle-alloc_percpu-returning-NULL-in.patch b/debian/patches/bugfix/all/kernel-relay.c-handle-alloc_percpu-returning-NULL-in.patch new file mode 100644 index 000000000..0772ccfbe --- /dev/null +++ b/debian/patches/bugfix/all/kernel-relay.c-handle-alloc_percpu-returning-NULL-in.patch @@ -0,0 +1,71 @@ +From: Daniel Axtens +Date: Thu, 4 Jun 2020 16:51:27 -0700 +Subject: kernel/relay.c: handle alloc_percpu returning NULL in relay_open +Origin: https://git.kernel.org/linus/54e200ab40fc14c863bcc80a51e20b7906608fce +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2019-19462 + +alloc_percpu() may return NULL, which means chan->buf may be set to NULL. +In that case, when we do *per_cpu_ptr(chan->buf, ...), we dereference an +invalid pointer: + + BUG: Unable to handle kernel data access at 0x7dae0000 + Faulting instruction address: 0xc0000000003f3fec + ... + NIP relay_open+0x29c/0x600 + LR relay_open+0x270/0x600 + Call Trace: + relay_open+0x264/0x600 (unreliable) + __blk_trace_setup+0x254/0x600 + blk_trace_setup+0x68/0xa0 + sg_ioctl+0x7bc/0x2e80 + do_vfs_ioctl+0x13c/0x1300 + ksys_ioctl+0x94/0x130 + sys_ioctl+0x48/0xb0 + system_call+0x5c/0x68 + +Check if alloc_percpu returns NULL. + +This was found by syzkaller both on x86 and powerpc, and the reproducer +it found on powerpc is capable of hitting the issue as an unprivileged +user. + +Fixes: 017c59c042d0 ("relay: Use per CPU constructs for the relay channel buffer pointers") +Reported-by: syzbot+1e925b4b836afe85a1c6@syzkaller-ppc64.appspotmail.com +Reported-by: syzbot+587b2421926808309d21@syzkaller-ppc64.appspotmail.com +Reported-by: syzbot+58320b7171734bf79d26@syzkaller.appspotmail.com +Reported-by: syzbot+d6074fb08bdb2e010520@syzkaller.appspotmail.com +Signed-off-by: Daniel Axtens +Signed-off-by: Andrew Morton +Reviewed-by: Michael Ellerman +Reviewed-by: Andrew Donnellan +Acked-by: David Rientjes +Cc: Akash Goel +Cc: Andrew Donnellan +Cc: Guenter Roeck +Cc: Salvatore Bonaccorso +Cc: [4.10+] +Link: http://lkml.kernel.org/r/20191219121256.26480-1-dja@axtens.net +Signed-off-by: Linus Torvalds +--- + kernel/relay.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/kernel/relay.c b/kernel/relay.c +index 90c7a002436d..dc82705e1cff 100644 +--- a/kernel/relay.c ++++ b/kernel/relay.c +@@ -581,6 +581,11 @@ struct rchan *relay_open(const char *base_filename, + return NULL; + + chan->buf = alloc_percpu(struct rchan_buf *); ++ if (!chan->buf) { ++ kfree(chan); ++ return NULL; ++ } ++ + chan->version = RELAYFS_CHANNEL_VERSION; + chan->n_subbufs = n_subbufs; + chan->subbuf_size = subbuf_size; +-- +2.27.0.rc0 + diff --git a/debian/patches/series b/debian/patches/series index 10d611c8a..3f23eca11 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -308,5 +308,6 @@ bugfix/all/scsi-sg-add-sg_remove_request-in-sg_write.patch bugfix/all/usb-gadget-fix-illegal-array-access-in-binding-with-.patch bugfix/all/netlabel-cope-with-NULL-catmap.patch bugfix/all/fs-binfmt_elf.c-allocate-initialized-memory-in-fill_.patch +bugfix/all/kernel-relay.c-handle-alloc_percpu-returning-NULL-in.patch # ABI maintenance From 789f116fbc2b5a89a8905309f882878863744d2e Mon Sep 17 00:00:00 2001 From: Salvatore Bonaccorso Date: Fri, 5 Jun 2020 12:34:01 +0200 Subject: [PATCH 12/17] mm: Fix mremap not considering huge pmd devmap (CVE-2020-10757) --- debian/changelog | 1 + ...emap-not-considering-huge-pmd-devmap.patch | 58 +++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 60 insertions(+) create mode 100644 debian/patches/bugfix/all/mm-Fix-mremap-not-considering-huge-pmd-devmap.patch diff --git a/debian/changelog b/debian/changelog index 13ca538b3..c023405ed 100644 --- a/debian/changelog +++ b/debian/changelog @@ -14,6 +14,7 @@ linux (4.19.118-2+deb10u1) UNRELEASED; urgency=medium (CVE-2020-10732) * kernel/relay.c: handle alloc_percpu returning NULL in relay_open (CVE-2019-19462) + * mm: Fix mremap not considering huge pmd devmap (CVE-2020-10757) -- Salvatore Bonaccorso Thu, 28 May 2020 23:02:30 +0200 diff --git a/debian/patches/bugfix/all/mm-Fix-mremap-not-considering-huge-pmd-devmap.patch b/debian/patches/bugfix/all/mm-Fix-mremap-not-considering-huge-pmd-devmap.patch new file mode 100644 index 000000000..70ec97519 --- /dev/null +++ b/debian/patches/bugfix/all/mm-Fix-mremap-not-considering-huge-pmd-devmap.patch @@ -0,0 +1,58 @@ +From: Fan Yang +Date: Thu, 4 Jun 2020 18:22:07 +0800 +Subject: mm: Fix mremap not considering huge pmd devmap +Origin: https://git.kernel.org/linus/5bfea2d9b17f1034a68147a8b03b9789af5700f9 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2020-10757 + +The original code in mm/mremap.c checks huge pmd by: + + if (is_swap_pmd(*old_pmd) || pmd_trans_huge(*old_pmd)) { + +However, a DAX mapped nvdimm is mapped as huge page (by default) but it +is not transparent huge page (_PAGE_PSE | PAGE_DEVMAP). This commit +changes the condition to include the case. + +This addresses CVE-2020-10757. + +Fixes: 5c7fb56e5e3f ("mm, dax: dax-pmd vs thp-pmd vs hugetlbfs-pmd") +Cc: +Reported-by: Fan Yang +Signed-off-by: Fan Yang +Tested-by: Fan Yang +Tested-by: Dan Williams +Reviewed-by: Dan Williams +Acked-by: Kirill A. Shutemov +Signed-off-by: Linus Torvalds +--- + arch/x86/include/asm/pgtable.h | 1 + + mm/mremap.c | 2 +- + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h +index f51d8997ed00..b8f46bbe69f4 100644 +--- a/arch/x86/include/asm/pgtable.h ++++ b/arch/x86/include/asm/pgtable.h +@@ -257,6 +257,7 @@ static inline int pmd_large(pmd_t pte) + } + + #ifdef CONFIG_TRANSPARENT_HUGEPAGE ++/* NOTE: when predicate huge page, consider also pmd_devmap, or use pmd_large */ + static inline int pmd_trans_huge(pmd_t pmd) + { + return (pmd_val(pmd) & (_PAGE_PSE|_PAGE_DEVMAP)) == _PAGE_PSE; +diff --git a/mm/mremap.c b/mm/mremap.c +index 6aa6ea605068..57b1f999f789 100644 +--- a/mm/mremap.c ++++ b/mm/mremap.c +@@ -266,7 +266,7 @@ unsigned long move_page_tables(struct vm_area_struct *vma, + new_pmd = alloc_new_pmd(vma->vm_mm, vma, new_addr); + if (!new_pmd) + break; +- if (is_swap_pmd(*old_pmd) || pmd_trans_huge(*old_pmd)) { ++ if (is_swap_pmd(*old_pmd) || pmd_trans_huge(*old_pmd) || pmd_devmap(*old_pmd)) { + if (extent == HPAGE_PMD_SIZE) { + bool moved; + /* See comment in move_ptes() */ +-- +2.27.0.rc0 + diff --git a/debian/patches/series b/debian/patches/series index 3f23eca11..04c22b16a 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -309,5 +309,6 @@ bugfix/all/usb-gadget-fix-illegal-array-access-in-binding-with-.patch bugfix/all/netlabel-cope-with-NULL-catmap.patch bugfix/all/fs-binfmt_elf.c-allocate-initialized-memory-in-fill_.patch bugfix/all/kernel-relay.c-handle-alloc_percpu-returning-NULL-in.patch +bugfix/all/mm-Fix-mremap-not-considering-huge-pmd-devmap.patch # ABI maintenance From 6e26711704bef28d1802fc763f567af726afb4bb Mon Sep 17 00:00:00 2001 From: Salvatore Bonaccorso Date: Sat, 6 Jun 2020 10:35:47 +0200 Subject: [PATCH 13/17] Add fixes for CVE-2019-3016 Cherry-pick 11 commits from the 4.19.118 including prerequisited to adress CVE-2019-3016. --- debian/changelog | 11 + ...VM-Introduce-a-new-guest-mapping-API.patch | 161 ++++++++++ ...ck-if-page-is-valid-in-kvm_vcpu_unma.patch | 36 +++ .../kvm-fix-compilation-on-aarch64.patch | 54 ++++ .../s390x/kvm-fix-compilation-on-s390.patch | 35 +++ .../kvm-fix-compile-on-s390-part-2.patch | 38 +++ ...-all-general-purpose-registers-after.patch | 67 ++++ ...sync-GUEST_BNDCFGS-when-it-comes-fro.patch | 58 ++++ ...Clean-up-host-s-steal-time-structure.patch | 86 +++++ ...e-KVM_VCPU_FLUSH_TLB-flag-is-not-mis.patch | 130 ++++++++ ...x86-kvm-Cache-gfn-to-pfn-translation.patch | 296 ++++++++++++++++++ .../x86-kvm-Introduce-kvm_-un-map_gfn.patch | 114 +++++++ debian/patches/series | 12 + 13 files changed, 1098 insertions(+) create mode 100644 debian/patches/bugfix/all/KVM-Introduce-a-new-guest-mapping-API.patch create mode 100644 debian/patches/bugfix/all/KVM-Properly-check-if-page-is-valid-in-kvm_vcpu_unma.patch create mode 100644 debian/patches/bugfix/arm64/kvm-fix-compilation-on-aarch64.patch create mode 100644 debian/patches/bugfix/s390x/kvm-fix-compilation-on-s390.patch create mode 100644 debian/patches/bugfix/s390x/kvm-fix-compile-on-s390-part-2.patch create mode 100644 debian/patches/bugfix/x86/KVM-VMX-Zero-out-all-general-purpose-registers-after.patch create mode 100644 debian/patches/bugfix/x86/KVM-nVMX-Always-sync-GUEST_BNDCFGS-when-it-comes-fro.patch create mode 100644 debian/patches/bugfix/x86/x86-KVM-Clean-up-host-s-steal-time-structure.patch create mode 100644 debian/patches/bugfix/x86/x86-KVM-Make-sure-KVM_VCPU_FLUSH_TLB-flag-is-not-mis.patch create mode 100644 debian/patches/bugfix/x86/x86-kvm-Cache-gfn-to-pfn-translation.patch create mode 100644 debian/patches/bugfix/x86/x86-kvm-Introduce-kvm_-un-map_gfn.patch diff --git a/debian/changelog b/debian/changelog index c023405ed..d2911c508 100644 --- a/debian/changelog +++ b/debian/changelog @@ -15,6 +15,17 @@ linux (4.19.118-2+deb10u1) UNRELEASED; urgency=medium * kernel/relay.c: handle alloc_percpu returning NULL in relay_open (CVE-2019-19462) * mm: Fix mremap not considering huge pmd devmap (CVE-2020-10757) + * [x86] KVM: VMX: Zero out *all* general purpose registers after VM-Exit + * [x86] KVM: nVMX: Always sync GUEST_BNDCFGS when it comes from vmcs01 + * KVM: Introduce a new guest mapping API + * [arm64] kvm: fix compilation on aarch64 + * [s390x] kvm: fix compilation on s390 + * [s390x] kvm: fix compile on s390 part 2 + * KVM: Properly check if "page" is valid in kvm_vcpu_unmap + * [x86] kvm: Introduce kvm_(un)map_gfn() (CVE-2019-3016) + * [x86] kvm: Cache gfn to pfn translation (CVE-2019-3016) + * [x86] KVM: Make sure KVM_VCPU_FLUSH_TLB flag is not missed (CVE-2019-3016) + * [x86] KVM: Clean up host's steal time structure (CVE-2019-3016) -- Salvatore Bonaccorso Thu, 28 May 2020 23:02:30 +0200 diff --git a/debian/patches/bugfix/all/KVM-Introduce-a-new-guest-mapping-API.patch b/debian/patches/bugfix/all/KVM-Introduce-a-new-guest-mapping-API.patch new file mode 100644 index 000000000..378b02428 --- /dev/null +++ b/debian/patches/bugfix/all/KVM-Introduce-a-new-guest-mapping-API.patch @@ -0,0 +1,161 @@ +From: KarimAllah Ahmed +Date: Thu, 31 Jan 2019 21:24:34 +0100 +Subject: [03/11] KVM: Introduce a new guest mapping API +Origin: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/commit?id=0125ed16a990014e27001f72fe75ad567da45f87 + +commit e45adf665a53df0db37f784ed87c6b57ddd81885 upstream. + +In KVM, specially for nested guests, there is a dominant pattern of: + + => map guest memory -> do_something -> unmap guest memory + +In addition to all this unnecessarily noise in the code due to boiler plate +code, most of the time the mapping function does not properly handle memory +that is not backed by "struct page". This new guest mapping API encapsulate +most of this boiler plate code and also handles guest memory that is not +backed by "struct page". + +The current implementation of this API is using memremap for memory that is +not backed by a "struct page" which would lead to a huge slow-down if it +was used for high-frequency mapping operations. The API does not have any +effect on current setups where guest memory is backed by a "struct page". +Further patches are going to also introduce a pfn-cache which would +significantly improve the performance of the memremap case. + +Signed-off-by: KarimAllah Ahmed +Reviewed-by: Konrad Rzeszutek Wilk +Signed-off-by: Paolo Bonzini +[bwh: Backported to 4.19 as dependency of commit 1eff70a9abd4 + "x86/kvm: Introduce kvm_(un)map_gfn()"] +Signed-off-by: Ben Hutchings +Signed-off-by: Sasha Levin +--- + include/linux/kvm_host.h | 28 ++++++++++++++++++ + virt/kvm/kvm_main.c | 64 ++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 92 insertions(+) + +diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h +index 0f99ecc01bc7..bef95dba14e8 100644 +--- a/include/linux/kvm_host.h ++++ b/include/linux/kvm_host.h +@@ -206,6 +206,32 @@ enum { + READING_SHADOW_PAGE_TABLES, + }; + ++#define KVM_UNMAPPED_PAGE ((void *) 0x500 + POISON_POINTER_DELTA) ++ ++struct kvm_host_map { ++ /* ++ * Only valid if the 'pfn' is managed by the host kernel (i.e. There is ++ * a 'struct page' for it. When using mem= kernel parameter some memory ++ * can be used as guest memory but they are not managed by host ++ * kernel). ++ * If 'pfn' is not managed by the host kernel, this field is ++ * initialized to KVM_UNMAPPED_PAGE. ++ */ ++ struct page *page; ++ void *hva; ++ kvm_pfn_t pfn; ++ kvm_pfn_t gfn; ++}; ++ ++/* ++ * Used to check if the mapping is valid or not. Never use 'kvm_host_map' ++ * directly to check for that. ++ */ ++static inline bool kvm_vcpu_mapped(struct kvm_host_map *map) ++{ ++ return !!map->hva; ++} ++ + /* + * Sometimes a large or cross-page mmio needs to be broken up into separate + * exits for userspace servicing. +@@ -711,7 +737,9 @@ struct kvm_memslots *kvm_vcpu_memslots(struct kvm_vcpu *vcpu); + struct kvm_memory_slot *kvm_vcpu_gfn_to_memslot(struct kvm_vcpu *vcpu, gfn_t gfn); + kvm_pfn_t kvm_vcpu_gfn_to_pfn_atomic(struct kvm_vcpu *vcpu, gfn_t gfn); + kvm_pfn_t kvm_vcpu_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn); ++int kvm_vcpu_map(struct kvm_vcpu *vcpu, gpa_t gpa, struct kvm_host_map *map); + struct page *kvm_vcpu_gfn_to_page(struct kvm_vcpu *vcpu, gfn_t gfn); ++void kvm_vcpu_unmap(struct kvm_vcpu *vcpu, struct kvm_host_map *map, bool dirty); + unsigned long kvm_vcpu_gfn_to_hva(struct kvm_vcpu *vcpu, gfn_t gfn); + unsigned long kvm_vcpu_gfn_to_hva_prot(struct kvm_vcpu *vcpu, gfn_t gfn, bool *writable); + int kvm_vcpu_read_guest_page(struct kvm_vcpu *vcpu, gfn_t gfn, void *data, int offset, +diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c +index 4e499b78569b..ec1479abb29d 100644 +--- a/virt/kvm/kvm_main.c ++++ b/virt/kvm/kvm_main.c +@@ -1705,6 +1705,70 @@ struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn) + } + EXPORT_SYMBOL_GPL(gfn_to_page); + ++static int __kvm_map_gfn(struct kvm_memory_slot *slot, gfn_t gfn, ++ struct kvm_host_map *map) ++{ ++ kvm_pfn_t pfn; ++ void *hva = NULL; ++ struct page *page = KVM_UNMAPPED_PAGE; ++ ++ if (!map) ++ return -EINVAL; ++ ++ pfn = gfn_to_pfn_memslot(slot, gfn); ++ if (is_error_noslot_pfn(pfn)) ++ return -EINVAL; ++ ++ if (pfn_valid(pfn)) { ++ page = pfn_to_page(pfn); ++ hva = kmap(page); ++ } else { ++ hva = memremap(pfn_to_hpa(pfn), PAGE_SIZE, MEMREMAP_WB); ++ } ++ ++ if (!hva) ++ return -EFAULT; ++ ++ map->page = page; ++ map->hva = hva; ++ map->pfn = pfn; ++ map->gfn = gfn; ++ ++ return 0; ++} ++ ++int kvm_vcpu_map(struct kvm_vcpu *vcpu, gfn_t gfn, struct kvm_host_map *map) ++{ ++ return __kvm_map_gfn(kvm_vcpu_gfn_to_memslot(vcpu, gfn), gfn, map); ++} ++EXPORT_SYMBOL_GPL(kvm_vcpu_map); ++ ++void kvm_vcpu_unmap(struct kvm_vcpu *vcpu, struct kvm_host_map *map, ++ bool dirty) ++{ ++ if (!map) ++ return; ++ ++ if (!map->hva) ++ return; ++ ++ if (map->page) ++ kunmap(map->page); ++ else ++ memunmap(map->hva); ++ ++ if (dirty) { ++ kvm_vcpu_mark_page_dirty(vcpu, map->gfn); ++ kvm_release_pfn_dirty(map->pfn); ++ } else { ++ kvm_release_pfn_clean(map->pfn); ++ } ++ ++ map->hva = NULL; ++ map->page = NULL; ++} ++EXPORT_SYMBOL_GPL(kvm_vcpu_unmap); ++ + struct page *kvm_vcpu_gfn_to_page(struct kvm_vcpu *vcpu, gfn_t gfn) + { + kvm_pfn_t pfn; +-- +2.27.0.rc0 + diff --git a/debian/patches/bugfix/all/KVM-Properly-check-if-page-is-valid-in-kvm_vcpu_unma.patch b/debian/patches/bugfix/all/KVM-Properly-check-if-page-is-valid-in-kvm_vcpu_unma.patch new file mode 100644 index 000000000..20d6bb262 --- /dev/null +++ b/debian/patches/bugfix/all/KVM-Properly-check-if-page-is-valid-in-kvm_vcpu_unma.patch @@ -0,0 +1,36 @@ +From: KarimAllah Ahmed +Date: Wed, 10 Jul 2019 11:13:13 +0200 +Subject: [07/11] KVM: Properly check if "page" is valid in kvm_vcpu_unmap +Origin: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/commit?id=ec81ed2fba221b8bb92b8010e82d92e1de3b39fa + +commit b614c6027896ff9ad6757122e84760d938cab15e upstream. + +The field "page" is initialized to KVM_UNMAPPED_PAGE when it is not used +(i.e. when the memory lives outside kernel control). So this check will +always end up using kunmap even for memremap regions. + +Fixes: e45adf665a53 ("KVM: Introduce a new guest mapping API") +Signed-off-by: KarimAllah Ahmed +Signed-off-by: Paolo Bonzini +Signed-off-by: Ben Hutchings +Signed-off-by: Sasha Levin +--- + virt/kvm/kvm_main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c +index 5b949aa273de..33b288469c70 100644 +--- a/virt/kvm/kvm_main.c ++++ b/virt/kvm/kvm_main.c +@@ -1754,7 +1754,7 @@ void kvm_vcpu_unmap(struct kvm_vcpu *vcpu, struct kvm_host_map *map, + if (!map->hva) + return; + +- if (map->page) ++ if (map->page != KVM_UNMAPPED_PAGE) + kunmap(map->page); + #ifdef CONFIG_HAS_IOMEM + else +-- +2.27.0.rc0 + diff --git a/debian/patches/bugfix/arm64/kvm-fix-compilation-on-aarch64.patch b/debian/patches/bugfix/arm64/kvm-fix-compilation-on-aarch64.patch new file mode 100644 index 000000000..a24c0086d --- /dev/null +++ b/debian/patches/bugfix/arm64/kvm-fix-compilation-on-aarch64.patch @@ -0,0 +1,54 @@ +From: Paolo Bonzini +Date: Fri, 17 May 2019 14:08:53 +0200 +Subject: [04/11] kvm: fix compilation on aarch64 +Origin: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/commit?id=94659e93c93c23dfaada78aaad45183867698f74 + +commit c011d23ba046826ccf8c4a4a6c1d01c9ccaa1403 upstream. + +Commit e45adf665a53 ("KVM: Introduce a new guest mapping API", 2019-01-31) +introduced a build failure on aarch64 defconfig: + +$ make -j$(nproc) ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- O=out defconfig \ + Image.gz +... +../arch/arm64/kvm/../../../virt/kvm/kvm_main.c: + In function '__kvm_map_gfn': +../arch/arm64/kvm/../../../virt/kvm/kvm_main.c:1763:9: error: + implicit declaration of function 'memremap'; did you mean 'memset_p'? +../arch/arm64/kvm/../../../virt/kvm/kvm_main.c:1763:46: error: + 'MEMREMAP_WB' undeclared (first use in this function) +../arch/arm64/kvm/../../../virt/kvm/kvm_main.c: + In function 'kvm_vcpu_unmap': +../arch/arm64/kvm/../../../virt/kvm/kvm_main.c:1795:3: error: + implicit declaration of function 'memunmap'; did you mean 'vm_munmap'? + +because these functions are declared in rather than , +and the former was being pulled in already on x86 but not on aarch64. + +Reported-by: Nathan Chancellor +Signed-off-by: Paolo Bonzini +[bwh: Backported to 4.19: adjust context] +Signed-off-by: Ben Hutchings +Signed-off-by: Sasha Levin +--- + virt/kvm/kvm_main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c +index ec1479abb29d..4a5ea263edf6 100644 +--- a/virt/kvm/kvm_main.c ++++ b/virt/kvm/kvm_main.c +@@ -52,9 +52,9 @@ + #include + #include + #include ++#include + + #include +-#include + #include + #include + #include +-- +2.27.0.rc0 + diff --git a/debian/patches/bugfix/s390x/kvm-fix-compilation-on-s390.patch b/debian/patches/bugfix/s390x/kvm-fix-compilation-on-s390.patch new file mode 100644 index 000000000..daf06e518 --- /dev/null +++ b/debian/patches/bugfix/s390x/kvm-fix-compilation-on-s390.patch @@ -0,0 +1,35 @@ +From: Paolo Bonzini +Date: Mon, 20 May 2019 12:06:36 +0200 +Subject: [05/11] kvm: fix compilation on s390 +Origin: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/commit?id=bef6507903d91be2d1a06c11d980a722b176bc09 + +commit d30b214d1d0addb7b2c9c78178d1501cd39a01fb upstream. + +s390 does not have memremap, even though in this particular case it +would be useful. + +Signed-off-by: Paolo Bonzini +Signed-off-by: Ben Hutchings +Signed-off-by: Sasha Levin +--- + virt/kvm/kvm_main.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c +index 4a5ea263edf6..f99b99b77a48 100644 +--- a/virt/kvm/kvm_main.c ++++ b/virt/kvm/kvm_main.c +@@ -1722,8 +1722,10 @@ static int __kvm_map_gfn(struct kvm_memory_slot *slot, gfn_t gfn, + if (pfn_valid(pfn)) { + page = pfn_to_page(pfn); + hva = kmap(page); ++#ifdef CONFIG_HAS_IOMEM + } else { + hva = memremap(pfn_to_hpa(pfn), PAGE_SIZE, MEMREMAP_WB); ++#endif + } + + if (!hva) +-- +2.27.0.rc0 + diff --git a/debian/patches/bugfix/s390x/kvm-fix-compile-on-s390-part-2.patch b/debian/patches/bugfix/s390x/kvm-fix-compile-on-s390-part-2.patch new file mode 100644 index 000000000..d7e2ebb29 --- /dev/null +++ b/debian/patches/bugfix/s390x/kvm-fix-compile-on-s390-part-2.patch @@ -0,0 +1,38 @@ +From: Christian Borntraeger +Date: Mon, 27 May 2019 10:28:25 +0200 +Subject: [06/11] kvm: fix compile on s390 part 2 +Origin: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/commit?id=e25441275142a0d57a51025213c4b6ef17b193e6 + +commit eb1f2f387db8c0d084581fb26e7faffde700bc8e upstream. + +We also need to fence the memunmap part. + +Fixes: e45adf665a53 ("KVM: Introduce a new guest mapping API") +Fixes: d30b214d1d0a (kvm: fix compilation on s390) +Cc: Michal Kubecek +Cc: KarimAllah Ahmed +Signed-off-by: Christian Borntraeger +Signed-off-by: Ben Hutchings +Signed-off-by: Sasha Levin +--- + virt/kvm/kvm_main.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c +index f99b99b77a48..5b949aa273de 100644 +--- a/virt/kvm/kvm_main.c ++++ b/virt/kvm/kvm_main.c +@@ -1756,8 +1756,10 @@ void kvm_vcpu_unmap(struct kvm_vcpu *vcpu, struct kvm_host_map *map, + + if (map->page) + kunmap(map->page); ++#ifdef CONFIG_HAS_IOMEM + else + memunmap(map->hva); ++#endif + + if (dirty) { + kvm_vcpu_mark_page_dirty(vcpu, map->gfn); +-- +2.27.0.rc0 + diff --git a/debian/patches/bugfix/x86/KVM-VMX-Zero-out-all-general-purpose-registers-after.patch b/debian/patches/bugfix/x86/KVM-VMX-Zero-out-all-general-purpose-registers-after.patch new file mode 100644 index 000000000..b997d0c01 --- /dev/null +++ b/debian/patches/bugfix/x86/KVM-VMX-Zero-out-all-general-purpose-registers-after.patch @@ -0,0 +1,67 @@ +From: Sean Christopherson +Date: Fri, 25 Jan 2019 07:40:50 -0800 +Subject: [01/11] KVM: VMX: Zero out *all* general purpose registers after + VM-Exit +Origin: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/commit?id=b4be98039a9224ec0cfc2b706e8e881b9ba53850 + +commit 0e0ab73c9a0243736bcd779b30b717e23ba9a56d upstream. + +...except RSP, which is restored by hardware as part of VM-Exit. + +Paolo theorized that restoring registers from the stack after a VM-Exit +in lieu of zeroing them could lead to speculative execution with the +guest's values, e.g. if the stack accesses miss the L1 cache[1]. +Zeroing XORs are dirt cheap, so just be ultra-paranoid. + +Note that the scratch register (currently RCX) used to save/restore the +guest state is also zeroed as its host-defined value is loaded via the +stack, just with a MOV instead of a POP. + +[1] https://patchwork.kernel.org/patch/10771539/#22441255 + +Fixes: 0cb5b30698fd ("kvm: vmx: Scrub hardware GPRs at VM-exit") +Cc: Jim Mattson +Signed-off-by: Sean Christopherson +Signed-off-by: Paolo Bonzini +[bwh: Backported to 4.19: adjust filename, context] +Signed-off-by: Ben Hutchings +Signed-off-by: Sasha Levin +--- + arch/x86/kvm/vmx.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c +index d37b48173e9c..e4d0ad06790e 100644 +--- a/arch/x86/kvm/vmx.c ++++ b/arch/x86/kvm/vmx.c +@@ -10841,6 +10841,15 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu) + "mov %%r13, %c[r13](%0) \n\t" + "mov %%r14, %c[r14](%0) \n\t" + "mov %%r15, %c[r15](%0) \n\t" ++ ++ /* ++ * Clear all general purpose registers (except RSP, which is loaded by ++ * the CPU during VM-Exit) to prevent speculative use of the guest's ++ * values, even those that are saved/loaded via the stack. In theory, ++ * an L1 cache miss when restoring registers could lead to speculative ++ * execution with the guest's values. Zeroing XORs are dirt cheap, ++ * i.e. the extra paranoia is essentially free. ++ */ + "xor %%r8d, %%r8d \n\t" + "xor %%r9d, %%r9d \n\t" + "xor %%r10d, %%r10d \n\t" +@@ -10855,8 +10864,11 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu) + + "xor %%eax, %%eax \n\t" + "xor %%ebx, %%ebx \n\t" ++ "xor %%ecx, %%ecx \n\t" ++ "xor %%edx, %%edx \n\t" + "xor %%esi, %%esi \n\t" + "xor %%edi, %%edi \n\t" ++ "xor %%ebp, %%ebp \n\t" + "pop %%" _ASM_BP "; pop %%" _ASM_DX " \n\t" + ".pushsection .rodata \n\t" + ".global vmx_return \n\t" +-- +2.27.0.rc0 + diff --git a/debian/patches/bugfix/x86/KVM-nVMX-Always-sync-GUEST_BNDCFGS-when-it-comes-fro.patch b/debian/patches/bugfix/x86/KVM-nVMX-Always-sync-GUEST_BNDCFGS-when-it-comes-fro.patch new file mode 100644 index 000000000..139ca7039 --- /dev/null +++ b/debian/patches/bugfix/x86/KVM-nVMX-Always-sync-GUEST_BNDCFGS-when-it-comes-fro.patch @@ -0,0 +1,58 @@ +From: Sean Christopherson +Date: Tue, 7 May 2019 09:06:28 -0700 +Subject: [02/11] KVM: nVMX: Always sync GUEST_BNDCFGS when it comes from + vmcs01 +Origin: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/commit?id=7570af489e73c55690d3666c360d0a6d56acdc12 + +commit 3b013a2972d5bc344d6eaa8f24fdfe268211e45f upstream. + +If L1 does not set VM_ENTRY_LOAD_BNDCFGS, then L1's BNDCFGS value must +be propagated to vmcs02 since KVM always runs with VM_ENTRY_LOAD_BNDCFGS +when MPX is supported. Because the value effectively comes from vmcs01, +vmcs02 must be updated even if vmcs12 is clean. + +Fixes: 62cf9bd8118c4 ("KVM: nVMX: Fix emulation of VM_ENTRY_LOAD_BNDCFGS") +Cc: Liran Alon +Signed-off-by: Sean Christopherson +Signed-off-by: Paolo Bonzini +[bwh: Backported to 4.19: adjust filename, context] +Signed-off-by: Ben Hutchings +Signed-off-by: Sasha Levin +--- + arch/x86/kvm/vmx.c | 13 ++++++------- + 1 file changed, 6 insertions(+), 7 deletions(-) + +diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c +index e4d0ad06790e..ccbddc80ad55 100644 +--- a/arch/x86/kvm/vmx.c ++++ b/arch/x86/kvm/vmx.c +@@ -12137,13 +12137,9 @@ static void prepare_vmcs02_full(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12) + + set_cr4_guest_host_mask(vmx); + +- if (kvm_mpx_supported()) { +- if (vmx->nested.nested_run_pending && +- (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_BNDCFGS)) +- vmcs_write64(GUEST_BNDCFGS, vmcs12->guest_bndcfgs); +- else +- vmcs_write64(GUEST_BNDCFGS, vmx->nested.vmcs01_guest_bndcfgs); +- } ++ if (kvm_mpx_supported() && vmx->nested.nested_run_pending && ++ (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_BNDCFGS)) ++ vmcs_write64(GUEST_BNDCFGS, vmcs12->guest_bndcfgs); + + if (enable_vpid) { + if (nested_cpu_has_vpid(vmcs12) && vmx->nested.vpid02) +@@ -12207,6 +12203,9 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12, + kvm_set_dr(vcpu, 7, vcpu->arch.dr7); + vmcs_write64(GUEST_IA32_DEBUGCTL, vmx->nested.vmcs01_debugctl); + } ++ if (kvm_mpx_supported() && (!vmx->nested.nested_run_pending || ++ !(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_BNDCFGS))) ++ vmcs_write64(GUEST_BNDCFGS, vmx->nested.vmcs01_guest_bndcfgs); + if (vmx->nested.nested_run_pending) { + vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, + vmcs12->vm_entry_intr_info_field); +-- +2.27.0.rc0 + diff --git a/debian/patches/bugfix/x86/x86-KVM-Clean-up-host-s-steal-time-structure.patch b/debian/patches/bugfix/x86/x86-KVM-Clean-up-host-s-steal-time-structure.patch new file mode 100644 index 000000000..38a102f7c --- /dev/null +++ b/debian/patches/bugfix/x86/x86-KVM-Clean-up-host-s-steal-time-structure.patch @@ -0,0 +1,86 @@ +From: Boris Ostrovsky +Date: Fri, 6 Dec 2019 15:36:12 +0000 +Subject: [11/11] x86/KVM: Clean up host's steal time structure +Origin: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/commit?id=c434092ef8172ed027f2bd9afcd42c0ee5002b85 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2019-3016 + +commit a6bd811f1209fe1c64c9f6fd578101d6436c6b6e upstream. + +Now that we are mapping kvm_steal_time from the guest directly we +don't need keep a copy of it in kvm_vcpu_arch.st. The same is true +for the stime field. + +This is part of CVE-2019-3016. + +Signed-off-by: Boris Ostrovsky +Reviewed-by: Joao Martins +Signed-off-by: Paolo Bonzini +Signed-off-by: Ben Hutchings +Signed-off-by: Sasha Levin +--- + arch/x86/include/asm/kvm_host.h | 3 +-- + arch/x86/kvm/x86.c | 11 +++-------- + 2 files changed, 4 insertions(+), 10 deletions(-) + +diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h +index ca9c7110b99d..33136395db8f 100644 +--- a/arch/x86/include/asm/kvm_host.h ++++ b/arch/x86/include/asm/kvm_host.h +@@ -622,10 +622,9 @@ struct kvm_vcpu_arch { + bool pvclock_set_guest_stopped_request; + + struct { ++ u8 preempted; + u64 msr_val; + u64 last_steal; +- struct gfn_to_hva_cache stime; +- struct kvm_steal_time steal; + struct gfn_to_pfn_cache cache; + } st; + +diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c +index d77822e03ff6..6bfc9eaf8dee 100644 +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -2418,7 +2418,7 @@ static void record_steal_time(struct kvm_vcpu *vcpu) + if (xchg(&st->preempted, 0) & KVM_VCPU_FLUSH_TLB) + kvm_vcpu_flush_tlb(vcpu, false); + +- vcpu->arch.st.steal.preempted = 0; ++ vcpu->arch.st.preempted = 0; + + if (st->version & 1) + st->version += 1; /* first time write, random junk */ +@@ -2577,11 +2577,6 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) + if (data & KVM_STEAL_RESERVED_MASK) + return 1; + +- if (kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.st.stime, +- data & KVM_STEAL_VALID_BITS, +- sizeof(struct kvm_steal_time))) +- return 1; +- + vcpu->arch.st.msr_val = data; + + if (!(data & KVM_MSR_ENABLED)) +@@ -3280,7 +3275,7 @@ static void kvm_steal_time_set_preempted(struct kvm_vcpu *vcpu) + if (!(vcpu->arch.st.msr_val & KVM_MSR_ENABLED)) + return; + +- if (vcpu->arch.st.steal.preempted) ++ if (vcpu->arch.st.preempted) + return; + + if (kvm_map_gfn(vcpu, vcpu->arch.st.msr_val >> PAGE_SHIFT, &map, +@@ -3290,7 +3285,7 @@ static void kvm_steal_time_set_preempted(struct kvm_vcpu *vcpu) + st = map.hva + + offset_in_page(vcpu->arch.st.msr_val & KVM_STEAL_VALID_BITS); + +- st->preempted = vcpu->arch.st.steal.preempted = KVM_VCPU_PREEMPTED; ++ st->preempted = vcpu->arch.st.preempted = KVM_VCPU_PREEMPTED; + + kvm_unmap_gfn(vcpu, &map, &vcpu->arch.st.cache, true, true); + } +-- +2.27.0.rc0 + diff --git a/debian/patches/bugfix/x86/x86-KVM-Make-sure-KVM_VCPU_FLUSH_TLB-flag-is-not-mis.patch b/debian/patches/bugfix/x86/x86-KVM-Make-sure-KVM_VCPU_FLUSH_TLB-flag-is-not-mis.patch new file mode 100644 index 000000000..d6235ad03 --- /dev/null +++ b/debian/patches/bugfix/x86/x86-KVM-Make-sure-KVM_VCPU_FLUSH_TLB-flag-is-not-mis.patch @@ -0,0 +1,130 @@ +From: Boris Ostrovsky +Date: Thu, 5 Dec 2019 03:45:32 +0000 +Subject: [10/11] x86/KVM: Make sure KVM_VCPU_FLUSH_TLB flag is not missed +Origin: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/commit?id=b5b79c757e6f22f17d8ddf2979abb7bf231bb327 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2019-3016 + +commit b043138246a41064527cf019a3d51d9f015e9796 upstream. + +There is a potential race in record_steal_time() between setting +host-local vcpu->arch.st.steal.preempted to zero (i.e. clearing +KVM_VCPU_PREEMPTED) and propagating this value to the guest with +kvm_write_guest_cached(). Between those two events the guest may +still see KVM_VCPU_PREEMPTED in its copy of kvm_steal_time, set +KVM_VCPU_FLUSH_TLB and assume that hypervisor will do the right +thing. Which it won't. + +Instad of copying, we should map kvm_steal_time and that will +guarantee atomicity of accesses to @preempted. + +This is part of CVE-2019-3016. + +Signed-off-by: Boris Ostrovsky +Reviewed-by: Joao Martins +Signed-off-by: Paolo Bonzini +[bwh: Backported to 4.19: No tracepoint in record_steal_time().] +Signed-off-by: Ben Hutchings +Signed-off-by: Sasha Levin +--- + arch/x86/kvm/x86.c | 49 +++++++++++++++++++++++++++------------------- + 1 file changed, 29 insertions(+), 20 deletions(-) + +diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c +index 6916f46909ab..d77822e03ff6 100644 +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -2397,43 +2397,45 @@ static void kvm_vcpu_flush_tlb(struct kvm_vcpu *vcpu, bool invalidate_gpa) + + static void record_steal_time(struct kvm_vcpu *vcpu) + { ++ struct kvm_host_map map; ++ struct kvm_steal_time *st; ++ + if (!(vcpu->arch.st.msr_val & KVM_MSR_ENABLED)) + return; + +- if (unlikely(kvm_read_guest_cached(vcpu->kvm, &vcpu->arch.st.stime, +- &vcpu->arch.st.steal, sizeof(struct kvm_steal_time)))) ++ /* -EAGAIN is returned in atomic context so we can just return. */ ++ if (kvm_map_gfn(vcpu, vcpu->arch.st.msr_val >> PAGE_SHIFT, ++ &map, &vcpu->arch.st.cache, false)) + return; + ++ st = map.hva + ++ offset_in_page(vcpu->arch.st.msr_val & KVM_STEAL_VALID_BITS); ++ + /* + * Doing a TLB flush here, on the guest's behalf, can avoid + * expensive IPIs. + */ +- if (xchg(&vcpu->arch.st.steal.preempted, 0) & KVM_VCPU_FLUSH_TLB) ++ if (xchg(&st->preempted, 0) & KVM_VCPU_FLUSH_TLB) + kvm_vcpu_flush_tlb(vcpu, false); + +- if (vcpu->arch.st.steal.version & 1) +- vcpu->arch.st.steal.version += 1; /* first time write, random junk */ ++ vcpu->arch.st.steal.preempted = 0; + +- vcpu->arch.st.steal.version += 1; ++ if (st->version & 1) ++ st->version += 1; /* first time write, random junk */ + +- kvm_write_guest_cached(vcpu->kvm, &vcpu->arch.st.stime, +- &vcpu->arch.st.steal, sizeof(struct kvm_steal_time)); ++ st->version += 1; + + smp_wmb(); + +- vcpu->arch.st.steal.steal += current->sched_info.run_delay - ++ st->steal += current->sched_info.run_delay - + vcpu->arch.st.last_steal; + vcpu->arch.st.last_steal = current->sched_info.run_delay; + +- kvm_write_guest_cached(vcpu->kvm, &vcpu->arch.st.stime, +- &vcpu->arch.st.steal, sizeof(struct kvm_steal_time)); +- + smp_wmb(); + +- vcpu->arch.st.steal.version += 1; ++ st->version += 1; + +- kvm_write_guest_cached(vcpu->kvm, &vcpu->arch.st.stime, +- &vcpu->arch.st.steal, sizeof(struct kvm_steal_time)); ++ kvm_unmap_gfn(vcpu, &map, &vcpu->arch.st.cache, true, false); + } + + int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) +@@ -3272,18 +3274,25 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) + + static void kvm_steal_time_set_preempted(struct kvm_vcpu *vcpu) + { ++ struct kvm_host_map map; ++ struct kvm_steal_time *st; ++ + if (!(vcpu->arch.st.msr_val & KVM_MSR_ENABLED)) + return; + + if (vcpu->arch.st.steal.preempted) + return; + +- vcpu->arch.st.steal.preempted = KVM_VCPU_PREEMPTED; ++ if (kvm_map_gfn(vcpu, vcpu->arch.st.msr_val >> PAGE_SHIFT, &map, ++ &vcpu->arch.st.cache, true)) ++ return; ++ ++ st = map.hva + ++ offset_in_page(vcpu->arch.st.msr_val & KVM_STEAL_VALID_BITS); ++ ++ st->preempted = vcpu->arch.st.steal.preempted = KVM_VCPU_PREEMPTED; + +- kvm_write_guest_offset_cached(vcpu->kvm, &vcpu->arch.st.stime, +- &vcpu->arch.st.steal.preempted, +- offsetof(struct kvm_steal_time, preempted), +- sizeof(vcpu->arch.st.steal.preempted)); ++ kvm_unmap_gfn(vcpu, &map, &vcpu->arch.st.cache, true, true); + } + + void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) +-- +2.27.0.rc0 + diff --git a/debian/patches/bugfix/x86/x86-kvm-Cache-gfn-to-pfn-translation.patch b/debian/patches/bugfix/x86/x86-kvm-Cache-gfn-to-pfn-translation.patch new file mode 100644 index 000000000..56a2e14dc --- /dev/null +++ b/debian/patches/bugfix/x86/x86-kvm-Cache-gfn-to-pfn-translation.patch @@ -0,0 +1,296 @@ +From: Boris Ostrovsky +Date: Thu, 5 Dec 2019 01:30:51 +0000 +Subject: [09/11] x86/kvm: Cache gfn to pfn translation +Origin: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/commit?id=ccfc73e56da7c8e68ab6a543c5b8cd0b83c9e9bb +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2019-3016 + +commit 917248144db5d7320655dbb41d3af0b8a0f3d589 upstream. + +__kvm_map_gfn()'s call to gfn_to_pfn_memslot() is +* relatively expensive +* in certain cases (such as when done from atomic context) cannot be called + +Stashing gfn-to-pfn mapping should help with both cases. + +This is part of CVE-2019-3016. + +Signed-off-by: Boris Ostrovsky +Reviewed-by: Joao Martins +Signed-off-by: Paolo Bonzini +Signed-off-by: Ben Hutchings +Signed-off-by: Sasha Levin +--- + arch/x86/include/asm/kvm_host.h | 1 + + arch/x86/kvm/x86.c | 10 ++++ + include/linux/kvm_host.h | 7 ++- + include/linux/kvm_types.h | 9 ++- + virt/kvm/kvm_main.c | 98 ++++++++++++++++++++++++++------- + 5 files changed, 103 insertions(+), 22 deletions(-) + +diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h +index 5c99b9bfce04..ca9c7110b99d 100644 +--- a/arch/x86/include/asm/kvm_host.h ++++ b/arch/x86/include/asm/kvm_host.h +@@ -626,6 +626,7 @@ struct kvm_vcpu_arch { + u64 last_steal; + struct gfn_to_hva_cache stime; + struct kvm_steal_time steal; ++ struct gfn_to_pfn_cache cache; + } st; + + u64 tsc_offset; +diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c +index 1a6e1aa2fb29..6916f46909ab 100644 +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -8634,6 +8634,9 @@ static void fx_init(struct kvm_vcpu *vcpu) + void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu) + { + void *wbinvd_dirty_mask = vcpu->arch.wbinvd_dirty_mask; ++ struct gfn_to_pfn_cache *cache = &vcpu->arch.st.cache; ++ ++ kvm_release_pfn(cache->pfn, cache->dirty, cache); + + kvmclock_reset(vcpu); + +@@ -9298,11 +9301,18 @@ int kvm_arch_create_memslot(struct kvm *kvm, struct kvm_memory_slot *slot, + + void kvm_arch_memslots_updated(struct kvm *kvm, u64 gen) + { ++ struct kvm_vcpu *vcpu; ++ int i; ++ + /* + * memslots->generation has been incremented. + * mmio generation may have reached its maximum value. + */ + kvm_mmu_invalidate_mmio_sptes(kvm, gen); ++ ++ /* Force re-initialization of steal_time cache */ ++ kvm_for_each_vcpu(i, vcpu, kvm) ++ kvm_vcpu_kick(vcpu); + } + + int kvm_arch_prepare_memory_region(struct kvm *kvm, +diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h +index 303c1a6916ce..dabb60f90726 100644 +--- a/include/linux/kvm_host.h ++++ b/include/linux/kvm_host.h +@@ -708,6 +708,7 @@ void kvm_set_pfn_dirty(kvm_pfn_t pfn); + void kvm_set_pfn_accessed(kvm_pfn_t pfn); + void kvm_get_pfn(kvm_pfn_t pfn); + ++void kvm_release_pfn(kvm_pfn_t pfn, bool dirty, struct gfn_to_pfn_cache *cache); + int kvm_read_guest_page(struct kvm *kvm, gfn_t gfn, void *data, int offset, + int len); + int kvm_read_guest_atomic(struct kvm *kvm, gpa_t gpa, void *data, +@@ -738,10 +739,12 @@ struct kvm_memory_slot *kvm_vcpu_gfn_to_memslot(struct kvm_vcpu *vcpu, gfn_t gfn + kvm_pfn_t kvm_vcpu_gfn_to_pfn_atomic(struct kvm_vcpu *vcpu, gfn_t gfn); + kvm_pfn_t kvm_vcpu_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn); + int kvm_vcpu_map(struct kvm_vcpu *vcpu, gpa_t gpa, struct kvm_host_map *map); +-int kvm_map_gfn(struct kvm_vcpu *vcpu, gfn_t gfn, struct kvm_host_map *map); ++int kvm_map_gfn(struct kvm_vcpu *vcpu, gfn_t gfn, struct kvm_host_map *map, ++ struct gfn_to_pfn_cache *cache, bool atomic); + struct page *kvm_vcpu_gfn_to_page(struct kvm_vcpu *vcpu, gfn_t gfn); + void kvm_vcpu_unmap(struct kvm_vcpu *vcpu, struct kvm_host_map *map, bool dirty); +-int kvm_unmap_gfn(struct kvm_vcpu *vcpu, struct kvm_host_map *map, bool dirty); ++int kvm_unmap_gfn(struct kvm_vcpu *vcpu, struct kvm_host_map *map, ++ struct gfn_to_pfn_cache *cache, bool dirty, bool atomic); + unsigned long kvm_vcpu_gfn_to_hva(struct kvm_vcpu *vcpu, gfn_t gfn); + unsigned long kvm_vcpu_gfn_to_hva_prot(struct kvm_vcpu *vcpu, gfn_t gfn, bool *writable); + int kvm_vcpu_read_guest_page(struct kvm_vcpu *vcpu, gfn_t gfn, void *data, int offset, +diff --git a/include/linux/kvm_types.h b/include/linux/kvm_types.h +index 8bf259dae9f6..a38729c8296f 100644 +--- a/include/linux/kvm_types.h ++++ b/include/linux/kvm_types.h +@@ -32,7 +32,7 @@ struct kvm_memslots; + + enum kvm_mr_change; + +-#include ++#include + + /* + * Address types: +@@ -63,4 +63,11 @@ struct gfn_to_hva_cache { + struct kvm_memory_slot *memslot; + }; + ++struct gfn_to_pfn_cache { ++ u64 generation; ++ gfn_t gfn; ++ kvm_pfn_t pfn; ++ bool dirty; ++}; ++ + #endif /* __KVM_TYPES_H__ */ +diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c +index 8e29b2e0bf2e..aca15bd1cc4c 100644 +--- a/virt/kvm/kvm_main.c ++++ b/virt/kvm/kvm_main.c +@@ -1705,27 +1705,72 @@ struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn) + } + EXPORT_SYMBOL_GPL(gfn_to_page); + ++void kvm_release_pfn(kvm_pfn_t pfn, bool dirty, struct gfn_to_pfn_cache *cache) ++{ ++ if (pfn == 0) ++ return; ++ ++ if (cache) ++ cache->pfn = cache->gfn = 0; ++ ++ if (dirty) ++ kvm_release_pfn_dirty(pfn); ++ else ++ kvm_release_pfn_clean(pfn); ++} ++ ++static void kvm_cache_gfn_to_pfn(struct kvm_memory_slot *slot, gfn_t gfn, ++ struct gfn_to_pfn_cache *cache, u64 gen) ++{ ++ kvm_release_pfn(cache->pfn, cache->dirty, cache); ++ ++ cache->pfn = gfn_to_pfn_memslot(slot, gfn); ++ cache->gfn = gfn; ++ cache->dirty = false; ++ cache->generation = gen; ++} ++ + static int __kvm_map_gfn(struct kvm_memslots *slots, gfn_t gfn, +- struct kvm_host_map *map) ++ struct kvm_host_map *map, ++ struct gfn_to_pfn_cache *cache, ++ bool atomic) + { + kvm_pfn_t pfn; + void *hva = NULL; + struct page *page = KVM_UNMAPPED_PAGE; + struct kvm_memory_slot *slot = __gfn_to_memslot(slots, gfn); ++ u64 gen = slots->generation; + + if (!map) + return -EINVAL; + +- pfn = gfn_to_pfn_memslot(slot, gfn); ++ if (cache) { ++ if (!cache->pfn || cache->gfn != gfn || ++ cache->generation != gen) { ++ if (atomic) ++ return -EAGAIN; ++ kvm_cache_gfn_to_pfn(slot, gfn, cache, gen); ++ } ++ pfn = cache->pfn; ++ } else { ++ if (atomic) ++ return -EAGAIN; ++ pfn = gfn_to_pfn_memslot(slot, gfn); ++ } + if (is_error_noslot_pfn(pfn)) + return -EINVAL; + + if (pfn_valid(pfn)) { + page = pfn_to_page(pfn); +- hva = kmap(page); ++ if (atomic) ++ hva = kmap_atomic(page); ++ else ++ hva = kmap(page); + #ifdef CONFIG_HAS_IOMEM +- } else { ++ } else if (!atomic) { + hva = memremap(pfn_to_hpa(pfn), PAGE_SIZE, MEMREMAP_WB); ++ } else { ++ return -EINVAL; + #endif + } + +@@ -1740,20 +1785,25 @@ static int __kvm_map_gfn(struct kvm_memslots *slots, gfn_t gfn, + return 0; + } + +-int kvm_map_gfn(struct kvm_vcpu *vcpu, gfn_t gfn, struct kvm_host_map *map) ++int kvm_map_gfn(struct kvm_vcpu *vcpu, gfn_t gfn, struct kvm_host_map *map, ++ struct gfn_to_pfn_cache *cache, bool atomic) + { +- return __kvm_map_gfn(kvm_memslots(vcpu->kvm), gfn, map); ++ return __kvm_map_gfn(kvm_memslots(vcpu->kvm), gfn, map, ++ cache, atomic); + } + EXPORT_SYMBOL_GPL(kvm_map_gfn); + + int kvm_vcpu_map(struct kvm_vcpu *vcpu, gfn_t gfn, struct kvm_host_map *map) + { +- return __kvm_map_gfn(kvm_vcpu_memslots(vcpu), gfn, map); ++ return __kvm_map_gfn(kvm_vcpu_memslots(vcpu), gfn, map, ++ NULL, false); + } + EXPORT_SYMBOL_GPL(kvm_vcpu_map); + + static void __kvm_unmap_gfn(struct kvm_memory_slot *memslot, +- struct kvm_host_map *map, bool dirty) ++ struct kvm_host_map *map, ++ struct gfn_to_pfn_cache *cache, ++ bool dirty, bool atomic) + { + if (!map) + return; +@@ -1761,34 +1811,44 @@ static void __kvm_unmap_gfn(struct kvm_memory_slot *memslot, + if (!map->hva) + return; + +- if (map->page != KVM_UNMAPPED_PAGE) +- kunmap(map->page); ++ if (map->page != KVM_UNMAPPED_PAGE) { ++ if (atomic) ++ kunmap_atomic(map->hva); ++ else ++ kunmap(map->page); ++ } + #ifdef CONFIG_HAS_IOMEM +- else ++ else if (!atomic) + memunmap(map->hva); ++ else ++ WARN_ONCE(1, "Unexpected unmapping in atomic context"); + #endif + +- if (dirty) { ++ if (dirty) + mark_page_dirty_in_slot(memslot, map->gfn); +- kvm_release_pfn_dirty(map->pfn); +- } else { +- kvm_release_pfn_clean(map->pfn); +- } ++ ++ if (cache) ++ cache->dirty |= dirty; ++ else ++ kvm_release_pfn(map->pfn, dirty, NULL); + + map->hva = NULL; + map->page = NULL; + } + +-int kvm_unmap_gfn(struct kvm_vcpu *vcpu, struct kvm_host_map *map, bool dirty) ++int kvm_unmap_gfn(struct kvm_vcpu *vcpu, struct kvm_host_map *map, ++ struct gfn_to_pfn_cache *cache, bool dirty, bool atomic) + { +- __kvm_unmap_gfn(gfn_to_memslot(vcpu->kvm, map->gfn), map, dirty); ++ __kvm_unmap_gfn(gfn_to_memslot(vcpu->kvm, map->gfn), map, ++ cache, dirty, atomic); + return 0; + } + EXPORT_SYMBOL_GPL(kvm_unmap_gfn); + + void kvm_vcpu_unmap(struct kvm_vcpu *vcpu, struct kvm_host_map *map, bool dirty) + { +- __kvm_unmap_gfn(kvm_vcpu_gfn_to_memslot(vcpu, map->gfn), map, dirty); ++ __kvm_unmap_gfn(kvm_vcpu_gfn_to_memslot(vcpu, map->gfn), map, NULL, ++ dirty, false); + } + EXPORT_SYMBOL_GPL(kvm_vcpu_unmap); + +-- +2.27.0.rc0 + diff --git a/debian/patches/bugfix/x86/x86-kvm-Introduce-kvm_-un-map_gfn.patch b/debian/patches/bugfix/x86/x86-kvm-Introduce-kvm_-un-map_gfn.patch new file mode 100644 index 000000000..dedbfea03 --- /dev/null +++ b/debian/patches/bugfix/x86/x86-kvm-Introduce-kvm_-un-map_gfn.patch @@ -0,0 +1,114 @@ +From: Boris Ostrovsky +Date: Tue, 12 Nov 2019 16:35:06 +0000 +Subject: [08/11] x86/kvm: Introduce kvm_(un)map_gfn() +Origin: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/commit?id=e36d68ec5090599058650152547d4a58ef3d79a0 +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2019-3016 + +commit 1eff70a9abd46f175defafd29bc17ad456f398a7 upstream. + +kvm_vcpu_(un)map operates on gfns from any current address space. +In certain cases we want to make sure we are not mapping SMRAM +and for that we can use kvm_(un)map_gfn() that we are introducing +in this patch. + +This is part of CVE-2019-3016. + +Signed-off-by: Boris Ostrovsky +Reviewed-by: Joao Martins +Signed-off-by: Paolo Bonzini +Signed-off-by: Ben Hutchings +Signed-off-by: Sasha Levin +--- + include/linux/kvm_host.h | 2 ++ + virt/kvm/kvm_main.c | 29 ++++++++++++++++++++++++----- + 2 files changed, 26 insertions(+), 5 deletions(-) + +diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h +index bef95dba14e8..303c1a6916ce 100644 +--- a/include/linux/kvm_host.h ++++ b/include/linux/kvm_host.h +@@ -738,8 +738,10 @@ struct kvm_memory_slot *kvm_vcpu_gfn_to_memslot(struct kvm_vcpu *vcpu, gfn_t gfn + kvm_pfn_t kvm_vcpu_gfn_to_pfn_atomic(struct kvm_vcpu *vcpu, gfn_t gfn); + kvm_pfn_t kvm_vcpu_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn); + int kvm_vcpu_map(struct kvm_vcpu *vcpu, gpa_t gpa, struct kvm_host_map *map); ++int kvm_map_gfn(struct kvm_vcpu *vcpu, gfn_t gfn, struct kvm_host_map *map); + struct page *kvm_vcpu_gfn_to_page(struct kvm_vcpu *vcpu, gfn_t gfn); + void kvm_vcpu_unmap(struct kvm_vcpu *vcpu, struct kvm_host_map *map, bool dirty); ++int kvm_unmap_gfn(struct kvm_vcpu *vcpu, struct kvm_host_map *map, bool dirty); + unsigned long kvm_vcpu_gfn_to_hva(struct kvm_vcpu *vcpu, gfn_t gfn); + unsigned long kvm_vcpu_gfn_to_hva_prot(struct kvm_vcpu *vcpu, gfn_t gfn, bool *writable); + int kvm_vcpu_read_guest_page(struct kvm_vcpu *vcpu, gfn_t gfn, void *data, int offset, +diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c +index 33b288469c70..8e29b2e0bf2e 100644 +--- a/virt/kvm/kvm_main.c ++++ b/virt/kvm/kvm_main.c +@@ -1705,12 +1705,13 @@ struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn) + } + EXPORT_SYMBOL_GPL(gfn_to_page); + +-static int __kvm_map_gfn(struct kvm_memory_slot *slot, gfn_t gfn, ++static int __kvm_map_gfn(struct kvm_memslots *slots, gfn_t gfn, + struct kvm_host_map *map) + { + kvm_pfn_t pfn; + void *hva = NULL; + struct page *page = KVM_UNMAPPED_PAGE; ++ struct kvm_memory_slot *slot = __gfn_to_memslot(slots, gfn); + + if (!map) + return -EINVAL; +@@ -1739,14 +1740,20 @@ static int __kvm_map_gfn(struct kvm_memory_slot *slot, gfn_t gfn, + return 0; + } + ++int kvm_map_gfn(struct kvm_vcpu *vcpu, gfn_t gfn, struct kvm_host_map *map) ++{ ++ return __kvm_map_gfn(kvm_memslots(vcpu->kvm), gfn, map); ++} ++EXPORT_SYMBOL_GPL(kvm_map_gfn); ++ + int kvm_vcpu_map(struct kvm_vcpu *vcpu, gfn_t gfn, struct kvm_host_map *map) + { +- return __kvm_map_gfn(kvm_vcpu_gfn_to_memslot(vcpu, gfn), gfn, map); ++ return __kvm_map_gfn(kvm_vcpu_memslots(vcpu), gfn, map); + } + EXPORT_SYMBOL_GPL(kvm_vcpu_map); + +-void kvm_vcpu_unmap(struct kvm_vcpu *vcpu, struct kvm_host_map *map, +- bool dirty) ++static void __kvm_unmap_gfn(struct kvm_memory_slot *memslot, ++ struct kvm_host_map *map, bool dirty) + { + if (!map) + return; +@@ -1762,7 +1769,7 @@ void kvm_vcpu_unmap(struct kvm_vcpu *vcpu, struct kvm_host_map *map, + #endif + + if (dirty) { +- kvm_vcpu_mark_page_dirty(vcpu, map->gfn); ++ mark_page_dirty_in_slot(memslot, map->gfn); + kvm_release_pfn_dirty(map->pfn); + } else { + kvm_release_pfn_clean(map->pfn); +@@ -1771,6 +1778,18 @@ void kvm_vcpu_unmap(struct kvm_vcpu *vcpu, struct kvm_host_map *map, + map->hva = NULL; + map->page = NULL; + } ++ ++int kvm_unmap_gfn(struct kvm_vcpu *vcpu, struct kvm_host_map *map, bool dirty) ++{ ++ __kvm_unmap_gfn(gfn_to_memslot(vcpu->kvm, map->gfn), map, dirty); ++ return 0; ++} ++EXPORT_SYMBOL_GPL(kvm_unmap_gfn); ++ ++void kvm_vcpu_unmap(struct kvm_vcpu *vcpu, struct kvm_host_map *map, bool dirty) ++{ ++ __kvm_unmap_gfn(kvm_vcpu_gfn_to_memslot(vcpu, map->gfn), map, dirty); ++} + EXPORT_SYMBOL_GPL(kvm_vcpu_unmap); + + struct page *kvm_vcpu_gfn_to_page(struct kvm_vcpu *vcpu, gfn_t gfn) +-- +2.27.0.rc0 + diff --git a/debian/patches/series b/debian/patches/series index 04c22b16a..dbdddb875 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -310,5 +310,17 @@ bugfix/all/netlabel-cope-with-NULL-catmap.patch bugfix/all/fs-binfmt_elf.c-allocate-initialized-memory-in-fill_.patch bugfix/all/kernel-relay.c-handle-alloc_percpu-returning-NULL-in.patch bugfix/all/mm-Fix-mremap-not-considering-huge-pmd-devmap.patch +# pre-requisites and CVE-2019-3016 +bugfix/x86/KVM-VMX-Zero-out-all-general-purpose-registers-after.patch +bugfix/x86/KVM-nVMX-Always-sync-GUEST_BNDCFGS-when-it-comes-fro.patch +bugfix/all/KVM-Introduce-a-new-guest-mapping-API.patch +bugfix/arm64/kvm-fix-compilation-on-aarch64.patch +bugfix/s390x/kvm-fix-compilation-on-s390.patch +bugfix/s390x/kvm-fix-compile-on-s390-part-2.patch +bugfix/all/KVM-Properly-check-if-page-is-valid-in-kvm_vcpu_unma.patch +bugfix/x86/x86-kvm-Introduce-kvm_-un-map_gfn.patch +bugfix/x86/x86-kvm-Cache-gfn-to-pfn-translation.patch +bugfix/x86/x86-KVM-Make-sure-KVM_VCPU_FLUSH_TLB-flag-is-not-mis.patch +bugfix/x86/x86-KVM-Clean-up-host-s-steal-time-structure.patch # ABI maintenance From ff5ad5a3d1175fdccde72067808b1d6fcea8a31e Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sun, 7 Jun 2020 00:46:11 +0100 Subject: [PATCH 14/17] propagate_one(): mnt_set_mountpoint() needs mount_lock A similar issue to CVE-2020-12114. --- debian/changelog | 4 ++ ...-mnt_set_mountpoint-needs-mount_lock.patch | 45 +++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 50 insertions(+) create mode 100644 debian/patches/bugfix/all/propagate_one-mnt_set_mountpoint-needs-mount_lock.patch diff --git a/debian/changelog b/debian/changelog index d2911c508..0c78411a1 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,5 +1,6 @@ linux (4.19.118-2+deb10u1) UNRELEASED; urgency=medium + [ Salvatore Bonaccorso ] * selinux: properly handle multiple messages in selinux_netlink_send() (CVE-2020-10751) * fs/namespace.c: fix mountpoint reference counter race (CVE-2020-12114) @@ -27,6 +28,9 @@ linux (4.19.118-2+deb10u1) UNRELEASED; urgency=medium * [x86] KVM: Make sure KVM_VCPU_FLUSH_TLB flag is not missed (CVE-2019-3016) * [x86] KVM: Clean up host's steal time structure (CVE-2019-3016) + [ Ben Hutchings ] + * propagate_one(): mnt_set_mountpoint() needs mount_lock + -- Salvatore Bonaccorso Thu, 28 May 2020 23:02:30 +0200 linux (4.19.118-2) buster; urgency=medium diff --git a/debian/patches/bugfix/all/propagate_one-mnt_set_mountpoint-needs-mount_lock.patch b/debian/patches/bugfix/all/propagate_one-mnt_set_mountpoint-needs-mount_lock.patch new file mode 100644 index 000000000..12e6c2410 --- /dev/null +++ b/debian/patches/bugfix/all/propagate_one-mnt_set_mountpoint-needs-mount_lock.patch @@ -0,0 +1,45 @@ +From: Al Viro +Date: Mon, 27 Apr 2020 10:26:22 -0400 +Subject: propagate_one(): mnt_set_mountpoint() needs mount_lock +Origin: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit?id=fa87bf609aa173b5dce91d23cd3dcebd9e846124 + +commit b0d3869ce9eeacbb1bbd541909beeef4126426d5 upstream. + +... to protect the modification of mp->m_count done by it. Most of +the places that modify that thing also have namespace_lock held, +but not all of them can do so, so we really need mount_lock here. +Kudos to Piotr Krysiuk , who'd spotted a related +bug in pivot_root(2) (fixed unnoticed in 5.3); search for other +similar turds has caught out this one. + +Cc: stable@kernel.org +Signed-off-by: Al Viro +Signed-off-by: Piotr Krysiuk +Signed-off-by: Greg Kroah-Hartman +--- + fs/pnode.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/fs/pnode.c b/fs/pnode.c +index 53d411a371ce..7910ae91f17e 100644 +--- a/fs/pnode.c ++++ b/fs/pnode.c +@@ -266,14 +266,13 @@ static int propagate_one(struct mount *m) + if (IS_ERR(child)) + return PTR_ERR(child); + child->mnt.mnt_flags &= ~MNT_LOCKED; ++ read_seqlock_excl(&mount_lock); + mnt_set_mountpoint(m, mp, child); ++ if (m->mnt_master != dest_master) ++ SET_MNT_MARK(m->mnt_master); ++ read_sequnlock_excl(&mount_lock); + last_dest = m; + last_source = child; +- if (m->mnt_master != dest_master) { +- read_seqlock_excl(&mount_lock); +- SET_MNT_MARK(m->mnt_master); +- read_sequnlock_excl(&mount_lock); +- } + hlist_add_head(&child->mnt_hash, list); + return count_mounts(m->mnt_ns, child); + } diff --git a/debian/patches/series b/debian/patches/series index dbdddb875..027deb9a1 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -302,6 +302,7 @@ bugfix/all/blktrace-fix-dereference-after-null-check.patch bugfix/s390x/s390-mm-fix-page-table-upgrade-vs-2ndary-address-mod.patch bugfix/all/selinux-properly-handle-multiple-messages-in-selinux.patch bugfix/all/fs-namespace.c-fix-mountpoint-reference-counter-race.patch +bugfix/all/propagate_one-mnt_set_mountpoint-needs-mount_lock.patch bugfix/all/usb-core-fix-free-while-in-use-bug-in-the-usb-s-glib.patch bugfix/x86/kvm-svm-fix-potential-memory-leak-in-svm_cpu_init.patch bugfix/all/scsi-sg-add-sg_remove_request-in-sg_write.patch From 22423990cd19eabba85940c9e759119850449476 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sun, 7 Jun 2020 01:13:16 +0100 Subject: [PATCH 15/17] Drop "KVM: VMX: Zero out *all* general purpose registers after VM-Exit" This is not needed to fix CVE-2019-3016, and is addressing an issue that's so far theoretical. It also needs a further fix to avoid causing a more serious regression (depending on the compiler behaviour). --- debian/changelog | 1 - ...-all-general-purpose-registers-after.patch | 67 ------------------- debian/patches/series | 1 - 3 files changed, 69 deletions(-) delete mode 100644 debian/patches/bugfix/x86/KVM-VMX-Zero-out-all-general-purpose-registers-after.patch diff --git a/debian/changelog b/debian/changelog index 0c78411a1..27c77c2ee 100644 --- a/debian/changelog +++ b/debian/changelog @@ -16,7 +16,6 @@ linux (4.19.118-2+deb10u1) UNRELEASED; urgency=medium * kernel/relay.c: handle alloc_percpu returning NULL in relay_open (CVE-2019-19462) * mm: Fix mremap not considering huge pmd devmap (CVE-2020-10757) - * [x86] KVM: VMX: Zero out *all* general purpose registers after VM-Exit * [x86] KVM: nVMX: Always sync GUEST_BNDCFGS when it comes from vmcs01 * KVM: Introduce a new guest mapping API * [arm64] kvm: fix compilation on aarch64 diff --git a/debian/patches/bugfix/x86/KVM-VMX-Zero-out-all-general-purpose-registers-after.patch b/debian/patches/bugfix/x86/KVM-VMX-Zero-out-all-general-purpose-registers-after.patch deleted file mode 100644 index b997d0c01..000000000 --- a/debian/patches/bugfix/x86/KVM-VMX-Zero-out-all-general-purpose-registers-after.patch +++ /dev/null @@ -1,67 +0,0 @@ -From: Sean Christopherson -Date: Fri, 25 Jan 2019 07:40:50 -0800 -Subject: [01/11] KVM: VMX: Zero out *all* general purpose registers after - VM-Exit -Origin: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/commit?id=b4be98039a9224ec0cfc2b706e8e881b9ba53850 - -commit 0e0ab73c9a0243736bcd779b30b717e23ba9a56d upstream. - -...except RSP, which is restored by hardware as part of VM-Exit. - -Paolo theorized that restoring registers from the stack after a VM-Exit -in lieu of zeroing them could lead to speculative execution with the -guest's values, e.g. if the stack accesses miss the L1 cache[1]. -Zeroing XORs are dirt cheap, so just be ultra-paranoid. - -Note that the scratch register (currently RCX) used to save/restore the -guest state is also zeroed as its host-defined value is loaded via the -stack, just with a MOV instead of a POP. - -[1] https://patchwork.kernel.org/patch/10771539/#22441255 - -Fixes: 0cb5b30698fd ("kvm: vmx: Scrub hardware GPRs at VM-exit") -Cc: Jim Mattson -Signed-off-by: Sean Christopherson -Signed-off-by: Paolo Bonzini -[bwh: Backported to 4.19: adjust filename, context] -Signed-off-by: Ben Hutchings -Signed-off-by: Sasha Levin ---- - arch/x86/kvm/vmx.c | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - -diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c -index d37b48173e9c..e4d0ad06790e 100644 ---- a/arch/x86/kvm/vmx.c -+++ b/arch/x86/kvm/vmx.c -@@ -10841,6 +10841,15 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu) - "mov %%r13, %c[r13](%0) \n\t" - "mov %%r14, %c[r14](%0) \n\t" - "mov %%r15, %c[r15](%0) \n\t" -+ -+ /* -+ * Clear all general purpose registers (except RSP, which is loaded by -+ * the CPU during VM-Exit) to prevent speculative use of the guest's -+ * values, even those that are saved/loaded via the stack. In theory, -+ * an L1 cache miss when restoring registers could lead to speculative -+ * execution with the guest's values. Zeroing XORs are dirt cheap, -+ * i.e. the extra paranoia is essentially free. -+ */ - "xor %%r8d, %%r8d \n\t" - "xor %%r9d, %%r9d \n\t" - "xor %%r10d, %%r10d \n\t" -@@ -10855,8 +10864,11 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu) - - "xor %%eax, %%eax \n\t" - "xor %%ebx, %%ebx \n\t" -+ "xor %%ecx, %%ecx \n\t" -+ "xor %%edx, %%edx \n\t" - "xor %%esi, %%esi \n\t" - "xor %%edi, %%edi \n\t" -+ "xor %%ebp, %%ebp \n\t" - "pop %%" _ASM_BP "; pop %%" _ASM_DX " \n\t" - ".pushsection .rodata \n\t" - ".global vmx_return \n\t" --- -2.27.0.rc0 - diff --git a/debian/patches/series b/debian/patches/series index 027deb9a1..d31e50ac1 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -312,7 +312,6 @@ bugfix/all/fs-binfmt_elf.c-allocate-initialized-memory-in-fill_.patch bugfix/all/kernel-relay.c-handle-alloc_percpu-returning-NULL-in.patch bugfix/all/mm-Fix-mremap-not-considering-huge-pmd-devmap.patch # pre-requisites and CVE-2019-3016 -bugfix/x86/KVM-VMX-Zero-out-all-general-purpose-registers-after.patch bugfix/x86/KVM-nVMX-Always-sync-GUEST_BNDCFGS-when-it-comes-fro.patch bugfix/all/KVM-Introduce-a-new-guest-mapping-API.patch bugfix/arm64/kvm-fix-compilation-on-aarch64.patch From da82e531d87687957fb75b57dde9f1df24bee7c8 Mon Sep 17 00:00:00 2001 From: Salvatore Bonaccorso Date: Wed, 13 May 2020 17:43:58 +0200 Subject: [PATCH 16/17] include/uapi/linux/swab.h: fix userspace breakage, use __BITS_PER_LONG for swap Closes: #960271 (cherry picked from commit a4fb2a7b7688f3a7cb36e17b9d8c661ac44a41a4) --- debian/changelog | 2 + ...ux-swab.h-fix-userspace-breakage-use.patch | 72 +++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 75 insertions(+) create mode 100644 debian/patches/bugfix/all/include-uapi-linux-swab.h-fix-userspace-breakage-use.patch diff --git a/debian/changelog b/debian/changelog index 27c77c2ee..6e8328a12 100644 --- a/debian/changelog +++ b/debian/changelog @@ -26,6 +26,8 @@ linux (4.19.118-2+deb10u1) UNRELEASED; urgency=medium * [x86] kvm: Cache gfn to pfn translation (CVE-2019-3016) * [x86] KVM: Make sure KVM_VCPU_FLUSH_TLB flag is not missed (CVE-2019-3016) * [x86] KVM: Clean up host's steal time structure (CVE-2019-3016) + * include/uapi/linux/swab.h: fix userspace breakage, use __BITS_PER_LONG for + swap (Closes: #960271) [ Ben Hutchings ] * propagate_one(): mnt_set_mountpoint() needs mount_lock diff --git a/debian/patches/bugfix/all/include-uapi-linux-swab.h-fix-userspace-breakage-use.patch b/debian/patches/bugfix/all/include-uapi-linux-swab.h-fix-userspace-breakage-use.patch new file mode 100644 index 000000000..8912e7b38 --- /dev/null +++ b/debian/patches/bugfix/all/include-uapi-linux-swab.h-fix-userspace-breakage-use.patch @@ -0,0 +1,72 @@ +From: Christian Borntraeger +Date: Thu, 20 Feb 2020 20:04:03 -0800 +Subject: include/uapi/linux/swab.h: fix userspace breakage, use + __BITS_PER_LONG for swap +Origin: https://git.kernel.org/linus/467d12f5c7842896d2de3ced74e4147ee29e97c8 +Bug-Debian: https://bugs.debian.org/960271 + +QEMU has a funny new build error message when I use the upstream kernel +headers: + + CC block/file-posix.o + In file included from /home/cborntra/REPOS/qemu/include/qemu/timer.h:4, + from /home/cborntra/REPOS/qemu/include/qemu/timed-average.h:29, + from /home/cborntra/REPOS/qemu/include/block/accounting.h:28, + from /home/cborntra/REPOS/qemu/include/block/block_int.h:27, + from /home/cborntra/REPOS/qemu/block/file-posix.c:30: + /usr/include/linux/swab.h: In function `__swab': + /home/cborntra/REPOS/qemu/include/qemu/bitops.h:20:34: error: "sizeof" is not defined, evaluates to 0 [-Werror=undef] + 20 | #define BITS_PER_LONG (sizeof (unsigned long) * BITS_PER_BYTE) + | ^~~~~~ + /home/cborntra/REPOS/qemu/include/qemu/bitops.h:20:41: error: missing binary operator before token "(" + 20 | #define BITS_PER_LONG (sizeof (unsigned long) * BITS_PER_BYTE) + | ^ + cc1: all warnings being treated as errors + make: *** [/home/cborntra/REPOS/qemu/rules.mak:69: block/file-posix.o] Error 1 + rm tests/qemu-iotests/socket_scm_helper.o + +This was triggered by commit d5767057c9a ("uapi: rename ext2_swab() to +swab() and share globally in swab.h"). That patch is doing + + #include + +but it uses BITS_PER_LONG. + +The kernel file asm/bitsperlong.h provide only __BITS_PER_LONG. + +Let us use the __ variant in swap.h + +Link: http://lkml.kernel.org/r/20200213142147.17604-1-borntraeger@de.ibm.com +Fixes: d5767057c9a ("uapi: rename ext2_swab() to swab() and share globally in swab.h") +Signed-off-by: Christian Borntraeger +Cc: Yury Norov +Cc: Allison Randal +Cc: Joe Perches +Cc: Thomas Gleixner +Cc: William Breathitt Gray +Cc: Torsten Hilbrich +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +--- + include/uapi/linux/swab.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/include/uapi/linux/swab.h b/include/uapi/linux/swab.h +index fa7f97da5b76..7272f85d6d6a 100644 +--- a/include/uapi/linux/swab.h ++++ b/include/uapi/linux/swab.h +@@ -135,9 +135,9 @@ static inline __attribute_const__ __u32 __fswahb32(__u32 val) + + static __always_inline unsigned long __swab(const unsigned long y) + { +-#if BITS_PER_LONG == 64 ++#if __BITS_PER_LONG == 64 + return __swab64(y); +-#else /* BITS_PER_LONG == 32 */ ++#else /* __BITS_PER_LONG == 32 */ + return __swab32(y); + #endif + } +-- +2.26.2 + diff --git a/debian/patches/series b/debian/patches/series index d31e50ac1..a1ce179ca 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -100,6 +100,7 @@ bugfix/all/kbuild-include-addtree-remove-quotes-before-matching-path.patch debian/revert-objtool-fix-config_stack_validation-y-warning.patch bugfix/all/mt76-use-the-correct-hweight8-function.patch bugfix/all/rtc-s35390a-set-uie_unsupported.patch +bugfix/all/include-uapi-linux-swab.h-fix-userspace-breakage-use.patch # Miscellaneous features From 51ce7dd8b395a9df30a66e8ececb4ff7f9bf2e72 Mon Sep 17 00:00:00 2001 From: Salvatore Bonaccorso Date: Sun, 7 Jun 2020 17:42:22 +0200 Subject: [PATCH 17/17] Prepare to release linux (4.19.118-2+deb10u1). --- debian/changelog | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index 0d06f2d30..70feff570 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -linux (4.19.118-2+deb10u1) UNRELEASED; urgency=medium +linux (4.19.118-2+deb10u1) buster-security; urgency=high [ Salvatore Bonaccorso ] * selinux: properly handle multiple messages in selinux_netlink_send() @@ -40,7 +40,7 @@ linux (4.19.118-2+deb10u1) UNRELEASED; urgency=medium - x86/speculation: Add Ivy Bridge to affected list * [x86] speculation: Do not match steppings, to avoid an ABI change - -- Salvatore Bonaccorso Thu, 28 May 2020 23:02:30 +0200 + -- Salvatore Bonaccorso Sun, 07 Jun 2020 17:42:22 +0200 linux (4.19.118-2) buster; urgency=medium