mirror of
https://github.com/torvalds/linux.git
synced 2026-05-28 09:04:39 +02:00
staging: gpib: Fix Oops after disconnect in ni_usb
If the usb dongle is disconnected subsequent calls to the
driver cause a NULL dereference Oops as the bus_interface
is set to NULL on disconnect.
This problem was introduced by setting usb_dev from the bus_interface
for dev_xxx messages.
Previously bus_interface was checked for NULL only in the the functions
directly calling usb_fill_bulk_urb or usb_control_msg.
Check for valid bus_interface on all interface entry points
and return -ENODEV if it is NULL.
Fixes: 4934b98bb2 ("staging: gpib: Update messaging and usb_device refs in ni_usb")
Cc: stable <stable@kernel.org>
Signed-off-by: Dave Penkler <dpenkler@gmail.com>
Link: https://lore.kernel.org/r/20250222165817.12856-1-dpenkler@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
20a351c36a
commit
a239c6e91b
|
|
@ -591,7 +591,7 @@ static int ni_usb_read(gpib_board_t *board, uint8_t *buffer, size_t length,
|
|||
{
|
||||
int retval, parse_retval;
|
||||
struct ni_usb_priv *ni_priv = board->private_data;
|
||||
struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
|
||||
struct usb_device *usb_dev;
|
||||
u8 *out_data, *in_data;
|
||||
static const int out_data_length = 0x20;
|
||||
int in_data_length;
|
||||
|
|
@ -604,8 +604,11 @@ static int ni_usb_read(gpib_board_t *board, uint8_t *buffer, size_t length,
|
|||
struct ni_usb_register reg;
|
||||
|
||||
*bytes_read = 0;
|
||||
if (!ni_priv->bus_interface)
|
||||
return -ENODEV;
|
||||
if (length > max_read_length)
|
||||
return -EINVAL;
|
||||
usb_dev = interface_to_usbdev(ni_priv->bus_interface);
|
||||
out_data = kmalloc(out_data_length, GFP_KERNEL);
|
||||
if (!out_data)
|
||||
return -ENOMEM;
|
||||
|
|
@ -718,7 +721,7 @@ static int ni_usb_write(gpib_board_t *board, uint8_t *buffer, size_t length,
|
|||
{
|
||||
int retval;
|
||||
struct ni_usb_priv *ni_priv = board->private_data;
|
||||
struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
|
||||
struct usb_device *usb_dev;
|
||||
u8 *out_data, *in_data;
|
||||
int out_data_length;
|
||||
static const int in_data_length = 0x10;
|
||||
|
|
@ -728,9 +731,11 @@ static int ni_usb_write(gpib_board_t *board, uint8_t *buffer, size_t length,
|
|||
struct ni_usb_status_block status;
|
||||
static const int max_write_length = 0xffff;
|
||||
|
||||
*bytes_written = 0;
|
||||
if (!ni_priv->bus_interface)
|
||||
return -ENODEV;
|
||||
if (length > max_write_length)
|
||||
return -EINVAL;
|
||||
usb_dev = interface_to_usbdev(ni_priv->bus_interface);
|
||||
out_data_length = length + 0x10;
|
||||
out_data = kmalloc(out_data_length, GFP_KERNEL);
|
||||
if (!out_data)
|
||||
|
|
@ -819,7 +824,7 @@ static int ni_usb_command_chunk(gpib_board_t *board, uint8_t *buffer, size_t len
|
|||
{
|
||||
int retval;
|
||||
struct ni_usb_priv *ni_priv = board->private_data;
|
||||
struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
|
||||
struct usb_device *usb_dev;
|
||||
u8 *out_data, *in_data;
|
||||
int out_data_length;
|
||||
static const int in_data_length = 0x10;
|
||||
|
|
@ -831,8 +836,11 @@ static int ni_usb_command_chunk(gpib_board_t *board, uint8_t *buffer, size_t len
|
|||
static const int max_command_length = 0x10;
|
||||
|
||||
*command_bytes_written = 0;
|
||||
if (!ni_priv->bus_interface)
|
||||
return -ENODEV;
|
||||
if (length > max_command_length)
|
||||
length = max_command_length;
|
||||
usb_dev = interface_to_usbdev(ni_priv->bus_interface);
|
||||
out_data_length = length + 0x10;
|
||||
out_data = kmalloc(out_data_length, GFP_KERNEL);
|
||||
if (!out_data)
|
||||
|
|
@ -925,7 +933,7 @@ static int ni_usb_take_control(gpib_board_t *board, int synchronous)
|
|||
{
|
||||
int retval;
|
||||
struct ni_usb_priv *ni_priv = board->private_data;
|
||||
struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
|
||||
struct usb_device *usb_dev;
|
||||
u8 *out_data, *in_data;
|
||||
static const int out_data_length = 0x10;
|
||||
static const int in_data_length = 0x10;
|
||||
|
|
@ -933,6 +941,9 @@ static int ni_usb_take_control(gpib_board_t *board, int synchronous)
|
|||
int i = 0;
|
||||
struct ni_usb_status_block status;
|
||||
|
||||
if (!ni_priv->bus_interface)
|
||||
return -ENODEV;
|
||||
usb_dev = interface_to_usbdev(ni_priv->bus_interface);
|
||||
out_data = kmalloc(out_data_length, GFP_KERNEL);
|
||||
if (!out_data)
|
||||
return -ENOMEM;
|
||||
|
|
@ -983,7 +994,7 @@ static int ni_usb_go_to_standby(gpib_board_t *board)
|
|||
{
|
||||
int retval;
|
||||
struct ni_usb_priv *ni_priv = board->private_data;
|
||||
struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
|
||||
struct usb_device *usb_dev;
|
||||
u8 *out_data, *in_data;
|
||||
static const int out_data_length = 0x10;
|
||||
static const int in_data_length = 0x20;
|
||||
|
|
@ -991,6 +1002,9 @@ static int ni_usb_go_to_standby(gpib_board_t *board)
|
|||
int i = 0;
|
||||
struct ni_usb_status_block status;
|
||||
|
||||
if (!ni_priv->bus_interface)
|
||||
return -ENODEV;
|
||||
usb_dev = interface_to_usbdev(ni_priv->bus_interface);
|
||||
out_data = kmalloc(out_data_length, GFP_KERNEL);
|
||||
if (!out_data)
|
||||
return -ENOMEM;
|
||||
|
|
@ -1039,11 +1053,14 @@ static void ni_usb_request_system_control(gpib_board_t *board, int request_contr
|
|||
{
|
||||
int retval;
|
||||
struct ni_usb_priv *ni_priv = board->private_data;
|
||||
struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
|
||||
struct usb_device *usb_dev;
|
||||
int i = 0;
|
||||
struct ni_usb_register writes[4];
|
||||
unsigned int ibsta;
|
||||
|
||||
if (!ni_priv->bus_interface)
|
||||
return; // -ENODEV;
|
||||
usb_dev = interface_to_usbdev(ni_priv->bus_interface);
|
||||
if (request_control) {
|
||||
writes[i].device = NIUSB_SUBDEV_TNT4882;
|
||||
writes[i].address = CMDR;
|
||||
|
|
@ -1087,7 +1104,7 @@ static void ni_usb_interface_clear(gpib_board_t *board, int assert)
|
|||
{
|
||||
int retval;
|
||||
struct ni_usb_priv *ni_priv = board->private_data;
|
||||
struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
|
||||
struct usb_device *usb_dev;
|
||||
u8 *out_data, *in_data;
|
||||
static const int out_data_length = 0x10;
|
||||
static const int in_data_length = 0x10;
|
||||
|
|
@ -1095,7 +1112,10 @@ static void ni_usb_interface_clear(gpib_board_t *board, int assert)
|
|||
int i = 0;
|
||||
struct ni_usb_status_block status;
|
||||
|
||||
// FIXME: we are going to pulse when assert is true, and ignore otherwise
|
||||
if (!ni_priv->bus_interface)
|
||||
return; // -ENODEV;
|
||||
usb_dev = interface_to_usbdev(ni_priv->bus_interface);
|
||||
// FIXME: we are going to pulse when assert is true, and ignore otherwise
|
||||
if (assert == 0)
|
||||
return;
|
||||
out_data = kmalloc(out_data_length, GFP_KERNEL);
|
||||
|
|
@ -1133,10 +1153,13 @@ static void ni_usb_remote_enable(gpib_board_t *board, int enable)
|
|||
{
|
||||
int retval;
|
||||
struct ni_usb_priv *ni_priv = board->private_data;
|
||||
struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
|
||||
struct usb_device *usb_dev;
|
||||
struct ni_usb_register reg;
|
||||
unsigned int ibsta;
|
||||
|
||||
if (!ni_priv->bus_interface)
|
||||
return; // -ENODEV;
|
||||
usb_dev = interface_to_usbdev(ni_priv->bus_interface);
|
||||
reg.device = NIUSB_SUBDEV_TNT4882;
|
||||
reg.address = nec7210_to_tnt4882_offset(AUXMR);
|
||||
if (enable)
|
||||
|
|
@ -1180,11 +1203,14 @@ static unsigned int ni_usb_update_status(gpib_board_t *board, unsigned int clear
|
|||
{
|
||||
int retval;
|
||||
struct ni_usb_priv *ni_priv = board->private_data;
|
||||
struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
|
||||
struct usb_device *usb_dev;
|
||||
static const int buffer_length = 8;
|
||||
u8 *buffer;
|
||||
struct ni_usb_status_block status;
|
||||
|
||||
if (!ni_priv->bus_interface)
|
||||
return -ENODEV;
|
||||
usb_dev = interface_to_usbdev(ni_priv->bus_interface);
|
||||
buffer = kmalloc(buffer_length, GFP_KERNEL);
|
||||
if (!buffer)
|
||||
return board->status;
|
||||
|
|
@ -1232,11 +1258,14 @@ static int ni_usb_primary_address(gpib_board_t *board, unsigned int address)
|
|||
{
|
||||
int retval;
|
||||
struct ni_usb_priv *ni_priv = board->private_data;
|
||||
struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
|
||||
struct usb_device *usb_dev;
|
||||
int i = 0;
|
||||
struct ni_usb_register writes[2];
|
||||
unsigned int ibsta;
|
||||
|
||||
if (!ni_priv->bus_interface)
|
||||
return -ENODEV;
|
||||
usb_dev = interface_to_usbdev(ni_priv->bus_interface);
|
||||
writes[i].device = NIUSB_SUBDEV_TNT4882;
|
||||
writes[i].address = nec7210_to_tnt4882_offset(ADR);
|
||||
writes[i].value = address;
|
||||
|
|
@ -1287,11 +1316,14 @@ static int ni_usb_secondary_address(gpib_board_t *board, unsigned int address, i
|
|||
{
|
||||
int retval;
|
||||
struct ni_usb_priv *ni_priv = board->private_data;
|
||||
struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
|
||||
struct usb_device *usb_dev;
|
||||
int i = 0;
|
||||
struct ni_usb_register writes[3];
|
||||
unsigned int ibsta;
|
||||
|
||||
if (!ni_priv->bus_interface)
|
||||
return -ENODEV;
|
||||
usb_dev = interface_to_usbdev(ni_priv->bus_interface);
|
||||
i += ni_usb_write_sad(writes, address, enable);
|
||||
retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta);
|
||||
if (retval < 0) {
|
||||
|
|
@ -1306,7 +1338,7 @@ static int ni_usb_parallel_poll(gpib_board_t *board, uint8_t *result)
|
|||
{
|
||||
int retval;
|
||||
struct ni_usb_priv *ni_priv = board->private_data;
|
||||
struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
|
||||
struct usb_device *usb_dev;
|
||||
u8 *out_data, *in_data;
|
||||
static const int out_data_length = 0x10;
|
||||
static const int in_data_length = 0x20;
|
||||
|
|
@ -1315,6 +1347,9 @@ static int ni_usb_parallel_poll(gpib_board_t *board, uint8_t *result)
|
|||
int j = 0;
|
||||
struct ni_usb_status_block status;
|
||||
|
||||
if (!ni_priv->bus_interface)
|
||||
return -ENODEV;
|
||||
usb_dev = interface_to_usbdev(ni_priv->bus_interface);
|
||||
out_data = kmalloc(out_data_length, GFP_KERNEL);
|
||||
if (!out_data)
|
||||
return -ENOMEM;
|
||||
|
|
@ -1358,11 +1393,14 @@ static void ni_usb_parallel_poll_configure(gpib_board_t *board, uint8_t config)
|
|||
{
|
||||
int retval;
|
||||
struct ni_usb_priv *ni_priv = board->private_data;
|
||||
struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
|
||||
struct usb_device *usb_dev;
|
||||
int i = 0;
|
||||
struct ni_usb_register writes[1];
|
||||
unsigned int ibsta;
|
||||
|
||||
if (!ni_priv->bus_interface)
|
||||
return; // -ENODEV;
|
||||
usb_dev = interface_to_usbdev(ni_priv->bus_interface);
|
||||
writes[i].device = NIUSB_SUBDEV_TNT4882;
|
||||
writes[i].address = nec7210_to_tnt4882_offset(AUXMR);
|
||||
writes[i].value = PPR | config;
|
||||
|
|
@ -1380,11 +1418,14 @@ static void ni_usb_parallel_poll_response(gpib_board_t *board, int ist)
|
|||
{
|
||||
int retval;
|
||||
struct ni_usb_priv *ni_priv = board->private_data;
|
||||
struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
|
||||
struct usb_device *usb_dev;
|
||||
int i = 0;
|
||||
struct ni_usb_register writes[1];
|
||||
unsigned int ibsta;
|
||||
|
||||
if (!ni_priv->bus_interface)
|
||||
return; // -ENODEV;
|
||||
usb_dev = interface_to_usbdev(ni_priv->bus_interface);
|
||||
writes[i].device = NIUSB_SUBDEV_TNT4882;
|
||||
writes[i].address = nec7210_to_tnt4882_offset(AUXMR);
|
||||
if (ist)
|
||||
|
|
@ -1405,11 +1446,14 @@ static void ni_usb_serial_poll_response(gpib_board_t *board, u8 status)
|
|||
{
|
||||
int retval;
|
||||
struct ni_usb_priv *ni_priv = board->private_data;
|
||||
struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
|
||||
struct usb_device *usb_dev;
|
||||
int i = 0;
|
||||
struct ni_usb_register writes[1];
|
||||
unsigned int ibsta;
|
||||
|
||||
if (!ni_priv->bus_interface)
|
||||
return; // -ENODEV;
|
||||
usb_dev = interface_to_usbdev(ni_priv->bus_interface);
|
||||
writes[i].device = NIUSB_SUBDEV_TNT4882;
|
||||
writes[i].address = nec7210_to_tnt4882_offset(SPMR);
|
||||
writes[i].value = status;
|
||||
|
|
@ -1432,11 +1476,14 @@ static void ni_usb_return_to_local(gpib_board_t *board)
|
|||
{
|
||||
int retval;
|
||||
struct ni_usb_priv *ni_priv = board->private_data;
|
||||
struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
|
||||
struct usb_device *usb_dev;
|
||||
int i = 0;
|
||||
struct ni_usb_register writes[1];
|
||||
unsigned int ibsta;
|
||||
|
||||
if (!ni_priv->bus_interface)
|
||||
return; // -ENODEV;
|
||||
usb_dev = interface_to_usbdev(ni_priv->bus_interface);
|
||||
writes[i].device = NIUSB_SUBDEV_TNT4882;
|
||||
writes[i].address = nec7210_to_tnt4882_offset(AUXMR);
|
||||
writes[i].value = AUX_RTL;
|
||||
|
|
@ -1454,7 +1501,7 @@ static int ni_usb_line_status(const gpib_board_t *board)
|
|||
{
|
||||
int retval;
|
||||
struct ni_usb_priv *ni_priv = board->private_data;
|
||||
struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
|
||||
struct usb_device *usb_dev;
|
||||
u8 *out_data, *in_data;
|
||||
static const int out_data_length = 0x20;
|
||||
static const int in_data_length = 0x20;
|
||||
|
|
@ -1464,6 +1511,9 @@ static int ni_usb_line_status(const gpib_board_t *board)
|
|||
int line_status = ValidALL;
|
||||
// NI windows driver reads 0xd(HSSEL), 0xc (ARD0), 0x1f (BSR)
|
||||
|
||||
if (!ni_priv->bus_interface)
|
||||
return -ENODEV;
|
||||
usb_dev = interface_to_usbdev(ni_priv->bus_interface);
|
||||
out_data = kmalloc(out_data_length, GFP_KERNEL);
|
||||
if (!out_data)
|
||||
return -ENOMEM;
|
||||
|
|
@ -1570,12 +1620,15 @@ static unsigned int ni_usb_t1_delay(gpib_board_t *board, unsigned int nano_sec)
|
|||
{
|
||||
int retval;
|
||||
struct ni_usb_priv *ni_priv = board->private_data;
|
||||
struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
|
||||
struct usb_device *usb_dev;
|
||||
struct ni_usb_register writes[3];
|
||||
unsigned int ibsta;
|
||||
unsigned int actual_ns;
|
||||
int i;
|
||||
|
||||
if (!ni_priv->bus_interface)
|
||||
return -ENODEV;
|
||||
usb_dev = interface_to_usbdev(ni_priv->bus_interface);
|
||||
i = ni_usb_setup_t1_delay(writes, nano_sec, &actual_ns);
|
||||
retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta);
|
||||
if (retval < 0) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user