All 3 upstream commits apply cleanly: * 5fcfb6d0bfcd ("hso: fix bailout in error case of probe") is a support patch needed for context * a6ecfb39ba9d ("usb: hso: fix error handling code of hso_create_net_device") is the actual fix * dcb713d53e2e ("usb: hso: remove the bailout parameter") is a follow up cleanup commit
Dongliang Mu (2): usb: hso: fix error handling code of hso_create_net_device usb: hso: remove the bailout parameter
Oliver Neukum (1): hso: fix bailout in error case of probe
drivers/net/usb/hso.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-)
From: Oliver Neukum oneukum@suse.com
commit 5fcfb6d0bfcda17f0d0656e4e5b3710af2bbaae5 upstream.
The driver tries to reuse code for disconnect in case of a failed probe. If resources need to be freed after an error in probe, the netdev must not be freed because it has never been registered. Fix it by telling the helper which path we are in.
Signed-off-by: Oliver Neukum oneukum@suse.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Ovidiu Panait ovidiu.panait@windriver.com --- drivers/net/usb/hso.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index a66077f51457..0839da773e62 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -2368,7 +2368,7 @@ static int remove_net_device(struct hso_device *hso_dev) }
/* Frees our network device */ -static void hso_free_net_device(struct hso_device *hso_dev) +static void hso_free_net_device(struct hso_device *hso_dev, bool bailout) { int i; struct hso_net *hso_net = dev2net(hso_dev); @@ -2391,7 +2391,7 @@ static void hso_free_net_device(struct hso_device *hso_dev) kfree(hso_net->mux_bulk_tx_buf); hso_net->mux_bulk_tx_buf = NULL;
- if (hso_net->net) + if (hso_net->net && !bailout) free_netdev(hso_net->net);
kfree(hso_dev); @@ -2567,7 +2567,7 @@ static struct hso_device *hso_create_net_device(struct usb_interface *interface,
return hso_dev; exit: - hso_free_net_device(hso_dev); + hso_free_net_device(hso_dev, true); return NULL; }
@@ -3132,7 +3132,7 @@ static void hso_free_interface(struct usb_interface *interface) rfkill_unregister(rfk); rfkill_destroy(rfk); } - hso_free_net_device(network_table[i]); + hso_free_net_device(network_table[i], false); } } }
From: Dongliang Mu mudongliangabcd@gmail.com
commit a6ecfb39ba9d7316057cea823b196b734f6b18ca upstream.
The current error handling code of hso_create_net_device is hso_free_net_device, no matter which errors lead to. For example, WARNING in hso_free_net_device [1].
Fix this by refactoring the error handling code of hso_create_net_device by handling different errors by different code.
[1] https://syzkaller.appspot.com/bug?id=66eff8d49af1b28370ad342787413e35bbe76ef...
Reported-by: syzbot+44d53c7255bb1aea22d2@syzkaller.appspotmail.com Fixes: 5fcfb6d0bfcd ("hso: fix bailout in error case of probe") Signed-off-by: Dongliang Mu mudongliangabcd@gmail.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Ovidiu Panait ovidiu.panait@windriver.com --- drivers/net/usb/hso.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-)
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 0839da773e62..8f0d86f91c5c 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -2511,7 +2511,7 @@ static struct hso_device *hso_create_net_device(struct usb_interface *interface, hso_net_init); if (!net) { dev_err(&interface->dev, "Unable to create ethernet device\n"); - goto exit; + goto err_hso_dev; }
hso_net = netdev_priv(net); @@ -2524,13 +2524,13 @@ static struct hso_device *hso_create_net_device(struct usb_interface *interface, USB_DIR_IN); if (!hso_net->in_endp) { dev_err(&interface->dev, "Can't find BULK IN endpoint\n"); - goto exit; + goto err_net; } hso_net->out_endp = hso_get_ep(interface, USB_ENDPOINT_XFER_BULK, USB_DIR_OUT); if (!hso_net->out_endp) { dev_err(&interface->dev, "Can't find BULK OUT endpoint\n"); - goto exit; + goto err_net; } SET_NETDEV_DEV(net, &interface->dev); SET_NETDEV_DEVTYPE(net, &hso_type); @@ -2539,18 +2539,18 @@ static struct hso_device *hso_create_net_device(struct usb_interface *interface, for (i = 0; i < MUX_BULK_RX_BUF_COUNT; i++) { hso_net->mux_bulk_rx_urb_pool[i] = usb_alloc_urb(0, GFP_KERNEL); if (!hso_net->mux_bulk_rx_urb_pool[i]) - goto exit; + goto err_mux_bulk_rx; hso_net->mux_bulk_rx_buf_pool[i] = kzalloc(MUX_BULK_RX_BUF_SIZE, GFP_KERNEL); if (!hso_net->mux_bulk_rx_buf_pool[i]) - goto exit; + goto err_mux_bulk_rx; } hso_net->mux_bulk_tx_urb = usb_alloc_urb(0, GFP_KERNEL); if (!hso_net->mux_bulk_tx_urb) - goto exit; + goto err_mux_bulk_rx; hso_net->mux_bulk_tx_buf = kzalloc(MUX_BULK_TX_BUF_SIZE, GFP_KERNEL); if (!hso_net->mux_bulk_tx_buf) - goto exit; + goto err_free_tx_urb;
add_net_device(hso_dev);
@@ -2558,7 +2558,7 @@ static struct hso_device *hso_create_net_device(struct usb_interface *interface, result = register_netdev(net); if (result) { dev_err(&interface->dev, "Failed to register device\n"); - goto exit; + goto err_free_tx_buf; }
hso_log_port(hso_dev); @@ -2566,8 +2566,21 @@ static struct hso_device *hso_create_net_device(struct usb_interface *interface, hso_create_rfkill(hso_dev, interface);
return hso_dev; -exit: - hso_free_net_device(hso_dev, true); + +err_free_tx_buf: + remove_net_device(hso_dev); + kfree(hso_net->mux_bulk_tx_buf); +err_free_tx_urb: + usb_free_urb(hso_net->mux_bulk_tx_urb); +err_mux_bulk_rx: + for (i = 0; i < MUX_BULK_RX_BUF_COUNT; i++) { + usb_free_urb(hso_net->mux_bulk_rx_urb_pool[i]); + kfree(hso_net->mux_bulk_rx_buf_pool[i]); + } +err_net: + free_netdev(net); +err_hso_dev: + kfree(hso_dev); return NULL; }
From: Dongliang Mu mudongliangabcd@gmail.com
commit dcb713d53e2eadf42b878c12a471e74dc6ed3145 upstream.
There are two invocation sites of hso_free_net_device. After refactoring hso_create_net_device, this parameter is useless. Remove the bailout in the hso_free_net_device and change the invocation sites of this function.
Signed-off-by: Dongliang Mu mudongliangabcd@gmail.com Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Ovidiu Panait ovidiu.panait@windriver.com --- drivers/net/usb/hso.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 8f0d86f91c5c..681b19901a94 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -2368,7 +2368,7 @@ static int remove_net_device(struct hso_device *hso_dev) }
/* Frees our network device */ -static void hso_free_net_device(struct hso_device *hso_dev, bool bailout) +static void hso_free_net_device(struct hso_device *hso_dev) { int i; struct hso_net *hso_net = dev2net(hso_dev); @@ -2391,7 +2391,7 @@ static void hso_free_net_device(struct hso_device *hso_dev, bool bailout) kfree(hso_net->mux_bulk_tx_buf); hso_net->mux_bulk_tx_buf = NULL;
- if (hso_net->net && !bailout) + if (hso_net->net) free_netdev(hso_net->net);
kfree(hso_dev); @@ -3145,7 +3145,7 @@ static void hso_free_interface(struct usb_interface *interface) rfkill_unregister(rfk); rfkill_destroy(rfk); } - hso_free_net_device(network_table[i], false); + hso_free_net_device(network_table[i]); } } }
linux-stable-mirror@lists.linaro.org