From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752966AbcLHLhu (ORCPT ); Thu, 8 Dec 2016 06:37:50 -0500 Received: from mout.web.de ([212.227.17.12]:60339 "EHLO mout.web.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751652AbcLHLht (ORCPT ); Thu, 8 Dec 2016 06:37:49 -0500 Subject: [PATCH 4/5] staging: comedi: usbduxsigma: Split a condition check in usbduxsigma_alloc_usb_buffers() To: devel@driverdev.osuosl.org, Chris Cesare , Greg Kroah-Hartman , H Hartley Sweeten , Ian Abbott References: <8cddc37d-4529-ada4-ac21-20e09e888d0d@users.sourceforge.net> Cc: LKML , kernel-janitors@vger.kernel.org From: SF Markus Elfring Message-ID: Date: Thu, 8 Dec 2016 12:37:01 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.5.1 MIME-Version: 1.0 In-Reply-To: <8cddc37d-4529-ada4-ac21-20e09e888d0d@users.sourceforge.net> Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-Provags-ID: V03:K0:p/e0EHLw0+oq6vAYj3iArDHGpmp4btwS1sF74lbjOA3Ckm5NBh+ 5IyZaqR1Dkxdd1ek73FkjeGcbNF8CE+hpFXRG99fmY4q8aP58nfhj33d422DcrYa9YvR2q+ Dimd8rOwAp669XHoO/6cf7WTDvuiB91Dhcp9hwDoDpc3kklZfOm4vD2Rb0YpRwyPvEndU1W sYmr3kaQkGzVjQOgT+ATg== X-UI-Out-Filterresults: notjunk:1;V01:K0:H2fsgb8TYLY=:XQjTDUnDP/gbng8Fic1N7C fkNVKRQZfW5KgJjr2bF8kqx80HY3uwLUwGJdTswq+p74AGIJ65P6/UdvnNkif51zC77dLrpl2 hsCL/zxu3lLb/28B3/9uJlPfBIDmaeR0FUNkZhacwE4xo5GDPy9BzsBC2v+U7UQOHQDwGH9UC BZGBd/QuFS/9YleFIIPx+jBBAj7BQS+HsUs8RD7KQfe8DsZG39GrqO5r0UdhUf/4o8SN0f/13 9yjb9gYe1ceQkdDRtHfiAQYCkF+ko0Ac3eKn/WQwW9vRQ8PjrP9iuOjOqM3GkfWr2zsYA9AyB 7ZwnCB82beZbdMU9QThmYiwEm8F/VNGLqILEo5YMODVe63cz5LHIr+B25l+WJ62zfN/8HVNe1 68zzbgUrJ/ISMXON7LPMLXC3d18UmaBujciKmiqq8wIOhUZGsooWDr+3tRUikcXCrufAzVOZ0 QSQoURFKSOGHHDzMqsHrrg5EEjCk7Ko6IBxdIYfJGvbqpkb1wlcCoSZNO0LNuFHzvRKYfrGyh 8BRsM+v0TPrzcNfVGsLDx1MCYk7OHoOtKrhfdEbcm0Mt6C4Zm08zerDyxyBIgbnNnkO8wtjdV WU3I/suQnW+pfH2rhirXz4dIUXgJHgOipBp8xvREou6Lq0hE7rdEOavDQE11u7gl2g5w/FYw9 F8yh8J1Sf9vUM2hXIZX2gUHeX1+r25agm6Tfr8sK7je+mfqFSEqajjGs6ZAQZJssiQUCubtcA FSiNS4H3rHFwC2AmbGbZIjgQDt4YpgQU+DmZcbM2fmZbZCwl4T4ug8sdYQUPSa/kkc95WV0+6 AxgW7JR Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Markus Elfring Date: Thu, 8 Dec 2016 11:15:40 +0100 The functions "kcalloc" and "kzalloc" were called in four cases by the function "usbduxsigma_alloc_usb_buffers" without checking immediately if they succeded. This issue was detected by using the Coccinelle software. Allocated memory was also not released if one of these function calls failed. * Reduce memory allocation sizes for two function calls. * Split a condition check for memory allocation failures. * Add more exception handling. Fixes: 65989c030bbca96be45ed137f6384dbd46030d10 ("staging: comedi: usbduxsigma: factor usb buffer allocation out of (*probe)") Signed-off-by: Markus Elfring --- drivers/staging/comedi/drivers/usbduxsigma.c | 61 ++++++++++++++++++++++------ 1 file changed, 49 insertions(+), 12 deletions(-) diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index 456e9f13becb..8c04aa5339f3 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c @@ -1341,22 +1341,37 @@ static int usbduxsigma_alloc_usb_buffers(struct comedi_device *dev) struct usb_device *usb = comedi_to_usb_dev(dev); struct usbduxsigma_private *devpriv = dev->private; struct urb *urb; - int i; + int i, x; devpriv->dux_commands = kzalloc(SIZEOFDUXBUFFER, GFP_KERNEL); + if (!devpriv->dux_commands) + return -ENOMEM; + devpriv->in_buf = kzalloc(SIZEINBUF, GFP_KERNEL); + if (!devpriv->in_buf) + goto free_commands; + devpriv->insn_buf = kzalloc(SIZEINSNBUF, GFP_KERNEL); - devpriv->ai_urbs = kcalloc(devpriv->n_ai_urbs, sizeof(urb), GFP_KERNEL); - devpriv->ao_urbs = kcalloc(devpriv->n_ao_urbs, sizeof(urb), GFP_KERNEL); - if (!devpriv->dux_commands || !devpriv->in_buf || !devpriv->insn_buf || - !devpriv->ai_urbs || !devpriv->ao_urbs) - return -ENOMEM; + if (!devpriv->insn_buf) + goto free_in_buf; + + devpriv->ai_urbs = kcalloc(devpriv->n_ai_urbs, + sizeof(*devpriv->ai_urbs), + GFP_KERNEL); + if (!devpriv->ai_urbs) + goto free_insn_buf; + + devpriv->ao_urbs = kcalloc(devpriv->n_ao_urbs, + sizeof(*devpriv->ao_urbs), + GFP_KERNEL); + if (!devpriv->ao_urbs) + goto free_ai_urbs; for (i = 0; i < devpriv->n_ai_urbs; i++) { /* one frame: 1ms */ urb = usb_alloc_urb(1, GFP_KERNEL); if (!urb) - return -ENOMEM; + goto free_n_ai_urbs; devpriv->ai_urbs[i] = urb; urb->dev = usb; /* will be filled later with a pointer to the comedi-device */ @@ -1366,7 +1381,7 @@ static int usbduxsigma_alloc_usb_buffers(struct comedi_device *dev) urb->transfer_flags = URB_ISO_ASAP; urb->transfer_buffer = kzalloc(SIZEINBUF, GFP_KERNEL); if (!urb->transfer_buffer) - return -ENOMEM; + goto free_n_ai_urbs; urb->complete = usbduxsigma_ai_urb_complete; urb->number_of_packets = 1; urb->transfer_buffer_length = SIZEINBUF; @@ -1378,7 +1393,7 @@ static int usbduxsigma_alloc_usb_buffers(struct comedi_device *dev) /* one frame: 1ms */ urb = usb_alloc_urb(1, GFP_KERNEL); if (!urb) - return -ENOMEM; + goto free_n_ao_urbs; devpriv->ao_urbs[i] = urb; urb->dev = usb; /* will be filled later with a pointer to the comedi-device */ @@ -1388,7 +1403,7 @@ static int usbduxsigma_alloc_usb_buffers(struct comedi_device *dev) urb->transfer_flags = URB_ISO_ASAP; urb->transfer_buffer = kzalloc(SIZEOUTBUF, GFP_KERNEL); if (!urb->transfer_buffer) - return -ENOMEM; + goto free_n_ao_urbs; urb->complete = usbduxsigma_ao_urb_complete; urb->number_of_packets = 1; urb->transfer_buffer_length = SIZEOUTBUF; @@ -1400,16 +1415,38 @@ static int usbduxsigma_alloc_usb_buffers(struct comedi_device *dev) if (devpriv->pwm_buf_sz) { urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) - return -ENOMEM; + goto free_n_ao_urbs; devpriv->pwm_urb = urb; urb->transfer_buffer = kzalloc(devpriv->pwm_buf_sz, GFP_KERNEL); if (!urb->transfer_buffer) - return -ENOMEM; + goto free_pwm_urb; } return 0; +free_pwm_urb: + usb_free_urb(urb); +free_n_ao_urbs: + for (x = 0; x < i; ++x) { + kfree(devpriv->ao_urbs[x]->transfer_buffer); + usb_free_urb(devpriv->ao_urbs[x]); + } +free_n_ai_urbs: + for (x = 0; x < i; ++x) { + kfree(devpriv->ai_urbs[x]->transfer_buffer); + usb_free_urb(devpriv->ai_urbs[x]); + } + kfree(devpriv->ao_urbs); +free_ai_urbs: + kfree(devpriv->ai_urbs); +free_insn_buf: + kfree(devpriv->insn_buf); +free_in_buf: + kfree(devpriv->in_buf); +free_commands: + kfree(devpriv->dux_commands); + return -ENOMEM; } static void usbduxsigma_free_usb_buffers(struct comedi_device *dev) -- 2.11.0