aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial
diff options
context:
space:
mode:
authorSteven Hardy <shardy@redhat.com>2011-04-04 12:59:55 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2011-04-13 18:53:16 -0400
commit99ab3f9e4eaec35fd2d7159c31b71f17f7e613e3 (patch)
tree59223dfce886e17092fe093e74e11a1a36453e71 /drivers/usb/serial
parent10c9ab15d6aee153968d150c05b3ee3df89673de (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.c15
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