From 725a70d8a68ef5368652c0c49631fefb361d62cf Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Fri, 28 Jun 2013 17:09:17 +0100 Subject: [PATCH] staging: comedi: ni_labpc: fix possible double-free of dma_buffer If `labpc_attach()` allocates memory for `devpriv->dma_buffer` but fails to request a DMA channel, it frees `devpriv->dma_buffer` but leaves the pointer set. Later, `labpc_detach()` frees `devpriv->dma_buffer` again, which means it has been freed twice in this case. Fix it by only setting `devpriv->dma_buffer` in `labpc_attach()` if the DMA channel was requested successfully. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_labpc.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index 3e95ac5402ca..4ff1ed0c8fa8 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -1712,13 +1712,15 @@ static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it) #ifdef CONFIG_ISA_DMA_API if (dev->irq && (dma_chan == 1 || dma_chan == 3)) { - devpriv->dma_buffer = kmalloc(dma_buffer_size, - GFP_KERNEL | GFP_DMA); - if (devpriv->dma_buffer) { + void *dma_buffer = kmalloc(dma_buffer_size, + GFP_KERNEL | GFP_DMA); + + if (dma_buffer) { ret = request_dma(dma_chan, dev->board_name); if (ret == 0) { unsigned long dma_flags; + devpriv->dma_buffer = dma_buffer; devpriv->dma_chan = dma_chan; devpriv->dma_addr = virt_to_bus(devpriv->dma_buffer); @@ -1728,7 +1730,7 @@ static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it) set_dma_mode(devpriv->dma_chan, DMA_MODE_READ); release_dma_lock(dma_flags); } else { - kfree(devpriv->dma_buffer); + kfree(dma_buffer); } } } -- 2.34.1