On 12/13/23 09:04, Amelie Delaunay wrote: > __dma_async_device_channel_register() can fail. In case of failure, > chan->local is freed (with free_percpu()), and chan->local is nullified. > When dma_async_device_unregister() is called (because of managed API or > intentionally by DMA controller driver), channels are unconditionally > unregistered, leading to this NULL pointer: > [ 1.318693] Unable to handle kernel NULL pointer dereference at virtual address 00000000000000d0 > [...] > [ 1.484499] Call trace: > [ 1.486930] device_del+0x40/0x394 > [ 1.490314] device_unregister+0x20/0x7c > [ 1.494220] __dma_async_device_channel_unregister+0x68/0xc0 > > Look at dma_async_device_register() function error path, channel device > unregistration is done only if chan->local is not NULL. > > Then add the same condition at the beginning of > __dma_async_device_channel_unregister() function, to avoid NULL pointer > issue whatever the API used to reach this function. > > Fixes: d2fb0a043838 ("dmaengine: break out channel registration") > Signed-off-by: Amelie Delaunay <amelie.delaunay@xxxxxxxxxxx> Reviewed-by: Dave Jiang <dave.jiang@xxxxxxxxx> > --- > drivers/dma/dmaengine.c | 3 +++ > 1 file changed, 3 insertions(+) > > diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c > index b7388ae62d7f..491b22240221 100644 > --- a/drivers/dma/dmaengine.c > +++ b/drivers/dma/dmaengine.c > @@ -1103,6 +1103,9 @@ EXPORT_SYMBOL_GPL(dma_async_device_channel_register); > static void __dma_async_device_channel_unregister(struct dma_device *device, > struct dma_chan *chan) > { > + if (chan->local == NULL) > + return; > + > WARN_ONCE(!device->device_release && chan->client_count, > "%s called while %d clients hold a reference\n", > __func__, chan->client_count);