From 4cb6560514fa19d556954b88128f3846fee66a03 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Thu, 28 Feb 2019 22:57:33 +0100 Subject: 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 Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/trigger/ledtrig-netdev.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/leds/trigger/ledtrig-netdev.c b/drivers/leds/trigger/ledtrig-netdev.c index 3dd3ed46d473..167a94c02d05 100644 --- a/drivers/leds/trigger/ledtrig-netdev.c +++ b/drivers/leds/trigger/ledtrig-netdev.c @@ -301,11 +301,11 @@ static int netdev_trig_notify(struct notifier_block *nb, 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 notifier_block *nb, 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: -- cgit v1.2.3 From 0aab8e4df4702b31314a27ec4b0631dfad0fae0a Mon Sep 17 00:00:00 2001 From: Kangjie Lu Date: Sat, 9 Mar 2019 00:04:11 -0600 Subject: leds: pca9532: fix a potential NULL pointer dereference In case of_match_device cannot find a match, return -EINVAL to avoid NULL pointer dereference. Fixes: fa4191a609f2 ("leds: pca9532: Add device tree support") Signed-off-by: Kangjie Lu Signed-off-by: Jacek Anaszewski --- drivers/leds/leds-pca9532.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/leds/leds-pca9532.c b/drivers/leds/leds-pca9532.c index 7fea18b0c15d..7cb4d685a1f1 100644 --- a/drivers/leds/leds-pca9532.c +++ b/drivers/leds/leds-pca9532.c @@ -513,6 +513,7 @@ static int pca9532_probe(struct i2c_client *client, const struct i2c_device_id *id) { int devid; + const struct of_device_id *of_id; struct pca9532_data *data = i2c_get_clientdata(client); struct pca9532_platform_data *pca9532_pdata = dev_get_platdata(&client->dev); @@ -528,8 +529,11 @@ static int pca9532_probe(struct i2c_client *client, dev_err(&client->dev, "no platform data\n"); return -EINVAL; } - devid = (int)(uintptr_t)of_match_device( - of_pca9532_leds_match, &client->dev)->data; + of_id = of_match_device(of_pca9532_leds_match, + &client->dev); + if (unlikely(!of_id)) + return -EINVAL; + devid = (int)(uintptr_t) of_id->data; } else { devid = id->driver_data; } -- cgit v1.2.3 From 909346433064b8d840dc82af26161926b8d37558 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Thu, 14 Mar 2019 15:06:14 +0100 Subject: leds: trigger: netdev: use memcpy in device_name_store If userspace doesn't end the input with a newline (which can easily happen if the write happens from a C program that does write(fd, iface, strlen(iface))), we may end up including garbage from a previous, longer value in the device_name. For example # cat device_name # printf 'eth12' > device_name # cat device_name eth12 # printf 'eth3' > device_name # cat device_name eth32 I highly doubt anybody is relying on this behaviour, so switch to simply copying the bytes (we've already checked that size is < IFNAMSIZ) and unconditionally zero-terminate it; of course, we also still have to strip a trailing newline. This is also preparation for future patches. Fixes: 06f502f57d0d ("leds: trigger: Introduce a NETDEV trigger") Signed-off-by: Rasmus Villemoes Acked-by: Pavel Machek Signed-off-by: Jacek Anaszewski --- drivers/leds/trigger/ledtrig-netdev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/leds/trigger/ledtrig-netdev.c b/drivers/leds/trigger/ledtrig-netdev.c index 167a94c02d05..136f86a1627d 100644 --- a/drivers/leds/trigger/ledtrig-netdev.c +++ b/drivers/leds/trigger/ledtrig-netdev.c @@ -122,7 +122,8 @@ static ssize_t device_name_store(struct device *dev, trigger_data->net_dev = NULL; } - strncpy(trigger_data->device_name, buf, size); + memcpy(trigger_data->device_name, buf, size); + trigger_data->device_name[size] = 0; if (size > 0 && trigger_data->device_name[size - 1] == '\n') trigger_data->device_name[size - 1] = 0; -- cgit v1.2.3