* [PATCH 0/2] scsi: leapraid: fix firmware log mmap lifetime @ 2026-08-11 11:19 Linmao Li 2026-08-11 11:20 ` [PATCH 1/2] scsi: leapraid: balance host references for firmware log VMAs Linmao Li 2026-08-11 11:20 ` [PATCH 2/2] scsi: leapraid: serialize firmware log mmap with teardown Linmao Li 0 siblings, 2 replies; 4+ messages in thread From: Linmao Li @ 2026-08-11 11:19 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. 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] 4+ messages in thread
* [PATCH 1/2] scsi: leapraid: balance host references for firmware log VMAs 2026-08-11 11:19 [PATCH 0/2] scsi: leapraid: fix firmware log mmap lifetime Linmao Li @ 2026-08-11 11:20 ` Linmao Li 2026-08-11 11:20 ` [PATCH 2/2] scsi: leapraid: serialize firmware log mmap with teardown Linmao Li 1 sibling, 0 replies; 4+ messages in thread From: Linmao Li @ 2026-08-11 11:20 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 [flat|nested] 4+ messages in thread
* [PATCH 2/2] scsi: leapraid: serialize firmware log mmap with teardown 2026-08-11 11:19 [PATCH 0/2] scsi: leapraid: fix firmware log mmap lifetime Linmao Li 2026-08-11 11:20 ` [PATCH 1/2] scsi: leapraid: balance host references for firmware log VMAs Linmao Li @ 2026-08-11 11:20 ` Linmao Li 2026-08-13 6:36 ` Hao Dongdong 1 sibling, 1 reply; 4+ messages in thread From: Linmao Li @ 2026-08-11 11:20 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..c124f9eaea6ea 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 [flat|nested] 4+ messages in thread
* Re: [PATCH 2/2] scsi: leapraid: serialize firmware log mmap with teardown 2026-08-11 11:20 ` [PATCH 2/2] scsi: leapraid: serialize firmware log mmap with teardown Linmao Li @ 2026-08-13 6:36 ` Hao Dongdong 0 siblings, 0 replies; 4+ messages in thread From: Hao Dongdong @ 2026-08-13 6:36 UTC (permalink / raw) To: Linmao Li, James.Bottomley, martin.petersen, linux-scsi Cc: hare, dlemoal, linux-kernel 在 2026/8/11 19:20, 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..c124f9eaea6ea 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) Hi Linmao, Thank you for identifying and fixing this race. Your analysis and fix are correct. I have only one minor comment: why the line break here? This declaration fits within the line-length limit, so please keep the return type and function name on the same line to follow the usual kernel coding style. With this minor formatting issue addressed, I will be happy to accept the patch. Thanks again! Best regards, Dongdong > { > 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; > } ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-08-13 7:12 UTC | newest] Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2026-08-11 11:19 [PATCH 0/2] scsi: leapraid: fix firmware log mmap lifetime Linmao Li 2026-08-11 11:20 ` [PATCH 1/2] scsi: leapraid: balance host references for firmware log VMAs Linmao Li 2026-08-11 11:20 ` [PATCH 2/2] scsi: leapraid: serialize firmware log mmap with teardown Linmao Li 2026-08-13 6:36 ` Hao Dongdong
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®