From d7f0c61e8214424ab77726611ca4f94aa745d730 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 22 Jan 2024 10:53:10 -0800 Subject: [PATCH] 4.19-stable patches added patches: usb-mon-fix-atomicity-violation-in-mon_bin_vma_fault.patch --- queue-4.19/series | 1 + ...icity-violation-in-mon_bin_vma_fault.patch | 90 +++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 queue-4.19/usb-mon-fix-atomicity-violation-in-mon_bin_vma_fault.patch diff --git a/queue-4.19/series b/queue-4.19/series index 168afbdcc84..53e30411784 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -123,3 +123,4 @@ revert-usb-dwc3-don-t-reset-device-side-if-dwc3-was-configured-as-host-only.patc usb-chipidea-wait-controller-resume-finished-for-wakeup-irq.patch revert-usb-typec-class-fix-typec_altmode_put_partner-to-put-plugs.patch usb-typec-class-fix-typec_altmode_put_partner-to-put-plugs.patch +usb-mon-fix-atomicity-violation-in-mon_bin_vma_fault.patch diff --git a/queue-4.19/usb-mon-fix-atomicity-violation-in-mon_bin_vma_fault.patch b/queue-4.19/usb-mon-fix-atomicity-violation-in-mon_bin_vma_fault.patch new file mode 100644 index 00000000000..27ba6a6cdb9 --- /dev/null +++ b/queue-4.19/usb-mon-fix-atomicity-violation-in-mon_bin_vma_fault.patch @@ -0,0 +1,90 @@ +From 2dd23cc4d0e6aa55cf9fb3b05f2f4165b01de81c Mon Sep 17 00:00:00 2001 +From: Gui-Dong Han <2045gemini@gmail.com> +Date: Fri, 5 Jan 2024 13:24:12 +0800 +Subject: usb: mon: Fix atomicity violation in mon_bin_vma_fault + +From: Gui-Dong Han <2045gemini@gmail.com> + +commit 2dd23cc4d0e6aa55cf9fb3b05f2f4165b01de81c upstream. + +In mon_bin_vma_fault(): + offset = vmf->pgoff << PAGE_SHIFT; + if (offset >= rp->b_size) + return VM_FAULT_SIGBUS; + chunk_idx = offset / CHUNK_SIZE; + pageptr = rp->b_vec[chunk_idx].pg; +The code is executed without holding any lock. + +In mon_bin_vma_close(): + spin_lock_irqsave(&rp->b_lock, flags); + rp->mmap_active--; + spin_unlock_irqrestore(&rp->b_lock, flags); + +In mon_bin_ioctl(): + spin_lock_irqsave(&rp->b_lock, flags); + if (rp->mmap_active) { + ... + } else { + ... + kfree(rp->b_vec); + rp->b_vec = vec; + rp->b_size = size; + ... + } + spin_unlock_irqrestore(&rp->b_lock, flags); + +Concurrent execution of mon_bin_vma_fault() with mon_bin_vma_close() and +mon_bin_ioctl() could lead to atomicity violations. mon_bin_vma_fault() +accesses rp->b_size and rp->b_vec without locking, risking array +out-of-bounds access or use-after-free bugs due to possible modifications +in mon_bin_ioctl(). + +This possible bug is found by an experimental static analysis tool +developed by our team, BassCheck[1]. This tool analyzes the locking APIs +to extract function pairs that can be concurrently executed, and then +analyzes the instructions in the paired functions to identify possible +concurrency bugs including data races and atomicity violations. The above +possible bug is reported when our tool analyzes the source code of +Linux 6.2. + +To address this issue, it is proposed to add a spin lock pair in +mon_bin_vma_fault() to ensure atomicity. With this patch applied, our tool +never reports the possible bug, with the kernel configuration allyesconfig +for x86_64. Due to the lack of associated hardware, we cannot test the +patch in runtime testing, and just verify it according to the code logic. + +[1] https://sites.google.com/view/basscheck/ + +Fixes: 19e6317d24c2 ("usb: mon: Fix a deadlock in usbmon between ...") +Cc: +Signed-off-by: Gui-Dong Han <2045gemini@gmail.com> +Link: https://lore.kernel.org/r/20240105052412.9377-1-2045gemini@gmail.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/mon/mon_bin.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +--- a/drivers/usb/mon/mon_bin.c ++++ b/drivers/usb/mon/mon_bin.c +@@ -1247,14 +1247,19 @@ static vm_fault_t mon_bin_vma_fault(stru + struct mon_reader_bin *rp = vmf->vma->vm_private_data; + unsigned long offset, chunk_idx; + struct page *pageptr; ++ unsigned long flags; + ++ spin_lock_irqsave(&rp->b_lock, flags); + offset = vmf->pgoff << PAGE_SHIFT; +- if (offset >= rp->b_size) ++ if (offset >= rp->b_size) { ++ spin_unlock_irqrestore(&rp->b_lock, flags); + return VM_FAULT_SIGBUS; ++ } + chunk_idx = offset / CHUNK_SIZE; + pageptr = rp->b_vec[chunk_idx].pg; + get_page(pageptr); + vmf->page = pageptr; ++ spin_unlock_irqrestore(&rp->b_lock, flags); + return 0; + } + -- 2.47.3