]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 5.10
authorSasha Levin <sashal@kernel.org>
Thu, 12 Aug 2021 11:51:32 +0000 (07:51 -0400)
committerSasha Levin <sashal@kernel.org>
Thu, 12 Aug 2021 11:51:32 +0000 (07:51 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-5.10/firmware-tee_bnxt-release-tee-shm-session-and-contex.patch [new file with mode: 0644]
queue-5.10/kvm-svm-fix-off-by-one-indexing-when-nullifying-last.patch [new file with mode: 0644]
queue-5.10/series [new file with mode: 0644]
queue-5.10/tee-correct-inappropriate-usage-of-tee_shm_dma_buf-f.patch [new file with mode: 0644]
queue-5.10/usb-dwc3-gadget-use-list_replace_init-before-travers.patch [new file with mode: 0644]

diff --git a/queue-5.10/firmware-tee_bnxt-release-tee-shm-session-and-contex.patch b/queue-5.10/firmware-tee_bnxt-release-tee-shm-session-and-contex.patch
new file mode 100644 (file)
index 0000000..c9c458a
--- /dev/null
@@ -0,0 +1,85 @@
+From 5114754396a891105fa2fda1111831d71466eb6e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 14 Jun 2021 17:33:17 -0500
+Subject: firmware: tee_bnxt: Release TEE shm, session, and context during
+ kexec
+
+From: Allen Pais <apais@linux.microsoft.com>
+
+[ Upstream commit 914ab19e471d8fb535ed50dff108b0a615f3c2d8 ]
+
+Implement a .shutdown hook that will be called during a kexec operation
+so that the TEE shared memory, session, and context that were set up
+during .probe can be properly freed/closed.
+
+Additionally, don't use dma-buf backed shared memory for the
+fw_shm_pool. dma-buf backed shared memory cannot be reliably freed and
+unregistered during a kexec operation even when tee_shm_free() is called
+on the shm from a .shutdown hook. The problem occurs because
+dma_buf_put() calls fput() which then uses task_work_add(), with the
+TWA_RESUME parameter, to queue tee_shm_release() to be called before the
+current task returns to user mode. However, the current task never
+returns to user mode before the kexec completes so the memory is never
+freed nor unregistered.
+
+Use tee_shm_alloc_kernel_buf() to avoid dma-buf backed shared memory
+allocation so that tee_shm_free() can directly call tee_shm_release().
+This will ensure that the shm can be freed and unregistered during a
+kexec operation.
+
+Fixes: 246880958ac9 ("firmware: broadcom: add OP-TEE based BNXT f/w manager")
+Cc: stable@vger.kernel.org
+Signed-off-by: Allen Pais <apais@linux.microsoft.com>
+Co-developed-by: Tyler Hicks <tyhicks@linux.microsoft.com>
+Signed-off-by: Tyler Hicks <tyhicks@linux.microsoft.com>
+Reviewed-by: Sumit Garg <sumit.garg@linaro.org>
+Acked-by: Florian Fainelli <f.fainelli@gmail.com>
+Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/firmware/broadcom/tee_bnxt_fw.c | 14 +++++++++++---
+ 1 file changed, 11 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/firmware/broadcom/tee_bnxt_fw.c b/drivers/firmware/broadcom/tee_bnxt_fw.c
+index ed10da5313e8..a5bf4c3f6dc7 100644
+--- a/drivers/firmware/broadcom/tee_bnxt_fw.c
++++ b/drivers/firmware/broadcom/tee_bnxt_fw.c
+@@ -212,10 +212,9 @@ static int tee_bnxt_fw_probe(struct device *dev)
+       pvt_data.dev = dev;
+-      fw_shm_pool = tee_shm_alloc(pvt_data.ctx, MAX_SHM_MEM_SZ,
+-                                  TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
++      fw_shm_pool = tee_shm_alloc_kernel_buf(pvt_data.ctx, MAX_SHM_MEM_SZ);
+       if (IS_ERR(fw_shm_pool)) {
+-              dev_err(pvt_data.dev, "tee_shm_alloc failed\n");
++              dev_err(pvt_data.dev, "tee_shm_alloc_kernel_buf failed\n");
+               err = PTR_ERR(fw_shm_pool);
+               goto out_sess;
+       }
+@@ -242,6 +241,14 @@ static int tee_bnxt_fw_remove(struct device *dev)
+       return 0;
+ }
++static void tee_bnxt_fw_shutdown(struct device *dev)
++{
++      tee_shm_free(pvt_data.fw_shm_pool);
++      tee_client_close_session(pvt_data.ctx, pvt_data.session_id);
++      tee_client_close_context(pvt_data.ctx);
++      pvt_data.ctx = NULL;
++}
++
+ static const struct tee_client_device_id tee_bnxt_fw_id_table[] = {
+       {UUID_INIT(0x6272636D, 0x2019, 0x0716,
+                   0x42, 0x43, 0x4D, 0x5F, 0x53, 0x43, 0x48, 0x49)},
+@@ -257,6 +264,7 @@ static struct tee_client_driver tee_bnxt_fw_driver = {
+               .bus            = &tee_bus_type,
+               .probe          = tee_bnxt_fw_probe,
+               .remove         = tee_bnxt_fw_remove,
++              .shutdown       = tee_bnxt_fw_shutdown,
+       },
+ };
+-- 
+2.30.2
+
diff --git a/queue-5.10/kvm-svm-fix-off-by-one-indexing-when-nullifying-last.patch b/queue-5.10/kvm-svm-fix-off-by-one-indexing-when-nullifying-last.patch
new file mode 100644 (file)
index 0000000..8127e7d
--- /dev/null
@@ -0,0 +1,52 @@
+From 6a82a6669f0eb4635d3128baa4ce3004c2f34aa3 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/sev.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
+index 01547bdbfb06..6c82ef22985d 100644
+--- a/arch/x86/kvm/svm/sev.c
++++ b/arch/x86/kvm/svm/sev.c
+@@ -124,7 +124,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;
+       }
+       mutex_unlock(&sev_bitmap_lock);
+-- 
+2.30.2
+
diff --git a/queue-5.10/series b/queue-5.10/series
new file mode 100644 (file)
index 0000000..f8481c7
--- /dev/null
@@ -0,0 +1,4 @@
+kvm-svm-fix-off-by-one-indexing-when-nullifying-last.patch
+tee-correct-inappropriate-usage-of-tee_shm_dma_buf-f.patch
+usb-dwc3-gadget-use-list_replace_init-before-travers.patch
+firmware-tee_bnxt-release-tee-shm-session-and-contex.patch
diff --git a/queue-5.10/tee-correct-inappropriate-usage-of-tee_shm_dma_buf-f.patch b/queue-5.10/tee-correct-inappropriate-usage-of-tee_shm_dma_buf-f.patch
new file mode 100644 (file)
index 0000000..5b26cff
--- /dev/null
@@ -0,0 +1,148 @@
+From 4ffd7c162578c7f17231f5522bd3d537497dad20 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 14 Jun 2021 17:33:15 -0500
+Subject: tee: Correct inappropriate usage of TEE_SHM_DMA_BUF flag
+
+From: Sumit Garg <sumit.garg@linaro.org>
+
+[ Upstream commit 376e4199e327a5cf29b8ec8fb0f64f3d8b429819 ]
+
+Currently TEE_SHM_DMA_BUF flag has been inappropriately used to not
+register shared memory allocated for private usage by underlying TEE
+driver: OP-TEE in this case. So rather add a new flag as TEE_SHM_PRIV
+that can be utilized by underlying TEE drivers for private allocation
+and usage of shared memory.
+
+With this corrected, allow tee_shm_alloc_kernel_buf() to allocate a
+shared memory region without the backing of dma-buf.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Sumit Garg <sumit.garg@linaro.org>
+Co-developed-by: Tyler Hicks <tyhicks@linux.microsoft.com>
+Signed-off-by: Tyler Hicks <tyhicks@linux.microsoft.com>
+Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org>
+Reviewed-by: Sumit Garg <sumit.garg@linaro.org>
+Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tee/optee/call.c     | 2 +-
+ drivers/tee/optee/core.c     | 3 ++-
+ drivers/tee/optee/rpc.c      | 5 +++--
+ drivers/tee/optee/shm_pool.c | 8 ++++++--
+ drivers/tee/tee_shm.c        | 4 ++--
+ include/linux/tee_drv.h      | 1 +
+ 6 files changed, 15 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c
+index 1231ce56e712..f8f1594bea43 100644
+--- a/drivers/tee/optee/call.c
++++ b/drivers/tee/optee/call.c
+@@ -181,7 +181,7 @@ static struct tee_shm *get_msg_arg(struct tee_context *ctx, size_t num_params,
+       struct optee_msg_arg *ma;
+       shm = tee_shm_alloc(ctx, OPTEE_MSG_GET_ARG_SIZE(num_params),
+-                          TEE_SHM_MAPPED);
++                          TEE_SHM_MAPPED | TEE_SHM_PRIV);
+       if (IS_ERR(shm))
+               return shm;
+diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
+index 7b17248f1527..823a81d8ff0e 100644
+--- a/drivers/tee/optee/core.c
++++ b/drivers/tee/optee/core.c
+@@ -278,7 +278,8 @@ static void optee_release(struct tee_context *ctx)
+       if (!ctxdata)
+               return;
+-      shm = tee_shm_alloc(ctx, sizeof(struct optee_msg_arg), TEE_SHM_MAPPED);
++      shm = tee_shm_alloc(ctx, sizeof(struct optee_msg_arg),
++                          TEE_SHM_MAPPED | TEE_SHM_PRIV);
+       if (!IS_ERR(shm)) {
+               arg = tee_shm_get_va(shm, 0);
+               /*
+diff --git a/drivers/tee/optee/rpc.c b/drivers/tee/optee/rpc.c
+index 6cbb3643c6c4..9dbdd783d6f2 100644
+--- a/drivers/tee/optee/rpc.c
++++ b/drivers/tee/optee/rpc.c
+@@ -313,7 +313,7 @@ static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
+               shm = cmd_alloc_suppl(ctx, sz);
+               break;
+       case OPTEE_MSG_RPC_SHM_TYPE_KERNEL:
+-              shm = tee_shm_alloc(ctx, sz, TEE_SHM_MAPPED);
++              shm = tee_shm_alloc(ctx, sz, TEE_SHM_MAPPED | TEE_SHM_PRIV);
+               break;
+       default:
+               arg->ret = TEEC_ERROR_BAD_PARAMETERS;
+@@ -501,7 +501,8 @@ void optee_handle_rpc(struct tee_context *ctx, struct optee_rpc_param *param,
+       switch (OPTEE_SMC_RETURN_GET_RPC_FUNC(param->a0)) {
+       case OPTEE_SMC_RPC_FUNC_ALLOC:
+-              shm = tee_shm_alloc(ctx, param->a1, TEE_SHM_MAPPED);
++              shm = tee_shm_alloc(ctx, param->a1,
++                                  TEE_SHM_MAPPED | TEE_SHM_PRIV);
+               if (!IS_ERR(shm) && !tee_shm_get_pa(shm, 0, &pa)) {
+                       reg_pair_from_64(&param->a1, &param->a2, pa);
+                       reg_pair_from_64(&param->a4, &param->a5,
+diff --git a/drivers/tee/optee/shm_pool.c b/drivers/tee/optee/shm_pool.c
+index da06ce9b9313..c41a9a501a6e 100644
+--- a/drivers/tee/optee/shm_pool.c
++++ b/drivers/tee/optee/shm_pool.c
+@@ -27,7 +27,11 @@ static int pool_op_alloc(struct tee_shm_pool_mgr *poolm,
+       shm->paddr = page_to_phys(page);
+       shm->size = PAGE_SIZE << order;
+-      if (shm->flags & TEE_SHM_DMA_BUF) {
++      /*
++       * Shared memory private to the OP-TEE driver doesn't need
++       * to be registered with OP-TEE.
++       */
++      if (!(shm->flags & TEE_SHM_PRIV)) {
+               unsigned int nr_pages = 1 << order, i;
+               struct page **pages;
+@@ -60,7 +64,7 @@ err:
+ static void pool_op_free(struct tee_shm_pool_mgr *poolm,
+                        struct tee_shm *shm)
+ {
+-      if (shm->flags & TEE_SHM_DMA_BUF)
++      if (!(shm->flags & TEE_SHM_PRIV))
+               optee_shm_unregister(shm->ctx, shm);
+       free_pages((unsigned long)shm->kaddr, get_order(shm->size));
+diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c
+index c65e44707cd6..8a9384a64f3e 100644
+--- a/drivers/tee/tee_shm.c
++++ b/drivers/tee/tee_shm.c
+@@ -117,7 +117,7 @@ struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags)
+               return ERR_PTR(-EINVAL);
+       }
+-      if ((flags & ~(TEE_SHM_MAPPED | TEE_SHM_DMA_BUF))) {
++      if ((flags & ~(TEE_SHM_MAPPED | TEE_SHM_DMA_BUF | TEE_SHM_PRIV))) {
+               dev_err(teedev->dev.parent, "invalid shm flags 0x%x", flags);
+               return ERR_PTR(-EINVAL);
+       }
+@@ -207,7 +207,7 @@ EXPORT_SYMBOL_GPL(tee_shm_alloc);
+  */
+ struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size)
+ {
+-      return tee_shm_alloc(ctx, size, TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
++      return tee_shm_alloc(ctx, size, TEE_SHM_MAPPED);
+ }
+ EXPORT_SYMBOL_GPL(tee_shm_alloc_kernel_buf);
+diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h
+index 9b24cc3d3024..459e9a76d7e6 100644
+--- a/include/linux/tee_drv.h
++++ b/include/linux/tee_drv.h
+@@ -27,6 +27,7 @@
+ #define TEE_SHM_USER_MAPPED   BIT(4)  /* Memory mapped in user space */
+ #define TEE_SHM_POOL          BIT(5)  /* Memory allocated from pool */
+ #define TEE_SHM_KERNEL_MAPPED BIT(6)  /* Memory mapped in kernel space */
++#define TEE_SHM_PRIV          BIT(7)  /* Memory private to TEE driver */
+ struct device;
+ struct tee_device;
+-- 
+2.30.2
+
diff --git a/queue-5.10/usb-dwc3-gadget-use-list_replace_init-before-travers.patch b/queue-5.10/usb-dwc3-gadget-use-list_replace_init-before-travers.patch
new file mode 100644 (file)
index 0000000..b5bcbf4
--- /dev/null
@@ -0,0 +1,117 @@
+From c73f9064fdd78a34de47d939739b92cc54257c7c 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 756839e0e91d..788bbb38cf79 100644
+--- a/drivers/usb/dwc3/gadget.c
++++ b/drivers/usb/dwc3/gadget.c
+@@ -1733,11 +1733,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,
+@@ -2867,8 +2874,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,
+@@ -2876,6 +2887,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
+