On Thu, Sep 5, 2019 at 4:20 AM Hui Peng <benquike@xxxxxxxxx> wrote: > > Can you guys have a look at the attached patch? Let's try it: #syz test: https://github.com/google/kasan.git eea39f24 FYI: there are two more reports coming from this driver, which might (or might not) have the same root cause. One of them has a suggested fix by Oliver. https://syzkaller.appspot.com/bug?extid=67b2bd0e34f952d0321e https://syzkaller.appspot.com/bug?extid=93f2f45b19519b289613 > > On 9/4/19 6:41 PM, Stephen Hemminger wrote: > > On Wed, 4 Sep 2019 16:27:50 -0400 > > Hui Peng <benquike@xxxxxxxxx> wrote: > > > >> Hi, all: > >> > >> I looked at the bug a little. > >> > >> The issue is that in the error handling code, hso_free_net_device > >> unregisters > >> > >> the net_device (hso_net->net) by calling unregister_netdev. In the > >> error handling code path, > >> > >> hso_net->net has not been registered yet. > >> > >> I think there are two ways to solve the issue: > >> > >> 1. fix it in drivers/net/usb/hso.c to avoiding unregistering the > >> net_device when it is still not registered > >> > >> 2. fix it in unregister_netdev. We can add a field in net_device to > >> record whether it is registered, and make unregister_netdev return if > >> the net_device is not registered yet. > >> > >> What do you guys think ? > > #1
From f3fdee8fc03aa2bc982f22da1d29bbf6bca72935 Mon Sep 17 00:00:00 2001 From: Hui Peng <benquike@xxxxxxxxx> Date: Wed, 4 Sep 2019 21:38:35 -0400 Subject: [PATCH] Fix a wrong unregistering bug in hso_free_net_device As shown below, hso_create_net_device may call hso_free_net_device before the net_device is registered. hso_free_net_device will unregister the network device no matter it is registered or not, unregister_netdev is not able to handle unregistered net_device, resulting in the bug reported by the syzbot. ``` static struct hso_device *hso_create_net_device(struct usb_interface *interface, int port_spec) { ...... net = alloc_netdev(sizeof(struct hso_net), "hso%d", NET_NAME_UNKNOWN, hso_net_init); ...... if (!hso_net->out_endp) { dev_err(&interface->dev, "Can't find BULK OUT endpoint\n"); goto exit; } ...... result = register_netdev(net); ...... exit: hso_free_net_device(hso_dev); return NULL; } static void hso_free_net_device(struct hso_device *hso_dev) { ...... if (hso_net->net) unregister_netdev(hso_net->net); ...... } ``` This patch adds a net_registered field in struct hso_net to record whether the containing net_device is registered or not, and avoid unregistering it if it is not registered yet. Reported-by: syzbot+44d53c7255bb1aea22d2@xxxxxxxxxxxxxxxxxxxxxxxxx Signed-off-by: Hui Peng <benquike@xxxxxxxxx> --- drivers/net/usb/hso.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index ce78714..5b3df33 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -128,6 +128,7 @@ struct hso_shared_int { struct hso_net { struct hso_device *parent; struct net_device *net; + bool net_registered; struct rfkill *rfkill; char name[24]; @@ -2362,7 +2363,7 @@ static void hso_free_net_device(struct hso_device *hso_dev) remove_net_device(hso_net->parent); - if (hso_net->net) + if (hso_net->net && hso_net->net_registered) unregister_netdev(hso_net->net); /* start freeing */ @@ -2544,6 +2545,7 @@ static struct hso_device *hso_create_net_device(struct usb_interface *interface, dev_err(&interface->dev, "Failed to register device\n"); goto exit; } + hso_net->net_registered = true; hso_log_port(hso_dev); -- 2.7.4