aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSean Young <sean@mess.org>2020-08-08 13:19:12 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-09-09 19:14:29 +0200
commit9af0c46a761293ef04c57f001cc2641d4ec1add3 (patch)
treefd3c832fa1ca3361b40fe82f02fcd795a2820a3c
parentbff924ee40ae3857e7373536fdda203378795e3c (diff)
downloadlinux-yocto-9af0c46a761293ef04c57f001cc2641d4ec1add3.tar.gz
linux-yocto-9af0c46a761293ef04c57f001cc2641d4ec1add3.tar.bz2
linux-yocto-9af0c46a761293ef04c57f001cc2641d4ec1add3.zip
media: rc: uevent sysfs file races with rc_unregister_device()
commit 4f0835d6677dc69263f90f976524cb92b257d9f4 upstream. Only report uevent file contents if device still registered, else we might read freed memory. Reported-by: syzbot+ceef16277388d6f24898@syzkaller.appspotmail.com Cc: Hillf Danton <hdanton@sina.com> Cc: <stable@vger.kernel.org> # 4.16+ Signed-off-by: Sean Young <sean@mess.org> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/media/rc/rc-main.c32
1 files changed, 16 insertions, 16 deletions
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index ae154a667fe0..38aa0c2de243 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -1613,25 +1613,25 @@ static void rc_dev_release(struct device *device)
kfree(dev);
}
-#define ADD_HOTPLUG_VAR(fmt, val...) \
- do { \
- int err = add_uevent_var(env, fmt, val); \
- if (err) \
- return err; \
- } while (0)
-
static int rc_dev_uevent(struct device *device, struct kobj_uevent_env *env)
{
struct rc_dev *dev = to_rc_dev(device);
+ int ret = 0;
- if (dev->rc_map.name)
- ADD_HOTPLUG_VAR("NAME=%s", dev->rc_map.name);
- if (dev->driver_name)
- ADD_HOTPLUG_VAR("DRV_NAME=%s", dev->driver_name);
- if (dev->device_name)
- ADD_HOTPLUG_VAR("DEV_NAME=%s", dev->device_name);
+ mutex_lock(&dev->lock);
- return 0;
+ if (!dev->registered)
+ ret = -ENODEV;
+ if (ret == 0 && dev->rc_map.name)
+ ret = add_uevent_var(env, "NAME=%s", dev->rc_map.name);
+ if (ret == 0 && dev->driver_name)
+ ret = add_uevent_var(env, "DRV_NAME=%s", dev->driver_name);
+ if (ret == 0 && dev->device_name)
+ ret = add_uevent_var(env, "DEV_NAME=%s", dev->device_name);
+
+ mutex_unlock(&dev->lock);
+
+ return ret;
}
/*
@@ -2023,14 +2023,14 @@ void rc_unregister_device(struct rc_dev *dev)
del_timer_sync(&dev->timer_keyup);
del_timer_sync(&dev->timer_repeat);
- rc_free_rx_device(dev);
-
mutex_lock(&dev->lock);
if (dev->users && dev->close)
dev->close(dev);
dev->registered = false;
mutex_unlock(&dev->lock);
+ rc_free_rx_device(dev);
+
/*
* lirc device should be freed with dev->registered = false, so
* that userspace polling will get notified.