Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

USB: keyspan: fix NULL-pointer dereferences and memory leaks

Fix NULL-pointer dereference at release by moving port data allocation
and deallocation to port_probe and port_remove.

Fix NULL-pointer dereference at disconnect by stopping port urbs at
port_remove.

Since commit 0998d0631001288 (device-core: Ensure drvdata = NULL when no
driver is bound) the port private data is no longer accessible at
disconnect or release.

Note that this patch also fixes port and interface-data memory leaks in
the error path of attach should port initialisation fail for any port.

Compile-only tested.

Cc: <stable@vger.kernel.org>
Signed-off-by: Johan Hovold <jhovold@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Johan Hovold and committed by
Greg Kroah-Hartman
f79b2d0f 5260e458

+99 -96
+91 -96
drivers/usb/serial/keyspan.c
··· 1374 1374 data in device_details */ 1375 1375 static void keyspan_setup_urbs(struct usb_serial *serial) 1376 1376 { 1377 - int i, j; 1378 1377 struct keyspan_serial_private *s_priv; 1379 1378 const struct keyspan_device_details *d_details; 1380 - struct usb_serial_port *port; 1381 - struct keyspan_port_private *p_priv; 1382 1379 struct callbacks *cback; 1383 - int endp; 1384 1380 1385 1381 s_priv = usb_get_serial_data(serial); 1386 1382 d_details = s_priv->device_details; ··· 1400 1404 (serial, d_details->glocont_endpoint, USB_DIR_OUT, 1401 1405 serial, s_priv->glocont_buf, GLOCONT_BUFLEN, 1402 1406 cback->glocont_callback); 1403 - 1404 - /* Setup endpoints for each port specific thing */ 1405 - for (i = 0; i < d_details->num_ports; i++) { 1406 - port = serial->port[i]; 1407 - p_priv = usb_get_serial_port_data(port); 1408 - 1409 - /* Do indat endpoints first, once for each flip */ 1410 - endp = d_details->indat_endpoints[i]; 1411 - for (j = 0; j <= d_details->indat_endp_flip; ++j, ++endp) { 1412 - p_priv->in_urbs[j] = keyspan_setup_urb 1413 - (serial, endp, USB_DIR_IN, port, 1414 - p_priv->in_buffer[j], 64, 1415 - cback->indat_callback); 1416 - } 1417 - for (; j < 2; ++j) 1418 - p_priv->in_urbs[j] = NULL; 1419 - 1420 - /* outdat endpoints also have flip */ 1421 - endp = d_details->outdat_endpoints[i]; 1422 - for (j = 0; j <= d_details->outdat_endp_flip; ++j, ++endp) { 1423 - p_priv->out_urbs[j] = keyspan_setup_urb 1424 - (serial, endp, USB_DIR_OUT, port, 1425 - p_priv->out_buffer[j], 64, 1426 - cback->outdat_callback); 1427 - } 1428 - for (; j < 2; ++j) 1429 - p_priv->out_urbs[j] = NULL; 1430 - 1431 - /* inack endpoint */ 1432 - p_priv->inack_urb = keyspan_setup_urb 1433 - (serial, d_details->inack_endpoints[i], USB_DIR_IN, 1434 - port, p_priv->inack_buffer, 1, cback->inack_callback); 1435 - 1436 - /* outcont endpoint */ 1437 - p_priv->outcont_urb = keyspan_setup_urb 1438 - (serial, d_details->outcont_endpoints[i], USB_DIR_OUT, 1439 - port, p_priv->outcont_buffer, 64, 1440 - cback->outcont_callback); 1441 - } 1442 1407 } 1443 1408 1444 1409 /* usa19 function doesn't require prescaler */ ··· 2364 2407 static int keyspan_startup(struct usb_serial *serial) 2365 2408 { 2366 2409 int i, err; 2367 - struct usb_serial_port *port; 2368 2410 struct keyspan_serial_private *s_priv; 2369 - struct keyspan_port_private *p_priv; 2370 2411 const struct keyspan_device_details *d_details; 2371 2412 2372 2413 for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i) ··· 2387 2432 s_priv->device_details = d_details; 2388 2433 usb_set_serial_data(serial, s_priv); 2389 2434 2390 - /* Now setup per port private data */ 2391 - for (i = 0; i < serial->num_ports; i++) { 2392 - port = serial->port[i]; 2393 - p_priv = kzalloc(sizeof(struct keyspan_port_private), 2394 - GFP_KERNEL); 2395 - if (!p_priv) { 2396 - dev_dbg(&port->dev, "%s - kmalloc for keyspan_port_private (%d) failed!.\n", __func__, i); 2397 - return 1; 2398 - } 2399 - p_priv->device_details = d_details; 2400 - usb_set_serial_port_data(port, p_priv); 2401 - } 2402 - 2403 2435 keyspan_setup_urbs(serial); 2404 2436 2405 2437 if (s_priv->instat_urb != NULL) { ··· 2405 2463 2406 2464 static void keyspan_disconnect(struct usb_serial *serial) 2407 2465 { 2408 - int i, j; 2409 - struct usb_serial_port *port; 2410 - struct keyspan_serial_private *s_priv; 2411 - struct keyspan_port_private *p_priv; 2466 + struct keyspan_serial_private *s_priv; 2412 2467 2413 2468 s_priv = usb_get_serial_data(serial); 2414 2469 2415 - /* Stop reading/writing urbs */ 2416 2470 stop_urb(s_priv->instat_urb); 2417 2471 stop_urb(s_priv->glocont_urb); 2418 2472 stop_urb(s_priv->indat_urb); 2419 - for (i = 0; i < serial->num_ports; ++i) { 2420 - port = serial->port[i]; 2421 - p_priv = usb_get_serial_port_data(port); 2422 - stop_urb(p_priv->inack_urb); 2423 - stop_urb(p_priv->outcont_urb); 2424 - for (j = 0; j < 2; j++) { 2425 - stop_urb(p_priv->in_urbs[j]); 2426 - stop_urb(p_priv->out_urbs[j]); 2427 - } 2428 - } 2429 - 2430 - /* Now free them */ 2431 - usb_free_urb(s_priv->instat_urb); 2432 - usb_free_urb(s_priv->indat_urb); 2433 - usb_free_urb(s_priv->glocont_urb); 2434 - for (i = 0; i < serial->num_ports; ++i) { 2435 - port = serial->port[i]; 2436 - p_priv = usb_get_serial_port_data(port); 2437 - usb_free_urb(p_priv->inack_urb); 2438 - usb_free_urb(p_priv->outcont_urb); 2439 - for (j = 0; j < 2; j++) { 2440 - usb_free_urb(p_priv->in_urbs[j]); 2441 - usb_free_urb(p_priv->out_urbs[j]); 2442 - } 2443 - } 2444 2473 } 2445 2474 2446 2475 static void keyspan_release(struct usb_serial *serial) 2447 2476 { 2448 - int i; 2449 - struct usb_serial_port *port; 2450 - struct keyspan_serial_private *s_priv; 2477 + struct keyspan_serial_private *s_priv; 2451 2478 2452 2479 s_priv = usb_get_serial_data(serial); 2453 2480 2454 - kfree(s_priv); 2481 + usb_free_urb(s_priv->instat_urb); 2482 + usb_free_urb(s_priv->indat_urb); 2483 + usb_free_urb(s_priv->glocont_urb); 2455 2484 2456 - /* Now free per port private data */ 2457 - for (i = 0; i < serial->num_ports; i++) { 2458 - port = serial->port[i]; 2459 - kfree(usb_get_serial_port_data(port)); 2485 + kfree(s_priv); 2486 + } 2487 + 2488 + static int keyspan_port_probe(struct usb_serial_port *port) 2489 + { 2490 + struct usb_serial *serial = port->serial; 2491 + struct keyspan_port_private *s_priv; 2492 + struct keyspan_port_private *p_priv; 2493 + const struct keyspan_device_details *d_details; 2494 + struct callbacks *cback; 2495 + int endp; 2496 + int port_num; 2497 + int i; 2498 + 2499 + s_priv = usb_get_serial_data(serial); 2500 + d_details = s_priv->device_details; 2501 + 2502 + p_priv = kzalloc(sizeof(*p_priv), GFP_KERNEL); 2503 + if (!p_priv) 2504 + return -ENOMEM; 2505 + 2506 + s_priv = usb_get_serial_data(port->serial); 2507 + p_priv->device_details = d_details; 2508 + 2509 + /* Setup values for the various callback routines */ 2510 + cback = &keyspan_callbacks[d_details->msg_format]; 2511 + 2512 + port_num = port->number - port->serial->minor; 2513 + 2514 + /* Do indat endpoints first, once for each flip */ 2515 + endp = d_details->indat_endpoints[port_num]; 2516 + for (i = 0; i <= d_details->indat_endp_flip; ++i, ++endp) { 2517 + p_priv->in_urbs[i] = keyspan_setup_urb(serial, endp, 2518 + USB_DIR_IN, port, 2519 + p_priv->in_buffer[i], 64, 2520 + cback->indat_callback); 2460 2521 } 2522 + /* outdat endpoints also have flip */ 2523 + endp = d_details->outdat_endpoints[port_num]; 2524 + for (i = 0; i <= d_details->outdat_endp_flip; ++i, ++endp) { 2525 + p_priv->out_urbs[i] = keyspan_setup_urb(serial, endp, 2526 + USB_DIR_OUT, port, 2527 + p_priv->out_buffer[i], 64, 2528 + cback->outdat_callback); 2529 + } 2530 + /* inack endpoint */ 2531 + p_priv->inack_urb = keyspan_setup_urb(serial, 2532 + d_details->inack_endpoints[port_num], 2533 + USB_DIR_IN, port, 2534 + p_priv->inack_buffer, 1, 2535 + cback->inack_callback); 2536 + /* outcont endpoint */ 2537 + p_priv->outcont_urb = keyspan_setup_urb(serial, 2538 + d_details->outcont_endpoints[port_num], 2539 + USB_DIR_OUT, port, 2540 + p_priv->outcont_buffer, 64, 2541 + cback->outcont_callback); 2542 + 2543 + usb_set_serial_port_data(port, p_priv); 2544 + 2545 + return 0; 2546 + } 2547 + 2548 + static int keyspan_port_remove(struct usb_serial_port *port) 2549 + { 2550 + struct keyspan_port_private *p_priv; 2551 + int i; 2552 + 2553 + p_priv = usb_get_serial_port_data(port); 2554 + 2555 + stop_urb(p_priv->inack_urb); 2556 + stop_urb(p_priv->outcont_urb); 2557 + for (i = 0; i < 2; i++) { 2558 + stop_urb(p_priv->in_urbs[i]); 2559 + stop_urb(p_priv->out_urbs[i]); 2560 + } 2561 + 2562 + usb_free_urb(p_priv->inack_urb); 2563 + usb_free_urb(p_priv->outcont_urb); 2564 + for (i = 0; i < 2; i++) { 2565 + usb_free_urb(p_priv->in_urbs[i]); 2566 + usb_free_urb(p_priv->out_urbs[i]); 2567 + } 2568 + 2569 + kfree(p_priv); 2570 + 2571 + return 0; 2461 2572 } 2462 2573 2463 2574 MODULE_AUTHOR(DRIVER_AUTHOR);
+8
drivers/usb/serial/keyspan.h
··· 42 42 static int keyspan_startup (struct usb_serial *serial); 43 43 static void keyspan_disconnect (struct usb_serial *serial); 44 44 static void keyspan_release (struct usb_serial *serial); 45 + static int keyspan_port_probe(struct usb_serial_port *port); 46 + static int keyspan_port_remove(struct usb_serial_port *port); 45 47 static int keyspan_write_room (struct tty_struct *tty); 46 48 47 49 static int keyspan_write (struct tty_struct *tty, ··· 569 567 .attach = keyspan_startup, 570 568 .disconnect = keyspan_disconnect, 571 569 .release = keyspan_release, 570 + .port_probe = keyspan_port_probe, 571 + .port_remove = keyspan_port_remove, 572 572 }; 573 573 574 574 static struct usb_serial_driver keyspan_2port_device = { ··· 593 589 .attach = keyspan_startup, 594 590 .disconnect = keyspan_disconnect, 595 591 .release = keyspan_release, 592 + .port_probe = keyspan_port_probe, 593 + .port_remove = keyspan_port_remove, 596 594 }; 597 595 598 596 static struct usb_serial_driver keyspan_4port_device = { ··· 617 611 .attach = keyspan_startup, 618 612 .disconnect = keyspan_disconnect, 619 613 .release = keyspan_release, 614 + .port_probe = keyspan_port_probe, 615 + .port_remove = keyspan_port_remove, 620 616 }; 621 617 622 618 static struct usb_serial_driver * const serial_drivers[] = {