Message ID | 20210331014458.3944-1-lyl2019@mail.ustc.edu.cn (mailing list archive) |
---|---|
State | Accepted |
Commit | ea45b6008f8095db0cc09ad6e03c7785c2986197 |
Headers | show |
Series | [v2] dma: Fix a double free in dma_async_device_register | expand |
On 3/30/2021 6:44 PM, Lv Yunlong wrote: > In the first list_for_each_entry() macro of dma_async_device_register, > it gets the chan from list and calls __dma_async_device_channel_register > (..,chan). We can see that chan->local is allocated by alloc_percpu() and > it is freed chan->local by free_percpu(chan->local) when > __dma_async_device_channel_register() failed. > > But after __dma_async_device_channel_register() failed, the caller will > goto err_out and freed the chan->local in the second time by free_percpu(). > > The cause of this problem is forget to set chan->local to NULL when > chan->local was freed in __dma_async_device_channel_register(). My > patch sets chan->local to NULL when the callee failed to avoid double free. > > Fixes: d2fb0a0438384 ("dmaengine: break out channel registration") > Signed-off-by: Lv Yunlong <lyl2019@mail.ustc.edu.cn> Reviewed-by: Dave Jiang <dave.jiang@intel.com> > --- > drivers/dma/dmaengine.c | 1 + > 1 file changed, 1 insertion(+) > > diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c > index fe6a460c4373..af3ee288bc11 100644 > --- a/drivers/dma/dmaengine.c > +++ b/drivers/dma/dmaengine.c > @@ -1086,6 +1086,7 @@ static int __dma_async_device_channel_register(struct dma_device *device, > kfree(chan->dev); > err_free_local: > free_percpu(chan->local); > + chan->local = NULL; > return rc; > } >
On 30-03-21, 18:44, Lv Yunlong wrote: > In the first list_for_each_entry() macro of dma_async_device_register, > it gets the chan from list and calls __dma_async_device_channel_register > (..,chan). We can see that chan->local is allocated by alloc_percpu() and > it is freed chan->local by free_percpu(chan->local) when > __dma_async_device_channel_register() failed. > > But after __dma_async_device_channel_register() failed, the caller will > goto err_out and freed the chan->local in the second time by free_percpu(). > > The cause of this problem is forget to set chan->local to NULL when > chan->local was freed in __dma_async_device_channel_register(). My > patch sets chan->local to NULL when the callee failed to avoid double free. Applied after fixing subsystem name, thanks
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index fe6a460c4373..af3ee288bc11 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -1086,6 +1086,7 @@ static int __dma_async_device_channel_register(struct dma_device *device, kfree(chan->dev); err_free_local: free_percpu(chan->local); + chan->local = NULL; return rc; }
In the first list_for_each_entry() macro of dma_async_device_register, it gets the chan from list and calls __dma_async_device_channel_register (..,chan). We can see that chan->local is allocated by alloc_percpu() and it is freed chan->local by free_percpu(chan->local) when __dma_async_device_channel_register() failed. But after __dma_async_device_channel_register() failed, the caller will goto err_out and freed the chan->local in the second time by free_percpu(). The cause of this problem is forget to set chan->local to NULL when chan->local was freed in __dma_async_device_channel_register(). My patch sets chan->local to NULL when the callee failed to avoid double free. Fixes: d2fb0a0438384 ("dmaengine: break out channel registration") Signed-off-by: Lv Yunlong <lyl2019@mail.ustc.edu.cn> --- drivers/dma/dmaengine.c | 1 + 1 file changed, 1 insertion(+)