* [PATCH v2 0/2] scsi: leapraid: fix firmware log mmap lifetime @ 2026-08-13 7:26 Linmao Li 2026-08-13 7:26 ` [PATCH v2 1/2] scsi: leapraid: balance host references for firmware log VMAs Linmao Li 2026-08-13 7:26 ` [PATCH v2 2/2] scsi: leapraid: serialize firmware log mmap with teardown Linmao Li 0 siblings, 2 replies; 5+ messages in thread From: Linmao Li @ 2026-08-13 7:26 UTC (permalink / raw) To: doubled, James.Bottomley, martin.petersen, linux-scsi Cc: hare, dlemoal, linux-kernel, Linmao Li The firmware log mmap path has two related lifetime issues. VMA clones drop Scsi_Host references that they never acquired, and device removal can free the coherent log buffer while mmap is still setting up a VMA. Patch 1 gives each VMA its own host device reference. Patch 2 claims a temporary mmap activity reference under the adapter-list lock so teardown cannot miss an in-progress mapping. Patch 2 depends on patch 1: patch 1 keeps adapter non-NULL on the successful mmap path, allowing patch 2 to drop the temporary mmap reference at out_put. Applied alone, patch 2 would leak that reference and make teardown wait indefinitely. Neither patch has been tested on hardware; both are derived from the reference counting and locking in the code. Changes in v2: - 2/2: keep the return type and function name of leapraid_ctl_lookup_adapter() on one line, the declaration fits in the line-length limit (Dongdong Hao) - 1/2: unchanged v1: https://lore.kernel.org/all/20260811112001.1158587-1-lilinmao@kylinos.cn/ Linmao Li (2): scsi: leapraid: balance host references for firmware log VMAs scsi: leapraid: serialize firmware log mmap with teardown drivers/scsi/leapraid/leapraid_app.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) base-commit: 376a3960e5efe85ff765abfb5b5b7e4655ad6aed -- 2.25.1 ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v2 1/2] scsi: leapraid: balance host references for firmware log VMAs 2026-08-13 7:26 [PATCH v2 0/2] scsi: leapraid: fix firmware log mmap lifetime Linmao Li @ 2026-08-13 7:26 ` Linmao Li 2026-08-13 7:39 ` sashiko-bot 2026-08-13 7:26 ` [PATCH v2 2/2] scsi: leapraid: serialize firmware log mmap with teardown Linmao Li 1 sibling, 1 reply; 5+ messages in thread From: Linmao Li @ 2026-08-13 7:26 UTC (permalink / raw) To: doubled, James.Bottomley, martin.petersen, linux-scsi Cc: hare, dlemoal, linux-kernel, Linmao Li leapraid_fw_mmap() keeps the Scsi_Host reference obtained while looking up the adapter for the lifetime of the initial VMA. The VMA close callback drops that reference. The open callback is also invoked when a VMA is duplicated or split, but it only increments mmap_refcnt. Since every corresponding close callback drops a host reference, cloning the mapping can release the host while another VMA still refers to the adapter. Take a host device reference for every VMA open and release the lookup reference once the initial mapping has acquired its own reference. Use get_device() because a VMA can be cloned after the host enters SHOST_DEL; an existing VMA still pins the host at that point and open cannot fail. Fixes: 5597088c9e79 ("scsi: leapraid: Add new SCSI driver") Signed-off-by: Linmao Li <lilinmao@kylinos.cn> --- drivers/scsi/leapraid/leapraid_app.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/leapraid/leapraid_app.c b/drivers/scsi/leapraid/leapraid_app.c index 742f19c07fcbb..841027ce2501c 100644 --- a/drivers/scsi/leapraid/leapraid_app.c +++ b/drivers/scsi/leapraid/leapraid_app.c @@ -697,6 +697,7 @@ static void leapraid_fw_mmap_open(struct vm_area_struct *vma) if (!adapter) return; + get_device(&adapter->shost->shost_gendev); atomic_inc(&adapter->fw_log_desc.mmap_refcnt); } @@ -767,7 +768,6 @@ static int leapraid_fw_mmap(struct file *filp, struct vm_area_struct *vma) vma->vm_private_data = adapter; vma->vm_ops = &leapraid_fw_mmap_vm_ops; leapraid_fw_mmap_open(vma); - adapter = NULL; rc = 0; out_put: -- 2.25.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v2 1/2] scsi: leapraid: balance host references for firmware log VMAs 2026-08-13 7:26 ` [PATCH v2 1/2] scsi: leapraid: balance host references for firmware log VMAs Linmao Li @ 2026-08-13 7:39 ` sashiko-bot 0 siblings, 0 replies; 5+ messages in thread From: sashiko-bot @ 2026-08-13 7:39 UTC (permalink / raw) To: Linmao Li; +Cc: linux-scsi Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: Pre-existing issues: - [High] Unkillable sleep in device removal path if userspace keeps the memory mapped. - [High] TOCTOU race in leapraid_fw_mmap allowing use-after-free of fw_log_buffer. -- --- Patch [1]: [PATCH v2 1/2] scsi: leapraid: balance host references for firmware log VMAs --- commit f0e08e76b84e5bcaddf6147e197d89f0cec2a4e9 Author: Linmao Li <lilinmao@kylinos.cn> scsi: leapraid: balance host references for firmware log VMAs leapraid_fw_mmap() keeps the Scsi_Host reference obtained while looking up the adapter for the lifetime of the initial VMA. The VMA close callback drops that reference. The open callback is also invoked when a VMA is duplicated or split, but it only increments mmap_refcnt. Since every corresponding close callback drops a host reference, cloning the mapping can release the host while another VMA still refers to the adapter. Take a host device reference for every VMA open and release the lookup reference once the initial mapping has acquired its own reference. Use get_device() because a VMA can be cloned after the host enters SHOST_DEL; an existing VMA still pins the host at that point and open cannot fail. > diff --git a/drivers/scsi/leapraid/leapraid_app.c b/drivers/scsi/leapraid/leapraid_app.c > index 742f19c07fcbb..841027ce2501c 100644 > --- a/drivers/scsi/leapraid/leapraid_app.c > +++ b/drivers/scsi/leapraid/leapraid_app.c > @@ -697,6 +697,7 @@ static void leapraid_fw_mmap_open(struct vm_area_struct *vma) > if (!adapter) > return; > > + get_device(&adapter->shost->shost_gendev); > atomic_inc(&adapter->fw_log_desc.mmap_refcnt); [Severity: High] This is a pre-existing issue, but does this create an unkillable sleep in the device removal path? If a user maps the firmware log buffer via mmap and never unmaps it, the removal thread executing leapraid_fw_log_exit() in leapraid_func.c will block indefinitely waiting for the reference count to drop to zero: wait_event(adapter->fw_log_desc.mmap_waitq, !atomic_read(&adapter->fw_log_desc.mmap_refcnt)); Since there is no mechanism to forcibly revoke the mapping, could this allow userspace to block device removal indefinitely? > } > > @@ -767,7 +768,6 @@ static int leapraid_fw_mmap(struct file *filp, struct vm_area_struct *vma) > vma->vm_private_data = adapter; > vma->vm_ops = &leapraid_fw_mmap_vm_ops; > leapraid_fw_mmap_open(vma); [Severity: High] This isn't a bug introduced by this patch, but is there a race condition here that allows a use-after-free of the firmware log buffer? The buffer is mapped to user space via dma_mmap_coherent() earlier in this function before mmap_refcnt is incremented here in leapraid_fw_mmap_open(). If a concurrent device removal preempts this thread right before leapraid_fw_mmap_open() is called, leapraid_fw_log_exit() will see mmap_refcnt == 0 and free the buffer via dma_free_coherent(). When the mmap thread resumes, will it have successfully mapped freed kernel DMA memory into user space? > - adapter = NULL; > > rc = 0; > out_put: -- Sashiko AI review · https://sashiko.dev/#/patchset/20260813072614.1387555-1-lilinmao@kylinos.cn?part=1 ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v2 2/2] scsi: leapraid: serialize firmware log mmap with teardown 2026-08-13 7:26 [PATCH v2 0/2] scsi: leapraid: fix firmware log mmap lifetime Linmao Li 2026-08-13 7:26 ` [PATCH v2 1/2] scsi: leapraid: balance host references for firmware log VMAs Linmao Li @ 2026-08-13 7:26 ` Linmao Li 2026-08-13 7:39 ` sashiko-bot 1 sibling, 1 reply; 5+ messages in thread From: Linmao Li @ 2026-08-13 7:26 UTC (permalink / raw) To: doubled, James.Bottomley, martin.petersen, linux-scsi Cc: hare, dlemoal, linux-kernel, Linmao Li leapraid_fw_log_exit() waits for mmap_refcnt to reach zero before it frees the firmware log buffer. leapraid_fw_mmap() checks host_removing, but it does not increment mmap_refcnt until after dma_mmap_coherent() succeeds and the VMA open callback runs. Removal can set host_removing and observe a zero mmap_refcnt between the check and the VMA open. It can then free the coherent buffer while the mmap path is still establishing a userspace mapping of it. Claim a temporary mmap reference while looking up the adapter under leapraid_adapter_lock. Removal deletes the adapter from the same locked list after setting host_removing, so a mapping is either rejected or included in the count that removal waits for. Drop the temporary reference on the common exit path, after a successful VMA open has acquired the reference covering the VMA lifetime. Fixes: 5597088c9e79 ("scsi: leapraid: Add new SCSI driver") Signed-off-by: Linmao Li <lilinmao@kylinos.cn> --- drivers/scsi/leapraid/leapraid_app.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/leapraid/leapraid_app.c b/drivers/scsi/leapraid/leapraid_app.c index 841027ce2501c..790a3191e9259 100644 --- a/drivers/scsi/leapraid/leapraid_app.c +++ b/drivers/scsi/leapraid/leapraid_app.c @@ -171,7 +171,7 @@ static int leapraid_ctl_validate_sge_offset(struct leapraid_adapter *adapter, return 0; } -static struct leapraid_adapter *leapraid_ctl_lookup_adapter(int adapter_id) +static struct leapraid_adapter *leapraid_ctl_lookup_adapter(int adapter_id, bool track_mmap) { struct leapraid_adapter *adapter; struct Scsi_Host *shost; @@ -184,6 +184,8 @@ static struct leapraid_adapter *leapraid_ctl_lookup_adapter(int adapter_id) shost = adapter->shost; if (!shost || !scsi_host_get(shost)) break; + if (track_mmap) + atomic_inc(&adapter->fw_log_desc.mmap_refcnt); spin_unlock(&leapraid_adapter_lock); return adapter; } @@ -589,7 +591,7 @@ static int leapraid_ctl_ioctl_main(struct file *file, unsigned int cmd, return -EFAULT; } - adapter = leapraid_ctl_lookup_adapter(ioctl_header.adapter_id); + adapter = leapraid_ctl_lookup_adapter(ioctl_header.adapter_id, false); if (!adapter) return -EFAULT; @@ -728,7 +730,7 @@ static int leapraid_fw_mmap(struct file *filp, struct vm_area_struct *vma) length = vma->vm_end - vma->vm_start; - adapter = leapraid_ctl_lookup_adapter(adapter_id); + adapter = leapraid_ctl_lookup_adapter(adapter_id, true); if (!adapter) { pr_err("%s: No adapter found!\n", __func__); return -EINVAL; @@ -771,6 +773,9 @@ static int leapraid_fw_mmap(struct file *filp, struct vm_area_struct *vma) rc = 0; out_put: + if (adapter && + atomic_dec_and_test(&adapter->fw_log_desc.mmap_refcnt)) + wake_up(&adapter->fw_log_desc.mmap_waitq); leapraid_ctl_put_adapter(adapter); return rc; } -- 2.25.1 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v2 2/2] scsi: leapraid: serialize firmware log mmap with teardown 2026-08-13 7:26 ` [PATCH v2 2/2] scsi: leapraid: serialize firmware log mmap with teardown Linmao Li @ 2026-08-13 7:39 ` sashiko-bot 0 siblings, 0 replies; 5+ messages in thread From: sashiko-bot @ 2026-08-13 7:39 UTC (permalink / raw) To: Linmao Li; +Cc: linux-scsi Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: Pre-existing issues: - [High] Device removal and module unloading can be permanently blocked by a userspace process holding an open memory mapping. -- --- Patch [2]: [PATCH v2 2/2] scsi: leapraid: serialize firmware log mmap with teardown --- commit 3180bb0e1579b0aca65c2e7927f3bdc91744a626 Author: Linmao Li <lilinmao@kylinos.cn> scsi: leapraid: serialize firmware log mmap with teardown This patch addresses a race condition where a firmware log buffer could be freed during device removal while a concurrent mmap operation is establishing a userspace mapping. It claims a temporary mmap reference while looking up the adapter, and drops it on the exit path. > diff --git a/drivers/scsi/leapraid/leapraid_app.c b/drivers/scsi/leapraid/leapraid_app.c > index 841027ce2501c..790a3191e9259 100644 > --- a/drivers/scsi/leapraid/leapraid_app.c > +++ b/drivers/scsi/leapraid/leapraid_app.c [ ... ] > @@ -771,6 +773,9 @@ static int leapraid_fw_mmap(struct file *filp, struct vm_area_struct *vma) > > rc = 0; > out_put: > + if (adapter && > + atomic_dec_and_test(&adapter->fw_log_desc.mmap_refcnt)) > + wake_up(&adapter->fw_log_desc.mmap_waitq); [Severity: High] This is a pre-existing issue, but can this userspace-controlled reference count block device removal and module unloading permanently? Since a userspace process can hold the VMA open indefinitely, and device removal waits unconditionally in leapraid_fw_log_exit() for the count to reach zero: drivers/scsi/leapraid/leapraid_func.c:leapraid_fw_log_exit() { ... wait_event(adapter->fw_log_desc.mmap_waitq, !atomic_read(&adapter->fw_log_desc.mmap_refcnt)); ... } Could a buggy or malicious userspace process that never unmaps the memory cause the kernel thread handling PCI hotplug or sysfs unbind to hang forever without a timeout? > leapraid_ctl_put_adapter(adapter); > return rc; > } -- Sashiko AI review · https://sashiko.dev/#/patchset/20260813072614.1387555-1-lilinmao@kylinos.cn?part=2 ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-08-13 7:39 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-08-13 7:26 [PATCH v2 0/2] scsi: leapraid: fix firmware log mmap lifetime Linmao Li 2026-08-13 7:26 ` [PATCH v2 1/2] scsi: leapraid: balance host references for firmware log VMAs Linmao Li 2026-08-13 7:39 ` sashiko-bot 2026-08-13 7:26 ` [PATCH v2 2/2] scsi: leapraid: serialize firmware log mmap with teardown Linmao Li 2026-08-13 7:39 ` sashiko-bot
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox