From: Greg Kroah-Hartman Date: Tue, 3 Mar 2020 13:06:23 +0000 (+0100) Subject: 4.14-stable patches X-Git-Tag: v4.19.108~32 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5bbd7f410d9e5c9c7b67352506c5cd7c02138ebd;p=thirdparty%2Fkernel%2Fstable-queue.git 4.14-stable patches added patches: kvm-check-for-a-bad-hva-before-dropping-into-the-ghc-slow-path.patch kvm-svm-override-default-mmio-mask-if-memory-encryption-is-enabled.patch mwifiex-drop-most-magic-numbers-from-mwifiex_process_tdls_action_frame.patch namei-only-return-echild-from-follow_dotdot_rcu.patch sched-fair-optimize-select_idle_cpu.patch --- diff --git a/queue-4.14/kvm-check-for-a-bad-hva-before-dropping-into-the-ghc-slow-path.patch b/queue-4.14/kvm-check-for-a-bad-hva-before-dropping-into-the-ghc-slow-path.patch new file mode 100644 index 00000000000..2cdb753bd9d --- /dev/null +++ b/queue-4.14/kvm-check-for-a-bad-hva-before-dropping-into-the-ghc-slow-path.patch @@ -0,0 +1,77 @@ +From fcfbc617547fc6d9552cb6c1c563b6a90ee98085 Mon Sep 17 00:00:00 2001 +From: Sean Christopherson +Date: Thu, 9 Jan 2020 15:56:18 -0800 +Subject: KVM: Check for a bad hva before dropping into the ghc slow path + +From: Sean Christopherson + +commit fcfbc617547fc6d9552cb6c1c563b6a90ee98085 upstream. + +When reading/writing using the guest/host cache, check for a bad hva +before checking for a NULL memslot, which triggers the slow path for +handing cross-page accesses. Because the memslot is nullified on error +by __kvm_gfn_to_hva_cache_init(), if the bad hva is encountered after +crossing into a new page, then the kvm_{read,write}_guest() slow path +could potentially write/access the first chunk prior to detecting the +bad hva. + +Arguably, performing a partial access is semantically correct from an +architectural perspective, but that behavior is certainly not intended. +In the original implementation, memslot was not explicitly nullified +and therefore the partial access behavior varied based on whether the +memslot itself was null, or if the hva was simply bad. The current +behavior was introduced as a seemingly unintentional side effect in +commit f1b9dd5eb86c ("kvm: Disallow wraparound in +kvm_gfn_to_hva_cache_init"), which justified the change with "since some +callers don't check the return code from this function, it sit seems +prudent to clear ghc->memslot in the event of an error". + +Regardless of intent, the partial access is dependent on _not_ checking +the result of the cache initialization, which is arguably a bug in its +own right, at best simply weird. + +Fixes: 8f964525a121 ("KVM: Allow cross page reads and writes from cached translations.") +Cc: Jim Mattson +Cc: Andrew Honig +Signed-off-by: Sean Christopherson +Signed-off-by: Paolo Bonzini +Signed-off-by: Greg Kroah-Hartman + +--- + virt/kvm/kvm_main.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +--- a/virt/kvm/kvm_main.c ++++ b/virt/kvm/kvm_main.c +@@ -2027,12 +2027,12 @@ int kvm_write_guest_offset_cached(struct + if (slots->generation != ghc->generation) + __kvm_gfn_to_hva_cache_init(slots, ghc, ghc->gpa, ghc->len); + +- if (unlikely(!ghc->memslot)) +- return kvm_write_guest(kvm, gpa, data, len); +- + if (kvm_is_error_hva(ghc->hva)) + return -EFAULT; + ++ if (unlikely(!ghc->memslot)) ++ return kvm_write_guest(kvm, gpa, data, len); ++ + r = __copy_to_user((void __user *)ghc->hva + offset, data, len); + if (r) + return -EFAULT; +@@ -2060,12 +2060,12 @@ int kvm_read_guest_cached(struct kvm *kv + if (slots->generation != ghc->generation) + __kvm_gfn_to_hva_cache_init(slots, ghc, ghc->gpa, ghc->len); + +- if (unlikely(!ghc->memslot)) +- return kvm_read_guest(kvm, ghc->gpa, data, len); +- + if (kvm_is_error_hva(ghc->hva)) + return -EFAULT; + ++ if (unlikely(!ghc->memslot)) ++ return kvm_read_guest(kvm, ghc->gpa, data, len); ++ + r = __copy_from_user(data, (void __user *)ghc->hva, len); + if (r) + return -EFAULT; diff --git a/queue-4.14/kvm-svm-override-default-mmio-mask-if-memory-encryption-is-enabled.patch b/queue-4.14/kvm-svm-override-default-mmio-mask-if-memory-encryption-is-enabled.patch new file mode 100644 index 00000000000..88124b7b661 --- /dev/null +++ b/queue-4.14/kvm-svm-override-default-mmio-mask-if-memory-encryption-is-enabled.patch @@ -0,0 +1,89 @@ +From 52918ed5fcf05d97d257f4131e19479da18f5d16 Mon Sep 17 00:00:00 2001 +From: Tom Lendacky +Date: Thu, 9 Jan 2020 17:42:16 -0600 +Subject: KVM: SVM: Override default MMIO mask if memory encryption is enabled + +From: Tom Lendacky + +commit 52918ed5fcf05d97d257f4131e19479da18f5d16 upstream. + +The KVM MMIO support uses bit 51 as the reserved bit to cause nested page +faults when a guest performs MMIO. The AMD memory encryption support uses +a CPUID function to define the encryption bit position. Given this, it is +possible that these bits can conflict. + +Use svm_hardware_setup() to override the MMIO mask if memory encryption +support is enabled. Various checks are performed to ensure that the mask +is properly defined and rsvd_bits() is used to generate the new mask (as +was done prior to the change that necessitated this patch). + +Fixes: 28a1f3ac1d0c ("kvm: x86: Set highest physical address bits in non-present/reserved SPTEs") +Suggested-by: Sean Christopherson +Reviewed-by: Sean Christopherson +Signed-off-by: Tom Lendacky +Signed-off-by: Paolo Bonzini +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/kvm/svm.c | 43 +++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 43 insertions(+) + +--- a/arch/x86/kvm/svm.c ++++ b/arch/x86/kvm/svm.c +@@ -1088,6 +1088,47 @@ static int avic_ga_log_notifier(u32 ga_t + return 0; + } + ++/* ++ * The default MMIO mask is a single bit (excluding the present bit), ++ * which could conflict with the memory encryption bit. Check for ++ * memory encryption support and override the default MMIO mask if ++ * memory encryption is enabled. ++ */ ++static __init void svm_adjust_mmio_mask(void) ++{ ++ unsigned int enc_bit, mask_bit; ++ u64 msr, mask; ++ ++ /* If there is no memory encryption support, use existing mask */ ++ if (cpuid_eax(0x80000000) < 0x8000001f) ++ return; ++ ++ /* If memory encryption is not enabled, use existing mask */ ++ rdmsrl(MSR_K8_SYSCFG, msr); ++ if (!(msr & MSR_K8_SYSCFG_MEM_ENCRYPT)) ++ return; ++ ++ enc_bit = cpuid_ebx(0x8000001f) & 0x3f; ++ mask_bit = boot_cpu_data.x86_phys_bits; ++ ++ /* Increment the mask bit if it is the same as the encryption bit */ ++ if (enc_bit == mask_bit) ++ mask_bit++; ++ ++ /* ++ * If the mask bit location is below 52, then some bits above the ++ * physical addressing limit will always be reserved, so use the ++ * rsvd_bits() function to generate the mask. This mask, along with ++ * the present bit, will be used to generate a page fault with ++ * PFER.RSV = 1. ++ * ++ * If the mask bit location is 52 (or above), then clear the mask. ++ */ ++ mask = (mask_bit < 52) ? rsvd_bits(mask_bit, 51) | PT_PRESENT_MASK : 0; ++ ++ kvm_mmu_set_mmio_spte_mask(mask, mask, PT_WRITABLE_MASK | PT_USER_MASK); ++} ++ + static __init int svm_hardware_setup(void) + { + int cpu; +@@ -1123,6 +1164,8 @@ static __init int svm_hardware_setup(voi + kvm_enable_efer_bits(EFER_SVME | EFER_LMSLE); + } + ++ svm_adjust_mmio_mask(); ++ + for_each_possible_cpu(cpu) { + r = svm_cpu_init(cpu); + if (r) diff --git a/queue-4.14/mwifiex-drop-most-magic-numbers-from-mwifiex_process_tdls_action_frame.patch b/queue-4.14/mwifiex-drop-most-magic-numbers-from-mwifiex_process_tdls_action_frame.patch new file mode 100644 index 00000000000..7e9ebb243f6 --- /dev/null +++ b/queue-4.14/mwifiex-drop-most-magic-numbers-from-mwifiex_process_tdls_action_frame.patch @@ -0,0 +1,225 @@ +From 70e5b8f445fd27fde0c5583460e82539a7242424 Mon Sep 17 00:00:00 2001 +From: Brian Norris +Date: Fri, 6 Dec 2019 11:45:35 -0800 +Subject: mwifiex: drop most magic numbers from mwifiex_process_tdls_action_frame() + +From: Brian Norris + +commit 70e5b8f445fd27fde0c5583460e82539a7242424 upstream. + +Before commit 1e58252e334d ("mwifiex: Fix heap overflow in +mmwifiex_process_tdls_action_frame()"), +mwifiex_process_tdls_action_frame() already had too many magic numbers. +But this commit just added a ton more, in the name of checking for +buffer overflows. That seems like a really bad idea. + +Let's make these magic numbers a little less magic, by +(a) factoring out 'pos[1]' as 'ie_len' +(b) using 'sizeof' on the appropriate source or destination fields where + possible, instead of bare numbers +(c) dropping redundant checks, per below. + +Regarding redundant checks: the beginning of the loop has this: + + if (pos + 2 + pos[1] > end) + break; + +but then individual 'case's include stuff like this: + + if (pos > end - 3) + return; + if (pos[1] != 1) + return; + +Note that the second 'return' (validating the length, pos[1]) combined +with the above condition (ensuring 'pos + 2 + length' doesn't exceed +'end'), makes the first 'return' (whose 'if' can be reworded as 'pos > +end - pos[1] - 2') redundant. Rather than unwind the magic numbers +there, just drop those conditions. + +Fixes: 1e58252e334d ("mwifiex: Fix heap overflow in mmwifiex_process_tdls_action_frame()") +Signed-off-by: Brian Norris +Signed-off-by: Kalle Valo +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/marvell/mwifiex/tdls.c | 75 ++++++++++------------------ + 1 file changed, 28 insertions(+), 47 deletions(-) + +--- a/drivers/net/wireless/marvell/mwifiex/tdls.c ++++ b/drivers/net/wireless/marvell/mwifiex/tdls.c +@@ -897,7 +897,7 @@ void mwifiex_process_tdls_action_frame(s + u8 *peer, *pos, *end; + u8 i, action, basic; + u16 cap = 0; +- int ie_len = 0; ++ int ies_len = 0; + + if (len < (sizeof(struct ethhdr) + 3)) + return; +@@ -919,7 +919,7 @@ void mwifiex_process_tdls_action_frame(s + pos = buf + sizeof(struct ethhdr) + 4; + /* payload 1+ category 1 + action 1 + dialog 1 */ + cap = get_unaligned_le16(pos); +- ie_len = len - sizeof(struct ethhdr) - TDLS_REQ_FIX_LEN; ++ ies_len = len - sizeof(struct ethhdr) - TDLS_REQ_FIX_LEN; + pos += 2; + break; + +@@ -929,7 +929,7 @@ void mwifiex_process_tdls_action_frame(s + /* payload 1+ category 1 + action 1 + dialog 1 + status code 2*/ + pos = buf + sizeof(struct ethhdr) + 6; + cap = get_unaligned_le16(pos); +- ie_len = len - sizeof(struct ethhdr) - TDLS_RESP_FIX_LEN; ++ ies_len = len - sizeof(struct ethhdr) - TDLS_RESP_FIX_LEN; + pos += 2; + break; + +@@ -937,7 +937,7 @@ void mwifiex_process_tdls_action_frame(s + if (len < (sizeof(struct ethhdr) + TDLS_CONFIRM_FIX_LEN)) + return; + pos = buf + sizeof(struct ethhdr) + TDLS_CONFIRM_FIX_LEN; +- ie_len = len - sizeof(struct ethhdr) - TDLS_CONFIRM_FIX_LEN; ++ ies_len = len - sizeof(struct ethhdr) - TDLS_CONFIRM_FIX_LEN; + break; + default: + mwifiex_dbg(priv->adapter, ERROR, "Unknown TDLS frame type.\n"); +@@ -950,33 +950,33 @@ void mwifiex_process_tdls_action_frame(s + + sta_ptr->tdls_cap.capab = cpu_to_le16(cap); + +- for (end = pos + ie_len; pos + 1 < end; pos += 2 + pos[1]) { +- if (pos + 2 + pos[1] > end) ++ for (end = pos + ies_len; pos + 1 < end; pos += 2 + pos[1]) { ++ u8 ie_len = pos[1]; ++ ++ if (pos + 2 + ie_len > end) + break; + + switch (*pos) { + case WLAN_EID_SUPP_RATES: +- if (pos[1] > 32) ++ if (ie_len > sizeof(sta_ptr->tdls_cap.rates)) + return; +- sta_ptr->tdls_cap.rates_len = pos[1]; +- for (i = 0; i < pos[1]; i++) ++ sta_ptr->tdls_cap.rates_len = ie_len; ++ for (i = 0; i < ie_len; i++) + sta_ptr->tdls_cap.rates[i] = pos[i + 2]; + break; + + case WLAN_EID_EXT_SUPP_RATES: +- if (pos[1] > 32) ++ if (ie_len > sizeof(sta_ptr->tdls_cap.rates)) + return; + basic = sta_ptr->tdls_cap.rates_len; +- if (pos[1] > 32 - basic) ++ if (ie_len > sizeof(sta_ptr->tdls_cap.rates) - basic) + return; +- for (i = 0; i < pos[1]; i++) ++ for (i = 0; i < ie_len; i++) + sta_ptr->tdls_cap.rates[basic + i] = pos[i + 2]; +- sta_ptr->tdls_cap.rates_len += pos[1]; ++ sta_ptr->tdls_cap.rates_len += ie_len; + break; + case WLAN_EID_HT_CAPABILITY: +- if (pos > end - sizeof(struct ieee80211_ht_cap) - 2) +- return; +- if (pos[1] != sizeof(struct ieee80211_ht_cap)) ++ if (ie_len != sizeof(struct ieee80211_ht_cap)) + return; + /* copy the ie's value into ht_capb*/ + memcpy((u8 *)&sta_ptr->tdls_cap.ht_capb, pos + 2, +@@ -984,59 +984,45 @@ void mwifiex_process_tdls_action_frame(s + sta_ptr->is_11n_enabled = 1; + break; + case WLAN_EID_HT_OPERATION: +- if (pos > end - +- sizeof(struct ieee80211_ht_operation) - 2) +- return; +- if (pos[1] != sizeof(struct ieee80211_ht_operation)) ++ if (ie_len != sizeof(struct ieee80211_ht_operation)) + return; + /* copy the ie's value into ht_oper*/ + memcpy(&sta_ptr->tdls_cap.ht_oper, pos + 2, + sizeof(struct ieee80211_ht_operation)); + break; + case WLAN_EID_BSS_COEX_2040: +- if (pos > end - 3) +- return; +- if (pos[1] != 1) ++ if (ie_len != sizeof(pos[2])) + return; + sta_ptr->tdls_cap.coex_2040 = pos[2]; + break; + case WLAN_EID_EXT_CAPABILITY: +- if (pos > end - sizeof(struct ieee_types_header)) +- return; +- if (pos[1] < sizeof(struct ieee_types_header)) ++ if (ie_len < sizeof(struct ieee_types_header)) + return; +- if (pos[1] > 8) ++ if (ie_len > 8) + return; + memcpy((u8 *)&sta_ptr->tdls_cap.extcap, pos, + sizeof(struct ieee_types_header) + +- min_t(u8, pos[1], 8)); ++ min_t(u8, ie_len, 8)); + break; + case WLAN_EID_RSN: +- if (pos > end - sizeof(struct ieee_types_header)) ++ if (ie_len < sizeof(struct ieee_types_header)) + return; +- if (pos[1] < sizeof(struct ieee_types_header)) +- return; +- if (pos[1] > IEEE_MAX_IE_SIZE - ++ if (ie_len > IEEE_MAX_IE_SIZE - + sizeof(struct ieee_types_header)) + return; + memcpy((u8 *)&sta_ptr->tdls_cap.rsn_ie, pos, + sizeof(struct ieee_types_header) + +- min_t(u8, pos[1], IEEE_MAX_IE_SIZE - ++ min_t(u8, ie_len, IEEE_MAX_IE_SIZE - + sizeof(struct ieee_types_header))); + break; + case WLAN_EID_QOS_CAPA: +- if (pos > end - 3) +- return; +- if (pos[1] != 1) ++ if (ie_len != sizeof(pos[2])) + return; + sta_ptr->tdls_cap.qos_info = pos[2]; + break; + case WLAN_EID_VHT_OPERATION: + if (priv->adapter->is_hw_11ac_capable) { +- if (pos > end - +- sizeof(struct ieee80211_vht_operation) - 2) +- return; +- if (pos[1] != ++ if (ie_len != + sizeof(struct ieee80211_vht_operation)) + return; + /* copy the ie's value into vhtoper*/ +@@ -1046,10 +1032,7 @@ void mwifiex_process_tdls_action_frame(s + break; + case WLAN_EID_VHT_CAPABILITY: + if (priv->adapter->is_hw_11ac_capable) { +- if (pos > end - +- sizeof(struct ieee80211_vht_cap) - 2) +- return; +- if (pos[1] != sizeof(struct ieee80211_vht_cap)) ++ if (ie_len != sizeof(struct ieee80211_vht_cap)) + return; + /* copy the ie's value into vhtcap*/ + memcpy((u8 *)&sta_ptr->tdls_cap.vhtcap, pos + 2, +@@ -1059,9 +1042,7 @@ void mwifiex_process_tdls_action_frame(s + break; + case WLAN_EID_AID: + if (priv->adapter->is_hw_11ac_capable) { +- if (pos > end - 4) +- return; +- if (pos[1] != 2) ++ if (ie_len != sizeof(u16)) + return; + sta_ptr->tdls_cap.aid = + get_unaligned_le16((pos + 2)); diff --git a/queue-4.14/namei-only-return-echild-from-follow_dotdot_rcu.patch b/queue-4.14/namei-only-return-echild-from-follow_dotdot_rcu.patch new file mode 100644 index 00000000000..a7a4a224ad9 --- /dev/null +++ b/queue-4.14/namei-only-return-echild-from-follow_dotdot_rcu.patch @@ -0,0 +1,41 @@ +From 2b98149c2377bff12be5dd3ce02ae0506e2dd613 Mon Sep 17 00:00:00 2001 +From: Aleksa Sarai +Date: Sat, 7 Dec 2019 01:13:26 +1100 +Subject: namei: only return -ECHILD from follow_dotdot_rcu() + +From: Aleksa Sarai + +commit 2b98149c2377bff12be5dd3ce02ae0506e2dd613 upstream. + +It's over-zealous to return hard errors under RCU-walk here, given that +a REF-walk will be triggered for all other cases handling ".." under +RCU. + +The original purpose of this check was to ensure that if a rename occurs +such that a directory is moved outside of the bind-mount which the +resolution started in, it would be detected and blocked to avoid being +able to mess with paths outside of the bind-mount. However, triggering a +new REF-walk is just as effective a solution. + +Cc: "Eric W. Biederman" +Fixes: 397d425dc26d ("vfs: Test for and handle paths that are unreachable from their mnt_root") +Suggested-by: Al Viro +Signed-off-by: Aleksa Sarai +Signed-off-by: Al Viro +Signed-off-by: Greg Kroah-Hartman + +--- + fs/namei.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/namei.c ++++ b/fs/namei.c +@@ -1382,7 +1382,7 @@ static int follow_dotdot_rcu(struct name + nd->path.dentry = parent; + nd->seq = seq; + if (unlikely(!path_connected(&nd->path))) +- return -ENOENT; ++ return -ECHILD; + break; + } else { + struct mount *mnt = real_mount(nd->path.mnt); diff --git a/queue-4.14/sched-fair-optimize-select_idle_cpu.patch b/queue-4.14/sched-fair-optimize-select_idle_cpu.patch new file mode 100644 index 00000000000..72f9aa8ed35 --- /dev/null +++ b/queue-4.14/sched-fair-optimize-select_idle_cpu.patch @@ -0,0 +1,62 @@ +From 60588bfa223ff675b95f866249f90616613fbe31 Mon Sep 17 00:00:00 2001 +From: Cheng Jian +Date: Fri, 13 Dec 2019 10:45:30 +0800 +Subject: sched/fair: Optimize select_idle_cpu + +From: Cheng Jian + +commit 60588bfa223ff675b95f866249f90616613fbe31 upstream. + +select_idle_cpu() will scan the LLC domain for idle CPUs, +it's always expensive. so the next commit : + + 1ad3aaf3fcd2 ("sched/core: Implement new approach to scale select_idle_cpu()") + +introduces a way to limit how many CPUs we scan. + +But it consume some CPUs out of 'nr' that are not allowed +for the task and thus waste our attempts. The function +always return nr_cpumask_bits, and we can't find a CPU +which our task is allowed to run. + +Cpumask may be too big, similar to select_idle_core(), use +per_cpu_ptr 'select_idle_mask' to prevent stack overflow. + +Fixes: 1ad3aaf3fcd2 ("sched/core: Implement new approach to scale select_idle_cpu()") +Signed-off-by: Cheng Jian +Signed-off-by: Peter Zijlstra (Intel) +Reviewed-by: Srikar Dronamraju +Reviewed-by: Vincent Guittot +Reviewed-by: Valentin Schneider +Link: https://lkml.kernel.org/r/20191213024530.28052-1-cj.chengjian@huawei.com +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/sched/fair.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +--- a/kernel/sched/fair.c ++++ b/kernel/sched/fair.c +@@ -5779,6 +5779,7 @@ static inline int select_idle_smt(struct + */ + static int select_idle_cpu(struct task_struct *p, struct sched_domain *sd, int target) + { ++ struct cpumask *cpus = this_cpu_cpumask_var_ptr(select_idle_mask); + struct sched_domain *this_sd; + u64 avg_cost, avg_idle; + u64 time, cost; +@@ -5809,11 +5810,11 @@ static int select_idle_cpu(struct task_s + + time = local_clock(); + +- for_each_cpu_wrap(cpu, sched_domain_span(sd), target) { ++ cpumask_and(cpus, sched_domain_span(sd), p->cpus_ptr); ++ ++ for_each_cpu_wrap(cpu, cpus, target) { + if (!--nr) + return -1; +- if (!cpumask_test_cpu(cpu, &p->cpus_allowed)) +- continue; + if (idle_cpu(cpu)) + break; + } diff --git a/queue-4.14/series b/queue-4.14/series index e33d25a5fef..54d18a73296 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -54,3 +54,8 @@ include-linux-bitops.h-introduce-bits_per_type.patch net-netlink-cap-max-groups-which-will-be-considered-in-netlink_bind.patch net-atlantic-fix-potential-error-handling.patch net-ena-make-ena-rxfh-support-eth_rss_hash_no_change.patch +namei-only-return-echild-from-follow_dotdot_rcu.patch +mwifiex-drop-most-magic-numbers-from-mwifiex_process_tdls_action_frame.patch +kvm-svm-override-default-mmio-mask-if-memory-encryption-is-enabled.patch +kvm-check-for-a-bad-hva-before-dropping-into-the-ghc-slow-path.patch +sched-fair-optimize-select_idle_cpu.patch