]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 4.19
authorSasha Levin <sashal@kernel.org>
Thu, 12 Aug 2021 11:51:33 +0000 (07:51 -0400)
committerSasha Levin <sashal@kernel.org>
Thu, 12 Aug 2021 11:51:33 +0000 (07:51 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-4.19/kvm-svm-fix-off-by-one-indexing-when-nullifying-last.patch [new file with mode: 0644]
queue-4.19/series [new file with mode: 0644]
queue-4.19/usb-dwc3-gadget-use-list_replace_init-before-travers.patch [new file with mode: 0644]

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 (file)
index 0000000..ef3a28a
--- /dev/null
@@ -0,0 +1,52 @@
+From f5846898f43eccab6105564928f910a3594c93f5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <seanjc@google.com>
+
+[ 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 <thomas.lendacky@amd.com>
+Cc: Brijesh Singh <brijesh.singh@amd.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..3bf2f66
--- /dev/null
@@ -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 (file)
index 0000000..05d3106
--- /dev/null
@@ -0,0 +1,117 @@
+From 9c65ea2597a5fec2e57551b71c2a70e034a435d6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 29 Jul 2021 00:33:14 -0700
+Subject: usb: dwc3: gadget: Use list_replace_init() before traversing lists
+
+From: Wesley Cheng <wcheng@codeaurora.org>
+
+[ 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 <stable@vger.kernel.org>
+Acked-by: Felipe Balbi <balbi@kernel.org>
+Signed-off-by: Wesley Cheng <wcheng@codeaurora.org>
+Link: https://lore.kernel.org/r/1627543994-20327-1-git-send-email-wcheng@codeaurora.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+