* [PATCH v3 0/2] scsi: leapraid: fix firmware log mmap lifetime @ 2026-08-14 3:38 Linmao Li 2026-08-14 3:38 ` [PATCH v3 1/2] scsi: leapraid: balance host references for firmware log VMAs Linmao Li 2026-08-14 3:38 ` [PATCH v3 2/2] scsi: leapraid: serialize firmware log mmap with teardown Linmao Li 0 siblings, 2 replies; 7+ messages in thread From: Linmao Li @ 2026-08-14 3:38 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 v3: - 2/2: wrap the leapraid_ctl_lookup_adapter() declaration before bool track_mmap, aligned with int adapter_id, to stay within 80 columns, matching leapraid_ctl_validate_sge_offset() (Dongdong Hao) - 1/2: unchanged Changes in v2: - 2/2: keep the return type and function name on the same line (Dongdong Hao) - 1/2: unchanged v1: https://lore.kernel.org/all/20260811112001.1158587-1-lilinmao@kylinos.cn/ v2: https://lore.kernel.org/all/20260813072614.1387555-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 | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) base-commit: 376a3960e5efe85ff765abfb5b5b7e4655ad6aed -- 2.25.1 ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v3 1/2] scsi: leapraid: balance host references for firmware log VMAs 2026-08-14 3:38 [PATCH v3 0/2] scsi: leapraid: fix firmware log mmap lifetime Linmao Li @ 2026-08-14 3:38 ` Linmao Li 2026-08-14 3:56 ` sashiko-bot 2026-08-14 8:05 ` Hao Dongdong 2026-08-14 3:38 ` [PATCH v3 2/2] scsi: leapraid: serialize firmware log mmap with teardown Linmao Li 1 sibling, 2 replies; 7+ messages in thread From: Linmao Li @ 2026-08-14 3:38 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] 7+ messages in thread
* Re: [PATCH v3 1/2] scsi: leapraid: balance host references for firmware log VMAs 2026-08-14 3:38 ` [PATCH v3 1/2] scsi: leapraid: balance host references for firmware log VMAs Linmao Li @ 2026-08-14 3:56 ` sashiko-bot 2026-08-14 8:05 ` Hao Dongdong 1 sibling, 0 replies; 7+ messages in thread From: sashiko-bot @ 2026-08-14 3:56 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: - [Critical] TOCTOU race condition in `leapraid_fw_mmap` leading to Use-After-Free of DMA buffer. - [High] Device removal path hangs uninterruptibly waiting for userspace to close VMAs. -- --- Patch [1]: [PATCH v3 1/2] scsi: leapraid: balance host references for firmware log VMAs --- commit 727a052aa98a29cd5e6da31ed634d370a79651cc 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. > 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 reference counting lead to an uninterruptible hang during device removal? Looking at the teardown path in leapraid_remove_ctrl() -> leapraid_fw_log_exit(), the kernel waits for this reference count to hit zero: wait_event(adapter->fw_log_desc.mmap_waitq, !atomic_read(&adapter->fw_log_desc.mmap_refcnt)); Since there is no timeout and no alternative wake condition, couldn't any userspace process that keeps the VMA open indefinitely cause the kernel thread running the removal to hang, creating a denial of service? > } [ ... ] > @@ -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: Critical] This is a pre-existing issue, but does this sequence create a race condition leading to a use-after-free of the DMA buffer? Just prior to this snippet, dma_mmap_coherent() is called locklessly and before mmap_refcnt is incremented here via leapraid_fw_mmap_open(). If a concurrent device removal starts right before dma_mmap_coherent(), the removal thread would see mmap_refcnt == 0. It would then proceed to free fw_log_buffer via dma_free_coherent() in leapraid_fw_log_exit(). Could the mmap thread then resume and map the now-freed DMA memory into user space? > - adapter = NULL; > > rc = 0; > out_put: -- Sashiko AI review · https://sashiko.dev/#/patchset/20260814033845.2971706-1-lilinmao@kylinos.cn?part=1 ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v3 1/2] scsi: leapraid: balance host references for firmware log VMAs 2026-08-14 3:38 ` [PATCH v3 1/2] scsi: leapraid: balance host references for firmware log VMAs Linmao Li 2026-08-14 3:56 ` sashiko-bot @ 2026-08-14 8:05 ` Hao Dongdong 1 sibling, 0 replies; 7+ messages in thread From: Hao Dongdong @ 2026-08-14 8:05 UTC (permalink / raw) To: Linmao Li, James.Bottomley, martin.petersen, linux-scsi Cc: hare, dlemoal, linux-kernel 在 2026/8/14 11:38, 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: Thanks for the fix. This correctly fixes the issue. Reviewed-by: Dongdong Hao <doubled@leap-io-kernel.com> ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v3 2/2] scsi: leapraid: serialize firmware log mmap with teardown 2026-08-14 3:38 [PATCH v3 0/2] scsi: leapraid: fix firmware log mmap lifetime Linmao Li 2026-08-14 3:38 ` [PATCH v3 1/2] scsi: leapraid: balance host references for firmware log VMAs Linmao Li @ 2026-08-14 3:38 ` Linmao Li 2026-08-14 3:52 ` sashiko-bot 2026-08-14 8:08 ` Hao Dongdong 1 sibling, 2 replies; 7+ messages in thread From: Linmao Li @ 2026-08-14 3:38 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 | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/leapraid/leapraid_app.c b/drivers/scsi/leapraid/leapraid_app.c index 841027ce2501c..84eef50947aea 100644 --- a/drivers/scsi/leapraid/leapraid_app.c +++ b/drivers/scsi/leapraid/leapraid_app.c @@ -171,7 +171,8 @@ 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 +185,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 +592,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 +731,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 +774,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] 7+ messages in thread
* Re: [PATCH v3 2/2] scsi: leapraid: serialize firmware log mmap with teardown 2026-08-14 3:38 ` [PATCH v3 2/2] scsi: leapraid: serialize firmware log mmap with teardown Linmao Li @ 2026-08-14 3:52 ` sashiko-bot 2026-08-14 8:08 ` Hao Dongdong 1 sibling, 0 replies; 7+ messages in thread From: sashiko-bot @ 2026-08-14 3:52 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] Unbounded wait in `leapraid_fw_log_exit()` allows userspace to block PCI device removal indefinitely. -- --- Patch [2]: [PATCH v3 2/2] scsi: leapraid: serialize firmware log mmap with teardown --- commit f76020cc63b98ce5d018410c191835d8ffc2261a Author: Linmao Li <lilinmao@kylinos.cn> scsi: leapraid: serialize firmware log mmap with teardown This commit fixes a race condition during firmware log teardown by claiming a temporary mmap reference during adapter lookup. It ensures the driver does not free the coherent buffer while the mmap path is still establishing a mapping. > diff --git a/drivers/scsi/leapraid/leapraid_app.c b/drivers/scsi/leapraid/leapraid_app.c > index 841027ce2501c..84eef50947aea 100644 > --- a/drivers/scsi/leapraid/leapraid_app.c > +++ b/drivers/scsi/leapraid/leapraid_app.c [ ... ] > @@ -771,6 +774,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 since we are modifying the mmap teardown synchronization here, I noticed a potential problem on the wait side of this logic. If a userspace process keeps the VMA open indefinitely, won't the unbind process hang forever? Looking at the teardown side in 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)); } Since this waits in uninterruptible sleep without a timeout, could a rogue or stuck userspace application block PCI device removal or module unloading permanently? It seems like the kernel shouldn't rely on cooperative userspace behavior during hardware unbind, perhaps this needs an unmap_mapping_range() or similar asynchronous shootdown mechanism to ensure the wait completes? > leapraid_ctl_put_adapter(adapter); > return rc; > } -- Sashiko AI review · https://sashiko.dev/#/patchset/20260814033845.2971706-1-lilinmao@kylinos.cn?part=2 ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v3 2/2] scsi: leapraid: serialize firmware log mmap with teardown 2026-08-14 3:38 ` [PATCH v3 2/2] scsi: leapraid: serialize firmware log mmap with teardown Linmao Li 2026-08-14 3:52 ` sashiko-bot @ 2026-08-14 8:08 ` Hao Dongdong 1 sibling, 0 replies; 7+ messages in thread From: Hao Dongdong @ 2026-08-14 8:08 UTC (permalink / raw) To: Linmao Li, James.Bottomley, martin.petersen, linux-scsi Cc: hare, dlemoal, linux-kernel 在 2026/8/14 11:38, 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 | 12 +++++++++--- > 1 file changed, 9 insertions(+), 3 deletions(-) > > diff --git a/drivers/scsi/leapraid/leapraid_app.c b/drivers/scsi/leapraid/leapraid_app.c > index 841027ce2501c..84eef50947aea 100644 > --- a/drivers/scsi/leapraid/leapraid_app.c > +++ b/drivers/scsi/leapraid/leapraid_app.c > @@ -171,7 +171,8 @@ 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 +185,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 +592,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 +731,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 +774,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; > } Thanks for fixing this race. Taking the temporary mmap reference under leapraid_adapter_lock correctly closes the race with adapter removal. Reviewed-by: Dongdong Hao <doubled@leap-io-kernel.com> ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-08-14 8:23 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-08-14 3:38 [PATCH v3 0/2] scsi: leapraid: fix firmware log mmap lifetime Linmao Li 2026-08-14 3:38 ` [PATCH v3 1/2] scsi: leapraid: balance host references for firmware log VMAs Linmao Li 2026-08-14 3:56 ` sashiko-bot 2026-08-14 8:05 ` Hao Dongdong 2026-08-14 3:38 ` [PATCH v3 2/2] scsi: leapraid: serialize firmware log mmap with teardown Linmao Li 2026-08-14 3:52 ` sashiko-bot 2026-08-14 8:08 ` Hao Dongdong
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.