summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Abbott <abbotti@mev.co.uk>2013-06-28 16:09:17 (GMT)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-07-23 21:27:50 (GMT)
commit725a70d8a68ef5368652c0c49631fefb361d62cf (patch)
tree71dfe83245b4881ae61c9c59edc027e9c73262f4
parentc383e2d6dacf0b6fdd40fbaf044e235cac54a20f (diff)
downloadlinux-fsl-qoriq-725a70d8a68ef5368652c0c49631fefb361d62cf.tar.xz
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 <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/staging/comedi/drivers/ni_labpc.c10
1 files changed, 6 insertions, 4 deletions
diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c
index 3e95ac5..4ff1ed0 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);
}
}
}