diff options
author | Alexey Khoroshilov <khoroshilov@ispras.ru> | 2013-10-07 17:06:04 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2013-10-17 05:05:28 -0400 |
commit | 256d013a9bcc9a39b2e4b34ab19219bd054cf270 (patch) | |
tree | b16380050dbe612e9c3a60e9f5bd5d6b006faaaf /drivers/media/usb/cx231xx | |
parent | 1f61d41585f8a7a52d67fd3d6aa4aa6db75f360c (diff) |
[media] cx231xx: fix double free and leaks on failure path in cx231xx_usb_probe()
There are numerous issues in error handling code of cx231xx initialization.
Double free (when cx231xx_init_dev() calls kfree(dev) via cx231xx_release_resources()
and then cx231xx_usb_probe() does the same) and memory leaks
(e.g. usb_get_dev() before (ifnum != 1) check in cx231xx_usb_probe())
are just a few of them.
The patch fixes the issues in cx231xx_usb_probe() and cx231xx_init_dev()
by moving usb_get_dev(interface_to_usbdev(interface)) below in code and
implementing proper error handling.
Found by Linux Driver Verification project (linuxtesting.org).
Signed-off-by: Alexey Khoroshilov <khoroshilov@ispras.ru>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Diffstat (limited to 'drivers/media/usb/cx231xx')
-rw-r--r-- | drivers/media/usb/cx231xx/cx231xx-cards.c | 110 |
1 files changed, 57 insertions, 53 deletions
diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c index a384f80f595e..e9d017bea377 100644 --- a/drivers/media/usb/cx231xx/cx231xx-cards.c +++ b/drivers/media/usb/cx231xx/cx231xx-cards.c | |||
@@ -978,7 +978,6 @@ static int cx231xx_init_dev(struct cx231xx *dev, struct usb_device *udev, | |||
978 | int minor) | 978 | int minor) |
979 | { | 979 | { |
980 | int retval = -ENOMEM; | 980 | int retval = -ENOMEM; |
981 | int errCode; | ||
982 | unsigned int maxh, maxw; | 981 | unsigned int maxh, maxw; |
983 | 982 | ||
984 | dev->udev = udev; | 983 | dev->udev = udev; |
@@ -1014,8 +1013,8 @@ static int cx231xx_init_dev(struct cx231xx *dev, struct usb_device *udev, | |||
1014 | /* Cx231xx pre card setup */ | 1013 | /* Cx231xx pre card setup */ |
1015 | cx231xx_pre_card_setup(dev); | 1014 | cx231xx_pre_card_setup(dev); |
1016 | 1015 | ||
1017 | errCode = cx231xx_config(dev); | 1016 | retval = cx231xx_config(dev); |
1018 | if (errCode) { | 1017 | if (retval) { |
1019 | cx231xx_errdev("error configuring device\n"); | 1018 | cx231xx_errdev("error configuring device\n"); |
1020 | return -ENOMEM; | 1019 | return -ENOMEM; |
1021 | } | 1020 | } |
@@ -1024,12 +1023,11 @@ static int cx231xx_init_dev(struct cx231xx *dev, struct usb_device *udev, | |||
1024 | dev->norm = dev->board.norm; | 1023 | dev->norm = dev->board.norm; |
1025 | 1024 | ||
1026 | /* register i2c bus */ | 1025 | /* register i2c bus */ |
1027 | errCode = cx231xx_dev_init(dev); | 1026 | retval = cx231xx_dev_init(dev); |
1028 | if (errCode < 0) { | 1027 | if (retval) { |
1029 | cx231xx_dev_uninit(dev); | ||
1030 | cx231xx_errdev("%s: cx231xx_i2c_register - errCode [%d]!\n", | 1028 | cx231xx_errdev("%s: cx231xx_i2c_register - errCode [%d]!\n", |
1031 | __func__, errCode); | 1029 | __func__, retval); |
1032 | return errCode; | 1030 | goto err_dev_init; |
1033 | } | 1031 | } |
1034 | 1032 | ||
1035 | /* Do board specific init */ | 1033 | /* Do board specific init */ |
@@ -1047,11 +1045,11 @@ static int cx231xx_init_dev(struct cx231xx *dev, struct usb_device *udev, | |||
1047 | dev->interlaced = 0; | 1045 | dev->interlaced = 0; |
1048 | dev->video_input = 0; | 1046 | dev->video_input = 0; |
1049 | 1047 | ||
1050 | errCode = cx231xx_config(dev); | 1048 | retval = cx231xx_config(dev); |
1051 | if (errCode < 0) { | 1049 | if (retval) { |
1052 | cx231xx_errdev("%s: cx231xx_config - errCode [%d]!\n", | 1050 | cx231xx_errdev("%s: cx231xx_config - errCode [%d]!\n", |
1053 | __func__, errCode); | 1051 | __func__, retval); |
1054 | return errCode; | 1052 | goto err_dev_init; |
1055 | } | 1053 | } |
1056 | 1054 | ||
1057 | /* init video dma queues */ | 1055 | /* init video dma queues */ |
@@ -1075,9 +1073,9 @@ static int cx231xx_init_dev(struct cx231xx *dev, struct usb_device *udev, | |||
1075 | } | 1073 | } |
1076 | 1074 | ||
1077 | retval = cx231xx_register_analog_devices(dev); | 1075 | retval = cx231xx_register_analog_devices(dev); |
1078 | if (retval < 0) { | 1076 | if (retval) { |
1079 | cx231xx_release_resources(dev); | 1077 | cx231xx_release_analog_resources(dev); |
1080 | return retval; | 1078 | goto err_analog; |
1081 | } | 1079 | } |
1082 | 1080 | ||
1083 | cx231xx_ir_init(dev); | 1081 | cx231xx_ir_init(dev); |
@@ -1085,6 +1083,11 @@ static int cx231xx_init_dev(struct cx231xx *dev, struct usb_device *udev, | |||
1085 | cx231xx_init_extension(dev); | 1083 | cx231xx_init_extension(dev); |
1086 | 1084 | ||
1087 | return 0; | 1085 | return 0; |
1086 | err_analog: | ||
1087 | cx231xx_remove_from_devlist(dev); | ||
1088 | err_dev_init: | ||
1089 | cx231xx_dev_uninit(dev); | ||
1090 | return retval; | ||
1088 | } | 1091 | } |
1089 | 1092 | ||
1090 | #if defined(CONFIG_MODULES) && defined(MODULE) | 1093 | #if defined(CONFIG_MODULES) && defined(MODULE) |
@@ -1132,7 +1135,6 @@ static int cx231xx_usb_probe(struct usb_interface *interface, | |||
1132 | char *speed; | 1135 | char *speed; |
1133 | struct usb_interface_assoc_descriptor *assoc_desc; | 1136 | struct usb_interface_assoc_descriptor *assoc_desc; |
1134 | 1137 | ||
1135 | udev = usb_get_dev(interface_to_usbdev(interface)); | ||
1136 | ifnum = interface->altsetting[0].desc.bInterfaceNumber; | 1138 | ifnum = interface->altsetting[0].desc.bInterfaceNumber; |
1137 | 1139 | ||
1138 | /* | 1140 | /* |
@@ -1161,6 +1163,8 @@ static int cx231xx_usb_probe(struct usb_interface *interface, | |||
1161 | return -ENOMEM; | 1163 | return -ENOMEM; |
1162 | } | 1164 | } |
1163 | 1165 | ||
1166 | udev = usb_get_dev(interface_to_usbdev(interface)); | ||
1167 | |||
1164 | snprintf(dev->name, 29, "cx231xx #%d", nr); | 1168 | snprintf(dev->name, 29, "cx231xx #%d", nr); |
1165 | dev->devno = nr; | 1169 | dev->devno = nr; |
1166 | dev->model = id->driver_info; | 1170 | dev->model = id->driver_info; |
@@ -1223,10 +1227,8 @@ static int cx231xx_usb_probe(struct usb_interface *interface, | |||
1223 | if (assoc_desc->bFirstInterface != ifnum) { | 1227 | if (assoc_desc->bFirstInterface != ifnum) { |
1224 | cx231xx_err(DRIVER_NAME ": Not found " | 1228 | cx231xx_err(DRIVER_NAME ": Not found " |
1225 | "matching IAD interface\n"); | 1229 | "matching IAD interface\n"); |
1226 | clear_bit(dev->devno, &cx231xx_devused); | 1230 | retval = -ENODEV; |
1227 | kfree(dev); | 1231 | goto err_if; |
1228 | dev = NULL; | ||
1229 | return -ENODEV; | ||
1230 | } | 1232 | } |
1231 | 1233 | ||
1232 | cx231xx_info("registering interface %d\n", ifnum); | 1234 | cx231xx_info("registering interface %d\n", ifnum); |
@@ -1242,22 +1244,13 @@ static int cx231xx_usb_probe(struct usb_interface *interface, | |||
1242 | retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev); | 1244 | retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev); |
1243 | if (retval) { | 1245 | if (retval) { |
1244 | cx231xx_errdev("v4l2_device_register failed\n"); | 1246 | cx231xx_errdev("v4l2_device_register failed\n"); |
1245 | clear_bit(dev->devno, &cx231xx_devused); | 1247 | retval = -EIO; |
1246 | kfree(dev); | 1248 | goto err_v4l2; |
1247 | dev = NULL; | ||
1248 | return -EIO; | ||
1249 | } | 1249 | } |
1250 | /* allocate device struct */ | 1250 | /* allocate device struct */ |
1251 | retval = cx231xx_init_dev(dev, udev, nr); | 1251 | retval = cx231xx_init_dev(dev, udev, nr); |
1252 | if (retval) { | 1252 | if (retval) |
1253 | clear_bit(dev->devno, &cx231xx_devused); | 1253 | goto err_init; |
1254 | v4l2_device_unregister(&dev->v4l2_dev); | ||
1255 | kfree(dev); | ||
1256 | dev = NULL; | ||
1257 | usb_set_intfdata(interface, NULL); | ||
1258 | |||
1259 | return retval; | ||
1260 | } | ||
1261 | 1254 | ||
1262 | /* compute alternate max packet sizes for video */ | 1255 | /* compute alternate max packet sizes for video */ |
1263 | uif = udev->actconfig->interface[dev->current_pcb_config. | 1256 | uif = udev->actconfig->interface[dev->current_pcb_config. |
@@ -1275,11 +1268,8 @@ static int cx231xx_usb_probe(struct usb_interface *interface, | |||
1275 | 1268 | ||
1276 | if (dev->video_mode.alt_max_pkt_size == NULL) { | 1269 | if (dev->video_mode.alt_max_pkt_size == NULL) { |
1277 | cx231xx_errdev("out of memory!\n"); | 1270 | cx231xx_errdev("out of memory!\n"); |
1278 | clear_bit(dev->devno, &cx231xx_devused); | 1271 | retval = -ENOMEM; |
1279 | v4l2_device_unregister(&dev->v4l2_dev); | 1272 | goto err_video_alt; |
1280 | kfree(dev); | ||
1281 | dev = NULL; | ||
1282 | return -ENOMEM; | ||
1283 | } | 1273 | } |
1284 | 1274 | ||
1285 | for (i = 0; i < dev->video_mode.num_alt; i++) { | 1275 | for (i = 0; i < dev->video_mode.num_alt; i++) { |
@@ -1309,11 +1299,8 @@ static int cx231xx_usb_probe(struct usb_interface *interface, | |||
1309 | 1299 | ||
1310 | if (dev->vbi_mode.alt_max_pkt_size == NULL) { | 1300 | if (dev->vbi_mode.alt_max_pkt_size == NULL) { |
1311 | cx231xx_errdev("out of memory!\n"); | 1301 | cx231xx_errdev("out of memory!\n"); |
1312 | clear_bit(dev->devno, &cx231xx_devused); | 1302 | retval = -ENOMEM; |
1313 | v4l2_device_unregister(&dev->v4l2_dev); | 1303 | goto err_vbi_alt; |
1314 | kfree(dev); | ||
1315 | dev = NULL; | ||
1316 | return -ENOMEM; | ||
1317 | } | 1304 | } |
1318 | 1305 | ||
1319 | for (i = 0; i < dev->vbi_mode.num_alt; i++) { | 1306 | for (i = 0; i < dev->vbi_mode.num_alt; i++) { |
@@ -1344,11 +1331,8 @@ static int cx231xx_usb_probe(struct usb_interface *interface, | |||
1344 | 1331 | ||
1345 | if (dev->sliced_cc_mode.alt_max_pkt_size == NULL) { | 1332 | if (dev->sliced_cc_mode.alt_max_pkt_size == NULL) { |
1346 | cx231xx_errdev("out of memory!\n"); | 1333 | cx231xx_errdev("out of memory!\n"); |
1347 | clear_bit(dev->devno, &cx231xx_devused); | 1334 | retval = -ENOMEM; |
1348 | v4l2_device_unregister(&dev->v4l2_dev); | 1335 | goto err_sliced_cc_alt; |
1349 | kfree(dev); | ||
1350 | dev = NULL; | ||
1351 | return -ENOMEM; | ||
1352 | } | 1336 | } |
1353 | 1337 | ||
1354 | for (i = 0; i < dev->sliced_cc_mode.num_alt; i++) { | 1338 | for (i = 0; i < dev->sliced_cc_mode.num_alt; i++) { |
@@ -1380,11 +1364,8 @@ static int cx231xx_usb_probe(struct usb_interface *interface, | |||
1380 | 1364 | ||
1381 | if (dev->ts1_mode.alt_max_pkt_size == NULL) { | 1365 | if (dev->ts1_mode.alt_max_pkt_size == NULL) { |
1382 | cx231xx_errdev("out of memory!\n"); | 1366 | cx231xx_errdev("out of memory!\n"); |
1383 | clear_bit(dev->devno, &cx231xx_devused); | 1367 | retval = -ENOMEM; |
1384 | v4l2_device_unregister(&dev->v4l2_dev); | 1368 | goto err_ts1_alt; |
1385 | kfree(dev); | ||
1386 | dev = NULL; | ||
1387 | return -ENOMEM; | ||
1388 | } | 1369 | } |
1389 | 1370 | ||
1390 | for (i = 0; i < dev->ts1_mode.num_alt; i++) { | 1371 | for (i = 0; i < dev->ts1_mode.num_alt; i++) { |
@@ -1411,6 +1392,29 @@ static int cx231xx_usb_probe(struct usb_interface *interface, | |||
1411 | request_modules(dev); | 1392 | request_modules(dev); |
1412 | 1393 | ||
1413 | return 0; | 1394 | return 0; |
1395 | err_ts1_alt: | ||
1396 | kfree(dev->sliced_cc_mode.alt_max_pkt_size); | ||
1397 | err_sliced_cc_alt: | ||
1398 | kfree(dev->vbi_mode.alt_max_pkt_size); | ||
1399 | err_vbi_alt: | ||
1400 | kfree(dev->video_mode.alt_max_pkt_size); | ||
1401 | err_video_alt: | ||
1402 | /* cx231xx_uninit_dev: */ | ||
1403 | cx231xx_close_extension(dev); | ||
1404 | cx231xx_ir_exit(dev); | ||
1405 | cx231xx_release_analog_resources(dev); | ||
1406 | cx231xx_417_unregister(dev); | ||
1407 | cx231xx_remove_from_devlist(dev); | ||
1408 | cx231xx_dev_uninit(dev); | ||
1409 | err_init: | ||
1410 | v4l2_device_unregister(&dev->v4l2_dev); | ||
1411 | err_v4l2: | ||
1412 | usb_set_intfdata(interface, NULL); | ||
1413 | err_if: | ||
1414 | usb_put_dev(udev); | ||
1415 | kfree(dev); | ||
1416 | clear_bit(dev->devno, &cx231xx_devused); | ||
1417 | return retval; | ||
1414 | } | 1418 | } |
1415 | 1419 | ||
1416 | /* | 1420 | /* |