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

USB: xhci: dbc: fix tty registration race

Make sure to allocate resources before registering the tty device to
avoid having a racing open() and write() fail to enable rx or
dereference a NULL pointer when accessing the uninitialised fifo.

Fixes: dfba2174dc42 ("usb: xhci: Add DbC support in xHCI driver")
Cc: stable@vger.kernel.org # 4.16
Cc: Lu Baolu <baolu.lu@linux.intel.com>
Signed-off-by: Johan Hovold <johan@kernel.org>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Link: https://lore.kernel.org/r/20211008092547.3996295-4-mathias.nyman@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Johan Hovold and committed by
Greg Kroah-Hartman
880de403 5255660b

+13 -15
+13 -15
drivers/usb/host/xhci-dbgtty.c
··· 408 408 return -EBUSY; 409 409 410 410 xhci_dbc_tty_init_port(dbc, port); 411 - tty_dev = tty_port_register_device(&port->port, 412 - dbc_tty_driver, 0, NULL); 413 - if (IS_ERR(tty_dev)) { 414 - ret = PTR_ERR(tty_dev); 415 - goto register_fail; 416 - } 417 411 418 412 ret = kfifo_alloc(&port->write_fifo, DBC_WRITE_BUF_SIZE, GFP_KERNEL); 419 413 if (ret) 420 - goto buf_alloc_fail; 414 + goto err_exit_port; 421 415 422 416 ret = xhci_dbc_alloc_requests(dbc, BULK_IN, &port->read_pool, 423 417 dbc_read_complete); 424 418 if (ret) 425 - goto request_fail; 419 + goto err_free_fifo; 426 420 427 421 ret = xhci_dbc_alloc_requests(dbc, BULK_OUT, &port->write_pool, 428 422 dbc_write_complete); 429 423 if (ret) 430 - goto request_fail; 424 + goto err_free_requests; 425 + 426 + tty_dev = tty_port_register_device(&port->port, 427 + dbc_tty_driver, 0, NULL); 428 + if (IS_ERR(tty_dev)) { 429 + ret = PTR_ERR(tty_dev); 430 + goto err_free_requests; 431 + } 431 432 432 433 port->registered = true; 433 434 434 435 return 0; 435 436 436 - request_fail: 437 + err_free_requests: 437 438 xhci_dbc_free_requests(&port->read_pool); 438 439 xhci_dbc_free_requests(&port->write_pool); 440 + err_free_fifo: 439 441 kfifo_free(&port->write_fifo); 440 - 441 - buf_alloc_fail: 442 - tty_unregister_device(dbc_tty_driver, 0); 443 - 444 - register_fail: 442 + err_exit_port: 445 443 xhci_dbc_tty_exit_port(port); 446 444 447 445 dev_err(dbc->dev, "can't register tty port, err %d\n", ret);