lkml.org 
[lkml]   [2019]   [Sep]   [4]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
SubjectRe: WARNING in hso_free_net_device
From
Date
Can you guys have  a look at the attached patch?

On 9/4/19 6:41 PM, Stephen Hemminger wrote:
> On Wed, 4 Sep 2019 16:27:50 -0400
> Hui Peng <benquike@gmail.com> 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@gmail.com>
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@syzkaller.appspotmail.com
Signed-off-by: Hui Peng <benquike@gmail.com>
---
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
[unhandled content-type:application/pgp-keys]
\
 
 \ /
  Last update: 2019-09-05 04:20    [W:0.099 / U:1.072 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site