Commit 9e7f2256 authored by Ian Abbott's avatar Ian Abbott Committed by Greg Kroah-Hartman

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: default avatarIan Abbott <abbotti@mev.co.uk>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 3c17ba07
...@@ -418,6 +418,7 @@ static int serial_2002_open(struct comedi_device *dev) ...@@ -418,6 +418,7 @@ static int serial_2002_open(struct comedi_device *dev)
struct config_t chan_out_config[32]; struct config_t chan_out_config[32];
int i; int i;
result = 0;
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
dig_in_config[i].kind = 0; dig_in_config[i].kind = 0;
dig_in_config[i].bits = 0; dig_in_config[i].bits = 0;
...@@ -633,22 +634,23 @@ static int serial_2002_open(struct comedi_device *dev) ...@@ -633,22 +634,23 @@ static int serial_2002_open(struct comedi_device *dev)
s = &dev->subdevices[i]; s = &dev->subdevices[i];
s->n_chan = chan; s->n_chan = chan;
s->maxdata = 0; s->maxdata = 0;
if (s->maxdata_list) {
kfree(s->maxdata_list); kfree(s->maxdata_list);
}
s->maxdata_list = maxdata_list = s->maxdata_list = maxdata_list =
kmalloc(sizeof(unsigned int) * s->n_chan, kmalloc(sizeof(unsigned int) * s->n_chan,
GFP_KERNEL); GFP_KERNEL);
if (s->range_table_list) { if (!s->maxdata_list)
break; /* error handled below */
kfree(s->range_table_list); kfree(s->range_table_list);
} s->range_table = NULL;
s->range_table_list = NULL;
if (range) { if (range) {
s->range_table = 0;
s->range_table_list = range_table_list = s->range_table_list = range_table_list =
kmalloc(sizeof kmalloc(sizeof
(struct (struct
serial2002_range_table_t) * serial2002_range_table_t) *
s->n_chan, GFP_KERNEL); s->n_chan, GFP_KERNEL);
if (!s->range_table_list)
break; /* err handled below */
} }
for (chan = 0, j = 0; j < 32; j++) { for (chan = 0, j = 0; j < 32; j++) {
if (c[j].kind == kind) { if (c[j].kind == kind) {
...@@ -674,7 +676,26 @@ static int serial_2002_open(struct comedi_device *dev) ...@@ -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; return result;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment