diff options
author | Steven Hardy <shardy@redhat.com> | 2011-04-04 12:59:55 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-04-13 18:53:16 -0400 |
commit | 99ab3f9e4eaec35fd2d7159c31b71f17f7e613e3 (patch) | |
tree | 59223dfce886e17092fe093e74e11a1a36453e71 /drivers/usb/serial | |
parent | 10c9ab15d6aee153968d150c05b3ee3df89673de (diff) |
usb: qcserial avoid pointing to freed memory
Rework the qcprobe logic such that serial->private is not set when
qcprobe exits with -ENODEV, otherwise serial->private will point to freed
memory on -ENODEV
Signed-off-by: Steven Hardy <shardy@redhat.com>
Cc: stable <stable@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/serial')
-rw-r--r-- | drivers/usb/serial/qcserial.c | 15 |
1 files changed, 9 insertions, 6 deletions
diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index 6e3b933457f4..cd638648479a 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c | |||
@@ -111,7 +111,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) | |||
111 | ifnum = intf->desc.bInterfaceNumber; | 111 | ifnum = intf->desc.bInterfaceNumber; |
112 | dbg("This Interface = %d", ifnum); | 112 | dbg("This Interface = %d", ifnum); |
113 | 113 | ||
114 | data = serial->private = kzalloc(sizeof(struct usb_wwan_intf_private), | 114 | data = kzalloc(sizeof(struct usb_wwan_intf_private), |
115 | GFP_KERNEL); | 115 | GFP_KERNEL); |
116 | if (!data) | 116 | if (!data) |
117 | return -ENOMEM; | 117 | return -ENOMEM; |
@@ -134,8 +134,10 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) | |||
134 | usb_endpoint_is_bulk_out(&intf->endpoint[1].desc)) { | 134 | usb_endpoint_is_bulk_out(&intf->endpoint[1].desc)) { |
135 | dbg("QDL port found"); | 135 | dbg("QDL port found"); |
136 | 136 | ||
137 | if (serial->interface->num_altsetting == 1) | 137 | if (serial->interface->num_altsetting == 1) { |
138 | return 0; | 138 | retval = 0; /* Success */ |
139 | break; | ||
140 | } | ||
139 | 141 | ||
140 | retval = usb_set_interface(serial->dev, ifnum, 1); | 142 | retval = usb_set_interface(serial->dev, ifnum, 1); |
141 | if (retval < 0) { | 143 | if (retval < 0) { |
@@ -145,7 +147,6 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) | |||
145 | retval = -ENODEV; | 147 | retval = -ENODEV; |
146 | kfree(data); | 148 | kfree(data); |
147 | } | 149 | } |
148 | return retval; | ||
149 | } | 150 | } |
150 | break; | 151 | break; |
151 | 152 | ||
@@ -177,7 +178,6 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) | |||
177 | retval = -ENODEV; | 178 | retval = -ENODEV; |
178 | kfree(data); | 179 | kfree(data); |
179 | } | 180 | } |
180 | return retval; | ||
181 | } else if (ifnum==3) { | 181 | } else if (ifnum==3) { |
182 | /* | 182 | /* |
183 | * NMEA (serial line 9600 8N1) | 183 | * NMEA (serial line 9600 8N1) |
@@ -199,9 +199,12 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) | |||
199 | dev_err(&serial->dev->dev, | 199 | dev_err(&serial->dev->dev, |
200 | "unknown number of interfaces: %d\n", nintf); | 200 | "unknown number of interfaces: %d\n", nintf); |
201 | kfree(data); | 201 | kfree(data); |
202 | return -ENODEV; | 202 | retval = -ENODEV; |
203 | } | 203 | } |
204 | 204 | ||
205 | /* Set serial->private if not returning -ENODEV */ | ||
206 | if (retval != -ENODEV) | ||
207 | usb_set_serial_data(serial, data); | ||
205 | return retval; | 208 | return retval; |
206 | } | 209 | } |
207 | 210 | ||