Message ID | 20231213160452.2598073-1-amelie.delaunay@foss.st.com (mailing list archive) |
---|---|
State | Accepted |
Commit | f5c24d94512f1b288262beda4d3dcb9629222fc7 |
Headers | show |
Series | dmaengine: fix NULL pointer in channel unregistration function | expand |
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@foss.st.com> Reviewed-by: Dave Jiang <dave.jiang@intel.com> > --- > 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);
On Wed, 13 Dec 2023 17:04:52 +0100, 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 > > [...] Applied, thanks! [1/1] dmaengine: fix NULL pointer in channel unregistration function commit: f5c24d94512f1b288262beda4d3dcb9629222fc7 Best regards,
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);
__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@foss.st.com> --- drivers/dma/dmaengine.c | 3 +++ 1 file changed, 3 insertions(+)