| From 98f5f932254b88ce828bc8e4d1642d14e5854caa Mon Sep 17 00:00:00 2001 |
| From: Richard Genoud <richard.genoud@gmail.com> |
| Date: Tue, 27 Nov 2018 17:06:34 +0100 |
| Subject: dmaengine: at_hdmac: fix memory leak in at_dma_xlate() |
| |
| From: Richard Genoud <richard.genoud@gmail.com> |
| |
| commit 98f5f932254b88ce828bc8e4d1642d14e5854caa upstream. |
| |
| The leak was found when opening/closing a serial port a great number of |
| time, increasing kmalloc-32 in slabinfo. |
| |
| Each time the port was opened, dma_request_slave_channel() was called. |
| Then, in at_dma_xlate(), atslave was allocated with devm_kzalloc() and |
| never freed. (Well, it was free at module unload, but that's not what we |
| want). |
| So, here, kzalloc is more suited for the job since it has to be freed in |
| atc_free_chan_resources(). |
| |
| Cc: stable@vger.kernel.org |
| Fixes: bbe89c8e3d59 ("at_hdmac: move to generic DMA binding") |
| Reported-by: Mario Forner <m.forner@be4energy.com> |
| Suggested-by: Alexandre Belloni <alexandre.belloni@bootlin.com> |
| Acked-by: Alexandre Belloni <alexandre.belloni@bootlin.com> |
| Acked-by: Ludovic Desroches <ludovic.desroches@microchip.com> |
| Signed-off-by: Richard Genoud <richard.genoud@gmail.com> |
| Signed-off-by: Vinod Koul <vkoul@kernel.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/dma/at_hdmac.c | 8 +++++++- |
| 1 file changed, 7 insertions(+), 1 deletion(-) |
| |
| --- a/drivers/dma/at_hdmac.c |
| +++ b/drivers/dma/at_hdmac.c |
| @@ -1232,6 +1232,12 @@ static void atc_free_chan_resources(stru |
| atchan->status = 0; |
| atchan->remain_desc = 0; |
| |
| + /* |
| + * Free atslave allocated in at_dma_xlate() |
| + */ |
| + kfree(chan->private); |
| + chan->private = NULL; |
| + |
| dev_vdbg(chan2dev(chan), "free_chan_resources: done\n"); |
| } |
| |
| @@ -1266,7 +1272,7 @@ static struct dma_chan *at_dma_xlate(str |
| dma_cap_zero(mask); |
| dma_cap_set(DMA_SLAVE, mask); |
| |
| - atslave = devm_kzalloc(&dmac_pdev->dev, sizeof(*atslave), GFP_KERNEL); |
| + atslave = kzalloc(sizeof(*atslave), GFP_KERNEL); |
| if (!atslave) |
| return NULL; |
| |