123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869 |
- From dd7590a3ab3f0804ed5e930295e2caa5979e3958 Mon Sep 17 00:00:00 2001
- From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
- Date: Thu, 28 Feb 2019 22:57:33 +0100
- Subject: [PATCH] leds: trigger: netdev: fix refcnt leak on interface rename
- MIME-Version: 1.0
- Content-Type: text/plain; charset=UTF-8
- Content-Transfer-Encoding: 8bit
- Renaming a netdev-trigger-tracked interface was resulting in an
- unbalanced dev_hold().
- Example:
- > iw phy phy0 interface add foo type __ap
- > echo netdev > trigger
- > echo foo > device_name
- > ip link set foo name bar
- > iw dev bar del
- [ 237.355366] unregister_netdevice: waiting for bar to become free. Usage count = 1
- [ 247.435362] unregister_netdevice: waiting for bar to become free. Usage count = 1
- [ 257.545366] unregister_netdevice: waiting for bar to become free. Usage count = 1
- Above problem was caused by trigger checking a dev->name which obviously
- changes after renaming an interface. It meant missing all further events
- including the NETDEV_UNREGISTER which is required for calling dev_put().
- This change fixes that by:
- 1) Comparing device struct *address* for notification-filtering purposes
- 2) Dropping unneeded NETDEV_CHANGENAME code (no behavior change)
- Fixes: 06f502f57d0d ("leds: trigger: Introduce a NETDEV trigger")
- Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
- Acked-by: Pavel Machek <pavel@ucw.cz>
- Signed-off-by: Jacek Anaszewski <jacek.anaszewski@gmail.com>
- ---
- drivers/leds/trigger/ledtrig-netdev.c | 13 +++++--------
- 1 file changed, 5 insertions(+), 8 deletions(-)
- --- a/drivers/leds/trigger/ledtrig-netdev.c
- +++ b/drivers/leds/trigger/ledtrig-netdev.c
- @@ -299,11 +299,11 @@ static int netdev_trig_notify(struct not
- notifier);
-
- if (evt != NETDEV_UP && evt != NETDEV_DOWN && evt != NETDEV_CHANGE
- - && evt != NETDEV_REGISTER && evt != NETDEV_UNREGISTER
- - && evt != NETDEV_CHANGENAME)
- + && evt != NETDEV_REGISTER && evt != NETDEV_UNREGISTER)
- return NOTIFY_DONE;
-
- - if (strcmp(dev->name, trigger_data->device_name))
- + if (!(dev == trigger_data->net_dev ||
- + (evt == NETDEV_REGISTER && !strcmp(dev->name, trigger_data->device_name))))
- return NOTIFY_DONE;
-
- cancel_delayed_work_sync(&trigger_data->work);
- @@ -318,12 +318,9 @@ static int netdev_trig_notify(struct not
- dev_hold(dev);
- trigger_data->net_dev = dev;
- break;
- - case NETDEV_CHANGENAME:
- case NETDEV_UNREGISTER:
- - if (trigger_data->net_dev) {
- - dev_put(trigger_data->net_dev);
- - trigger_data->net_dev = NULL;
- - }
- + dev_put(trigger_data->net_dev);
- + trigger_data->net_dev = NULL;
- break;
- case NETDEV_UP:
- case NETDEV_CHANGE:
|