* [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; 5+ 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] 5+ 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 3:38 ` [PATCH v3 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-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] 5+ 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
1 sibling, 1 reply; 5+ 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] 5+ 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
0 siblings, 0 replies; 5+ 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] 5+ 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
0 siblings, 0 replies; 5+ 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] 5+ messages in thread
end of thread, other threads:[~2026-08-14 3:56 UTC | newest]
Thread overview: 5+ 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 3:38 ` [PATCH v3 2/2] scsi: leapraid: serialize firmware log mmap with teardown Linmao Li
2026-08-14 3:52 ` sashiko-bot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox