Messages in this thread | | | Date | Wed, 23 Feb 2022 09:46:27 -0400 | From | Jason Gunthorpe <> | Subject | Re: [PATCH v6 02/11] driver core: Add dma_cleanup callback in bus_type |
| |
On Wed, Feb 23, 2022 at 01:04:00PM +0000, Robin Murphy wrote:
> 1 - tmp->driver is non-NULL because tmp is already bound. > 1.a - If tmp->driver->driver_managed_dma == 0, the group must currently be > DMA-API-owned as a whole. Regardless of what driver dev has unbound from, > its removal does not release someone else's DMA API (co-)ownership.
This is an uncommon locking pattern, but it does work. It relies on the mutex being an effective synchronization barrier for an unlocked store:
WRITE_ONCE(dev->driver, NULL)
mutex_lock(&group->lock) READ_ONCE(dev->driver) != NULL and no UAF mutex_unlock(&group->lock)
mutex_lock(&group->lock) tmp = READ_ONCE(dev1->driver); if (tmp && tmp->blah) [..] mutex_unlock(&group->lock) mutex_lock(&group->lock) READ_ONCE(dev->driver) == NULL mutex_unlock(&group->lock)
/* No other CPU can UAF dev->driver */ kfree(driver)
Ie the CPU setting driver cannot pass to the next step without all other CPUs observing the new value because of the release/acquire built into the mutex_lock.
It is tricky, and can work in this instance, but the pattern's unlocked design relies on ordering between the WRITE_ONCE and the locks - and that ordering in dd.c isn't like that today.
Jason
| |