All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "John Garry" <john.garry@linux.dev>,
	james.bottomley@hansenpartnership.com, mkp@kernel.org
Cc: hare@suse.com, linux-nvme@lists.infradead.org,
	linux-scsi@vger.kernel.org, snitzer@kernel.org,
	jmeneghi@redhat.com, bmarzins@redhat.com,
	dm-devel@lists.linux.dev, hch@lst.de,
	michael.christie@oracle.com
Subject: Re: [PATCH v9 18/29] scsi-multipath: revalidate paths upon device unblock
Date: Sun, 08 Nov 2026 21:08:12 +0000	[thread overview]
Message-ID: <sashiko-outbox-204059@kernel.org> (raw)
In-Reply-To: <20261108204733.557995-19-john.garry@linux.dev>

Thank you for your contribution! Sashiko AI review found 4 potential
issues to consider:
- [High] scsi: multipath: race in scsi_internal_device_unblock() on
  scsi_mpath_head
- [High] scsi: multipath: use-after-free in
  scsi_mpath_revalidate_paths() requeue_work
- [Medium] scsi: multipath: race in scsi_device_block() accessing
  scsi_mpath_head
- [Medium] scsi: multipath: premature scsi_mpath_dev publish in
  scsi_mpath_dev_alloc()
--

commit ed012aa632cd8957f54296618fde6fa312555b38
Author: John Garry <john.garry@linux.dev>

scsi-multipath: revalidate paths upon device unblock

This commit adds scsi_mpath_revalidate_paths() and calls it from
scsi_internal_device_unblock() to clear paths and requeue bios when a
multipath SCSI device is unblocked.

> diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
> index 1950034f580f4..4dbd01484b4a5 100644
> --- a/drivers/scsi/scsi_lib.c
> +++ b/drivers/scsi/scsi_lib.c
> @@ -3121,6 +3121,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 scsi_internal_device_unblock() race with __scsi_remove_device() and
dereference a NULL or freed scsi_mpath_head?

Callers such as scsi_target_unblock() and scsi_host_unblock() iterate
devices with shost_for_each_device(), which pins sdev->sdev_gendev (deferring
scsi_device_dev_release() where sdev->scsi_mpath_dev is freed) without
holding shost->scan_mutex.  Because sdev->state_mutex is dropped before
calling scsi_mpath_revalidate_paths() (and
scsi_internal_device_unblock_nowait() also returns 0 in SDEV_CANCEL),
__scsi_remove_device() can tear down scsi_mpath_dev->scsi_mpath_head
concurrently:

CPU0                                  CPU1
scsi_target_unblock()
  scsi_internal_device_unblock()
    mutex_lock(&sdev->state_mutex)
    scsi_internal_device_unblock_nowait()
    mutex_unlock(&sdev->state_mutex)
                                      __scsi_remove_device()
                                        ...
                                        scsi_mpath_remove_device()
                                          scsi_mpath_remove_head()
                                            scsi_mpath_put_head()
                                            scsi_mpath_dev->scsi_mpath_head = NULL
    scsi_mpath_revalidate_paths()
      mpath_revalidate_paths(mpath_head)  <-- NULL deref or use-after-free

In scsi_mpath_revalidate_paths(), &scsi_mpath_head->mpath_head is at offset
0, so mpath_clear_paths() and mpath_schedule_requeue_work() dereference a
NULL or freed mpath_head.

[Severity: Medium]
Can scsi_internal_device_unblock() also observe a partially initialized or
freed sdev->scsi_mpath_dev during LUN scanning?

In scsi_add_lun(), sdev is already on shost->__devices and starget->devices
and set to SDEV_RUNNING or SDEV_BLOCK before scsi_mpath_dev_alloc() runs:

CPU0                                  CPU1
scsi_add_lun()
  scsi_mpath_dev_alloc()
    scsi_multipath_sdev_init()
      sdev->scsi_mpath_dev = scsi_mpath_dev
                                      scsi_target_unblock()
                                        scsi_internal_device_unblock()
                                          if (ret == 0 && sdev->scsi_mpath_dev)
                                            scsi_mpath_revalidate_paths()
                                              mpath_revalidate_paths(NULL)
                                              <-- NULL pointer dereference
    scsi_mpath_unique_lun_id()
    ...
    sdev->scsi_mpath_dev->scsi_mpath_head = ...

If scsi_mpath_dev_alloc() fails later at out_uninit,
scsi_multipath_sdev_uninit() also frees sdev->scsi_mpath_dev before clearing
the pointer, allowing a concurrent unblock to hit a use-after-free.

> diff --git a/drivers/scsi/scsi_multipath.c b/drivers/scsi/scsi_multipath.c
> index 67e9010d54782..008bcafe73ad2 100644
> --- a/drivers/scsi/scsi_multipath.c
> +++ b/drivers/scsi/scsi_multipath.c
> @@ -240,6 +240,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]
Can mpath_head->requeue_work queued by scsi_mpath_revalidate_paths() run
after scsi_mpath_head is freed?

Transport target teardown paths such as fc_starget_delete(),
iscsi_remove_session(), and rport_dev_loss_timedout() call
scsi_target_unblock(..., SDEV_TRANSPORT_OFFLINE) immediately followed by
scsi_remove_target():

CPU0                                  kworker
fc_starget_delete()
  scsi_target_unblock()
    scsi_internal_device_unblock()
      scsi_mpath_revalidate_paths()
        mpath_revalidate_paths()
          mpath_schedule_requeue_work()
  scsi_remove_target()
    ...
      scsi_mpath_remove_device()
        scsi_mpath_put_head()
          scsi_mpath_head_release()
            kfree(scsi_mpath_head)
                                      mpath_requeue_work()
                                        spin_lock_irq(&mpath_head->requeue_lock)
                                        <-- use-after-free

Unlike scsi_mpath_device_iopolicy_store(), which calls
flush_work(&mpath_head->requeue_work) with a comment noting that
requeue_work could otherwise run after mpath_head is gone, neither
scsi_mpath_revalidate_paths() nor scsi_mpath_head_release() /
mpath_head_uninit() flushes or cancels mpath_head->requeue_work.

> +
>  void scsi_mpath_dev_clear_path(struct scsi_mpath_device *scsi_mpath_dev)
>  {
>         struct mpath_device *mpath_device = &scsi_mpath_dev->mpath_device;

[Severity: Medium]
Can scsi_device_block() hit the same race against __scsi_remove_device() or
scsi_mpath_dev_alloc() when calling scsi_mpath_dev_clear_path()?

drivers/scsi/scsi_lib.c:scsi_device_block() {
    ...
	mutex_unlock(&sdev->state_mutex);
	if ((err == 0) && sdev->scsi_mpath_dev)
		scsi_mpath_dev_clear_path(sdev->scsi_mpath_dev);
    ...
}

Once scsi_device_block() drops sdev->state_mutex, __scsi_remove_device() can
transition sdev from SDEV_BLOCK directly to SDEV_DEL and run
scsi_mpath_remove_device(), freeing scsi_mpath_head and clearing
scsi_mpath_dev->scsi_mpath_head before scsi_mpath_dev_clear_path()
dereferences it in mpath_synchronize().

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261108204733.557995-1-john.garry@linux.dev?part=18


  reply	other threads:[~2026-11-08 21:08 UTC|newest]

Thread overview: 45+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-08 20:47 [PATCH v9 00/29] Native SCSI Multipath support John Garry
2026-11-08 20:47 ` [PATCH v9 01/29] scsi: core: Clear cmd->flags for terminal queuing error John Garry
2026-11-09 20:49   ` Bart Van Assche
2026-11-08 20:47 ` [PATCH v9 02/29] libmultipath: Add initial framework John Garry
2026-11-08 20:47 ` [PATCH v9 03/29] libmultipath: Add basic gendisk support John Garry
2026-11-08 20:47 ` [PATCH v9 04/29] libmultipath: Add path selection support John Garry
2026-11-08 21:07   ` sashiko-bot
2026-11-08 20:47 ` [PATCH v9 05/29] libmultipath: Add bio handling John Garry
2026-11-08 20:47 ` [PATCH v9 06/29] libmultipath: Add support for mpath_device management John Garry
2026-11-08 20:47 ` [PATCH v9 07/29] libmultipath: Add delayed removal support John Garry
2026-11-08 21:11   ` sashiko-bot
2026-11-08 20:47 ` [PATCH v9 08/29] libmultipath: Add sysfs helpers John Garry
2026-11-08 21:02   ` sashiko-bot
2026-11-08 20:47 ` [PATCH v9 09/29] libmultipath: Add support for block device IOCTL John Garry
2026-11-08 21:09   ` sashiko-bot
2026-11-08 20:47 ` [PATCH v9 10/29] libmultipath: Add mpath_bdev_getgeo() John Garry
2026-11-08 20:47 ` [PATCH v9 11/29] libmultipath: Add mpath_bdev_get_unique_id() John Garry
2026-11-08 20:47 ` [PATCH v9 12/29] scsi-multipath: introduce basic SCSI device support John Garry
2026-11-08 21:02   ` sashiko-bot
2026-11-08 20:47 ` [PATCH v9 13/29] scsi-multipath: introduce scsi_device head structure John Garry
2026-11-08 20:47 ` [PATCH v9 14/29] scsi-multipath: provide sysfs link from to scsi_device John Garry
2026-11-08 20:47 ` [PATCH v9 15/29] scsi-multipath: support iopolicy John Garry
2026-11-08 20:47 ` [PATCH v9 16/29] scsi-multipath: clone each bio John Garry
2026-11-08 20:47 ` [PATCH v9 17/29] scsi-multipath: clear path when device is blocked John Garry
2026-11-08 21:06   ` sashiko-bot
2026-11-08 20:47 ` [PATCH v9 18/29] scsi-multipath: revalidate paths upon device unblock John Garry
2026-11-08 21:08   ` sashiko-bot [this message]
2026-11-08 20:47 ` [PATCH v9 19/29] scsi-multipath: failover handling John Garry
2026-11-08 21:15   ` sashiko-bot
2026-11-08 20:47 ` [PATCH v9 20/29] scsi-multipath: provide callbacks for path state John Garry
2026-11-08 21:05   ` sashiko-bot
2026-11-08 20:47 ` [PATCH v9 21/29] scsi-multipath: add scsi_mpath_{start,end}_request() John Garry
2026-11-08 21:28   ` sashiko-bot
2026-11-08 20:47 ` [PATCH v9 22/29] scsi-multipath: update request for terminal request queuing error John Garry
2026-11-08 21:09   ` sashiko-bot
2026-11-08 20:47 ` [PATCH v9 23/29] scsi-multipath: add delayed disk removal support John Garry
2026-11-08 20:47 ` [PATCH v9 24/29] scsi: sd: add multipath disk class John Garry
2026-11-08 20:47 ` [PATCH v9 25/29] scsi: sd: add multipath disk attr groups John Garry
2026-11-08 20:47 ` [PATCH v9 26/29] scsi: sd: support multipath disk John Garry
2026-11-08 21:23   ` sashiko-bot
2026-11-08 20:47 ` [PATCH v9 27/29] scsi: sd: add mpath_dev file John Garry
2026-11-08 20:47 ` [PATCH v9 28/29] scsi: sd: add mpath_numa_nodes dev attribute John Garry
2026-11-08 20:47 ` [PATCH v9 29/29] scsi: sd: add mpath_queue_depth " John Garry
2026-11-09 20:19 ` [PATCH v9 00/29] Native SCSI Multipath support Laurence Oberman
2026-11-10  9:05   ` John Garry

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=sashiko-outbox-204059@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=bmarzins@redhat.com \
    --cc=dm-devel@lists.linux.dev \
    --cc=hare@suse.com \
    --cc=hch@lst.de \
    --cc=james.bottomley@hansenpartnership.com \
    --cc=jmeneghi@redhat.com \
    --cc=john.garry@linux.dev \
    --cc=linux-nvme@lists.infradead.org \
    --cc=linux-scsi@vger.kernel.org \
    --cc=michael.christie@oracle.com \
    --cc=mkp@kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=snitzer@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.