forked from openwrt/openwrt
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
kernel: fix refcnt leak in LED netdev trigger on interface rename
This fixes a possible unbalanced dev_hold(): > 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 Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
- Loading branch information
Rafał Miłecki
committed
Mar 5, 2019
1 parent
64bb888
commit 9e32e28
Showing
2 changed files
with
138 additions
and
0 deletions.
There are no files selected for viewing
69 changes: 69 additions & 0 deletions
69
...generic/backport-4.14/401-v5.2-leds-trigger-netdev-fix-refcnt-leak-on-interface-ren.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
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: |
69 changes: 69 additions & 0 deletions
69
...generic/backport-4.19/400-v5.2-leds-trigger-netdev-fix-refcnt-leak-on-interface-ren.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
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 | ||
@@ -301,11 +301,11 @@ static int netdev_trig_notify(struct not | ||
container_of(nb, struct led_netdev_data, 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); | ||
@@ -320,12 +320,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: |