Re: [PATCH v5 17/27] scsi-multipath: revalidate paths upon device unblock

John Garry <[email protected]>
Newsgroups org.kernel.vger.linux-scsi,dev.linux.lists.sashiko-reviews
Organization Oracle Corporation
Message-ID <[email protected]>
On 27/07/2026 16:17, [email protected] wrote:
> Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
> - [High] Race condition in `scsi_internal_device_unblock` and `scsi_device_block` leading to NULL pointer dereference.
> - [High] Concurrent execution of `scsi_mpath_dev_alloc` and transport block/unblock leads to Use-After-Free and NULL pointer dereference.
> --
> 
> --- Patch [17]: [PATCH v5 17/27] scsi-multipath: revalidate paths upon device unblock ---
> commit d7b8727956ce248cf872dc90fa72742ade627f54
> Author: John Garry <[email protected]>
> 
> scsi-multipath: revalidate paths upon device unblock
>      
> When a scsi_device is unblocked, this patch clears paths and requeues
> any queued bios to revalidate the paths.
> 
>> diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
>> --- a/drivers/scsi/scsi_lib.c
>> +++ b/drivers/scsi/scsi_lib.c
> [ ... ]
>> @@ -3092,6 +3092,8 @@ static int scsi_internal_device_unblock(struct scsi_device *sdev,
>>   	mutex_lock(&sdev->state_mutex);
>>   	ret = scsi_internal_device_unblock_nowait(sdev, new_state);
>>   	mutex_unlock(&sdev->state_mutex);
>> +	if ((ret == 0) && sdev->scsi_mpath_dev)
>> +		scsi_mpath_revalidate_paths(sdev->scsi_mpath_dev);
>>   
>>   	return ret;
>>   }
> 
> [Severity: High]
> Can this lockless check of sdev->scsi_mpath_dev lead to a use-after-free or
> NULL pointer dereference?

Last time you complained about having locking. Now you complain about no 
locking.

> 
> During device discovery, scsi_alloc_sdev() publishes the scsi_device to
> shost->__devices. After this, scsi_mpath_dev_alloc() assigns
> sdev->scsi_mpath_dev but can fail and jump to out_uninit where it frees
> the structure:
> 
> drivers/scsi/scsi_multipath.c:scsi_mpath_dev_alloc() {
>      ...
>      ret = scsi_multipath_sdev_init(sdev);
>      if (ret)
>          return ret;
> 
>      ret = scsi_mpath_unique_lun_id(sdev);
>      if (ret < 0)
>          goto out_uninit;
>      ...
> }
> 
> If an asynchronous transport event triggers scsi_internal_device_unblock()
> during this window, could it read a freed sdev->scsi_mpath_dev, or one where
> scsi_mpath_head is not yet initialized?

Give a proper example of when this can happen and not just mention 
"asynchronous transport event"
> 
> Could a concurrent device removal also trigger a similar race?
> 
> If __scsi_remove_device() executes after the mutex_unlock() but before
> sdev->scsi_mpath_dev is evaluated

Again, this should not happen as __scsi_remove_device() should not be 
called before sdev->scsi_mpath_dev is evaluated

>, it could set the device state to
> SDEV_CANCEL and call scsi_mpath_remove_device(). This sets
> scsi_mpath_dev->scsi_mpath_head to NULL.
> 
> (Note: An earlier patch in this series appears to introduce an identical
> lockless pattern in scsi_device_block() checking sdev->scsi_mpath_dev.)

Who is calling scsi_internal_device_unblock() and __scsi_remove_device() 
in parallel?

> 
>> diff --git a/drivers/scsi/scsi_multipath.c b/drivers/scsi/scsi_multipath.c
>> --- a/drivers/scsi/scsi_multipath.c
>> +++ b/drivers/scsi/scsi_multipath.c
> [ ... ]
>> @@ -231,6 +231,14 @@ static int scsi_multipath_sdev_init(struct scsi_device *sdev)
>>   	return 0;
>>   }
>>   
>> +void scsi_mpath_revalidate_paths(struct scsi_mpath_device *scsi_mpath_dev)
>> +{
>> +       struct scsi_mpath_head *scsi_mpath_head = scsi_mpath_dev->scsi_mpath_head;
>> +       struct mpath_head *mpath_head = &scsi_mpath_head->mpath_head;
>> +
>> +       mpath_revalidate_paths(mpath_head);
>> +}
> 
> [Severity: High]
> Does this code safely handle a NULL scsi_mpath_head?
> 
> If the race mentioned above occurs and a concurrent teardown clears
> scsi_mpath_head to NULL, would this assignment dereference the NULL pointer
> when attempting to resolve mpath_head?
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.