From: Sasha Levin Date: Thu, 12 Aug 2021 11:51:33 +0000 (-0400) Subject: Fixes for 4.19 X-Git-Tag: v4.4.281~20 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=1f346f2191fc0315a469a76cf8c7e545cb0fa1eb;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 4.19 Signed-off-by: Sasha Levin --- diff --git a/queue-4.19/kvm-svm-fix-off-by-one-indexing-when-nullifying-last.patch b/queue-4.19/kvm-svm-fix-off-by-one-indexing-when-nullifying-last.patch new file mode 100644 index 00000000000..ef3a28a4384 --- /dev/null +++ b/queue-4.19/kvm-svm-fix-off-by-one-indexing-when-nullifying-last.patch @@ -0,0 +1,52 @@ +From f5846898f43eccab6105564928f910a3594c93f5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 3 Aug 2021 09:27:46 -0700 +Subject: KVM: SVM: Fix off-by-one indexing when nullifying last used SEV VMCB + +From: Sean Christopherson + +[ Upstream commit 179c6c27bf487273652efc99acd3ba512a23c137 ] + +Use the raw ASID, not ASID-1, when nullifying the last used VMCB when +freeing an SEV ASID. The consumer, pre_sev_run(), indexes the array by +the raw ASID, thus KVM could get a false negative when checking for a +different VMCB if KVM manages to reallocate the same ASID+VMCB combo for +a new VM. + +Note, this cannot cause a functional issue _in the current code_, as +pre_sev_run() also checks which pCPU last did VMRUN for the vCPU, and +last_vmentry_cpu is initialized to -1 during vCPU creation, i.e. is +guaranteed to mismatch on the first VMRUN. However, prior to commit +8a14fe4f0c54 ("kvm: x86: Move last_cpu into kvm_vcpu_arch as +last_vmentry_cpu"), SVM tracked pCPU on its own and zero-initialized the +last_cpu variable. Thus it's theoretically possible that older versions +of KVM could miss a TLB flush if the first VMRUN is on pCPU0 and the ASID +and VMCB exactly match those of a prior VM. + +Fixes: 70cd94e60c73 ("KVM: SVM: VMRUN should use associated ASID when SEV is enabled") +Cc: Tom Lendacky +Cc: Brijesh Singh +Cc: stable@vger.kernel.org +Signed-off-by: Sean Christopherson +Signed-off-by: Paolo Bonzini +Signed-off-by: Sasha Levin +--- + arch/x86/kvm/svm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c +index bd463d684237..72d729f34437 100644 +--- a/arch/x86/kvm/svm.c ++++ b/arch/x86/kvm/svm.c +@@ -1780,7 +1780,7 @@ static void __sev_asid_free(int asid) + + for_each_possible_cpu(cpu) { + sd = per_cpu(svm_data, cpu); +- sd->sev_vmcbs[pos] = NULL; ++ sd->sev_vmcbs[asid] = NULL; + } + } + +-- +2.30.2 + diff --git a/queue-4.19/series b/queue-4.19/series new file mode 100644 index 00000000000..3bf2f669090 --- /dev/null +++ b/queue-4.19/series @@ -0,0 +1,2 @@ +kvm-svm-fix-off-by-one-indexing-when-nullifying-last.patch +usb-dwc3-gadget-use-list_replace_init-before-travers.patch diff --git a/queue-4.19/usb-dwc3-gadget-use-list_replace_init-before-travers.patch b/queue-4.19/usb-dwc3-gadget-use-list_replace_init-before-travers.patch new file mode 100644 index 00000000000..05d3106c336 --- /dev/null +++ b/queue-4.19/usb-dwc3-gadget-use-list_replace_init-before-travers.patch @@ -0,0 +1,117 @@ +From 9c65ea2597a5fec2e57551b71c2a70e034a435d6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Jul 2021 00:33:14 -0700 +Subject: usb: dwc3: gadget: Use list_replace_init() before traversing lists + +From: Wesley Cheng + +[ Upstream commit d25d85061bd856d6be221626605319154f9b5043 ] + +The list_for_each_entry_safe() macro saves the current item (n) and +the item after (n+1), so that n can be safely removed without +corrupting the list. However, when traversing the list and removing +items using gadget giveback, the DWC3 lock is briefly released, +allowing other routines to execute. There is a situation where, while +items are being removed from the cancelled_list using +dwc3_gadget_ep_cleanup_cancelled_requests(), the pullup disable +routine is running in parallel (due to UDC unbind). As the cleanup +routine removes n, and the pullup disable removes n+1, once the +cleanup retakes the DWC3 lock, it references a request who was already +removed/handled. With list debug enabled, this leads to a panic. +Ensure all instances of the macro are replaced where gadget giveback +is used. + +Example call stack: + +Thread#1: +__dwc3_gadget_ep_set_halt() - CLEAR HALT + -> dwc3_gadget_ep_cleanup_cancelled_requests() + ->list_for_each_entry_safe() + ->dwc3_gadget_giveback(n) + ->dwc3_gadget_del_and_unmap_request()- n deleted[cancelled_list] + ->spin_unlock + ->Thread#2 executes + ... + ->dwc3_gadget_giveback(n+1) + ->Already removed! + +Thread#2: +dwc3_gadget_pullup() + ->waiting for dwc3 spin_lock + ... + ->Thread#1 released lock + ->dwc3_stop_active_transfers() + ->dwc3_remove_requests() + ->fetches n+1 item from cancelled_list (n removed by Thread#1) + ->dwc3_gadget_giveback() + ->dwc3_gadget_del_and_unmap_request()- n+1 +deleted[cancelled_list] + ->spin_unlock + +Fix this condition by utilizing list_replace_init(), and traversing +through a local copy of the current elements in the endpoint lists. +This will also set the parent list as empty, so if another thread is +also looping through the list, it will be empty on the next iteration. + +Fixes: d4f1afe5e896 ("usb: dwc3: gadget: move requests to cancelled_list") +Cc: stable +Acked-by: Felipe Balbi +Signed-off-by: Wesley Cheng +Link: https://lore.kernel.org/r/1627543994-20327-1-git-send-email-wcheng@codeaurora.org +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/dwc3/gadget.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c +index c93bed41d988..e6e3095303b1 100644 +--- a/drivers/usb/dwc3/gadget.c ++++ b/drivers/usb/dwc3/gadget.c +@@ -1466,11 +1466,18 @@ static void dwc3_gadget_ep_cleanup_cancelled_requests(struct dwc3_ep *dep) + { + struct dwc3_request *req; + struct dwc3_request *tmp; ++ struct list_head local; + +- list_for_each_entry_safe(req, tmp, &dep->cancelled_list, list) { ++restart: ++ list_replace_init(&dep->cancelled_list, &local); ++ ++ list_for_each_entry_safe(req, tmp, &local, list) { + dwc3_gadget_ep_skip_trbs(dep, req); + dwc3_gadget_giveback(dep, req, -ECONNRESET); + } ++ ++ if (!list_empty(&dep->cancelled_list)) ++ goto restart; + } + + static int dwc3_gadget_ep_dequeue(struct usb_ep *ep, +@@ -2443,8 +2450,12 @@ static void dwc3_gadget_ep_cleanup_completed_requests(struct dwc3_ep *dep, + { + struct dwc3_request *req; + struct dwc3_request *tmp; ++ struct list_head local; + +- list_for_each_entry_safe(req, tmp, &dep->started_list, list) { ++restart: ++ list_replace_init(&dep->started_list, &local); ++ ++ list_for_each_entry_safe(req, tmp, &local, list) { + int ret; + + ret = dwc3_gadget_ep_cleanup_completed_request(dep, event, +@@ -2452,6 +2463,9 @@ static void dwc3_gadget_ep_cleanup_completed_requests(struct dwc3_ep *dep, + if (ret) + break; + } ++ ++ if (!list_empty(&dep->started_list)) ++ goto restart; + } + + static bool dwc3_gadget_ep_should_continue(struct dwc3_ep *dep) +-- +2.30.2 +