Page MenuHomeFreeBSD

mpi3mr: Safely re-validate target before unblocking I/O in IOCTL error path
Needs ReviewPublic

Authored by chandrakanth.patil_broadcom.com on Sun, Oct 4, 2:11 PM.

Details

Summary

When issuing task management or configuration commands to a target device
via userland IOCTL, the driver temporarily blocks host I/O to that target.
If the command fails or times out, the error unwinding path decremented
the I/O blocking counter using the originally resolved target pointer.

However, management command timeouts can be lengthy. If the target device
was removed or deleted while the IOCTL was waiting for completion, the
original target structure could have been freed before the command timed
out. Decrementing the counter through the stale pointer resulted in a
use-after-free.

Safely re-lookup the target device by its hardware handle from the active
device list before modifying the counter. If the device was already
removed, the stale pointer dereference is safely skipped.

Test Plan
  • Clean build with WERROR=-Werror across FreeBSD 16, 15, and 14 with INVARIANTS/WITNESS enabled; git bisect verified.
  • Tested userland task management IOCTL commands alongside concurrent target device removal on SAS4116/SAS5116 controllers.
  • Verified that command timeouts during concurrent device removal do not cause use-after-free conditions.

Diff Detail

Lint
Lint Skipped
Unit
Tests Skipped

Event Timeline

sys/dev/mpi3mr/mpi3mr_app.c
1263

Since find_target_by_dev_handle drops the lock that prevents the target from being removed from list, tgtdev_recheck may be referencing a target that's just been freed by another thread that calls mpi3mr_remove_device_from_list?

sys/dev/mpi3mr/mpi3mr_app.c
1263

Since find_target_by_dev_handle drops the lock that prevents the target from being removed from list, tgtdev_recheck may be referencing a target that's just been freed by another thread that calls mpi3mr_remove_device_from_list?

Correct. Dropping target_lock inside find_target_by_dev_handle leaves a window where the target can be freed before block_io is decremented.

I will update this to perform the lookup and decrement directly under target_lock in V2 patch so the target cannot be removed or freed concurrently.