aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIan Abbott <abbotti@mev.co.uk>2010-05-19 14:10:01 +0100
committerGreg Kroah-Hartman <gregkh@suse.de>2010-06-17 13:28:56 -0700
commit9e7f2256883c954691e5d395d471e0f125f6b30b (patch)
treed07abf22d26b8842554bab8dd1343f80e2f77fc3
parent3c17ba0743d75f9888d905ddf9f8551c7dd36493 (diff)
downloadkernel_samsung_smdk4412-9e7f2256883c954691e5d395d471e0f125f6b30b.zip
kernel_samsung_smdk4412-9e7f2256883c954691e5d395d471e0f125f6b30b.tar.gz
kernel_samsung_smdk4412-9e7f2256883c954691e5d395d471e0f125f6b30b.tar.bz2
Staging: comedi: serial2002: handle allocation failures on 'open'
The comedi device 'open' method for the serial2002 driver frees any old 'maxdata_list' and 'range_table_list' arrays belonging to a subdevice and allocates them again, but was missing checks for allocation failure. If an allocation fails, free the 'maxdata_list' and 'range_table_list' arrays for all subdevices and return an error. Signed-off-by: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/staging/comedi/drivers/serial2002.c37
1 files changed, 29 insertions, 8 deletions
diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c
index a4a99b8..880fe89 100644
--- a/drivers/staging/comedi/drivers/serial2002.c
+++ b/drivers/staging/comedi/drivers/serial2002.c
@@ -418,6 +418,7 @@ static int serial_2002_open(struct comedi_device *dev)
struct config_t chan_out_config[32];
int i;
+ result = 0;
for (i = 0; i < 32; i++) {
dig_in_config[i].kind = 0;
dig_in_config[i].bits = 0;
@@ -633,22 +634,23 @@ static int serial_2002_open(struct comedi_device *dev)
s = &dev->subdevices[i];
s->n_chan = chan;
s->maxdata = 0;
- if (s->maxdata_list) {
- kfree(s->maxdata_list);
- }
+ kfree(s->maxdata_list);
s->maxdata_list = maxdata_list =
kmalloc(sizeof(unsigned int) * s->n_chan,
GFP_KERNEL);
- if (s->range_table_list) {
- kfree(s->range_table_list);
- }
+ if (!s->maxdata_list)
+ break; /* error handled below */
+ kfree(s->range_table_list);
+ s->range_table = NULL;
+ s->range_table_list = NULL;
if (range) {
- s->range_table = 0;
s->range_table_list = range_table_list =
kmalloc(sizeof
(struct
serial2002_range_table_t) *
s->n_chan, GFP_KERNEL);
+ if (!s->range_table_list)
+ break; /* err handled below */
}
for (chan = 0, j = 0; j < 32; j++) {
if (c[j].kind == kind) {
@@ -674,7 +676,26 @@ static int serial_2002_open(struct comedi_device *dev)
}
}
}
- result = 0;
+ if (i <= 4) {
+ /* Failed to allocate maxdata_list or range_table_list
+ * for a subdevice that needed it. */
+ result = -ENOMEM;
+ for (i = 0; i <= 4; i++) {
+ struct comedi_subdevice *s;
+
+ s = &dev->subdevices[i];
+ kfree(s->maxdata_list);
+ s->maxdata_list = NULL;
+ kfree(s->range_table_list);
+ s->range_table_list = NULL;
+ }
+ }
+ if (result) {
+ if (devpriv->tty) {
+ filp_close(devpriv->tty, 0);
+ devpriv->tty = NULL;
+ }
+ }
}
return result;
}