Commit 4f0835d6 authored by Sean Young's avatar Sean Young Committed by Mauro Carvalho Chehab

media: rc: uevent sysfs file races with rc_unregister_device()

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: default avatarSean Young <sean@mess.org>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+huawei@kernel.org>
parent 8a30c017
...@@ -1601,25 +1601,25 @@ static void rc_dev_release(struct device *device) ...@@ -1601,25 +1601,25 @@ static void rc_dev_release(struct device *device)
kfree(dev); 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) static int rc_dev_uevent(struct device *device, struct kobj_uevent_env *env)
{ {
struct rc_dev *dev = to_rc_dev(device); struct rc_dev *dev = to_rc_dev(device);
int ret = 0;
if (dev->rc_map.name) mutex_lock(&dev->lock);
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);
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;
} }
/* /*
...@@ -2011,14 +2011,14 @@ void rc_unregister_device(struct rc_dev *dev) ...@@ -2011,14 +2011,14 @@ void rc_unregister_device(struct rc_dev *dev)
del_timer_sync(&dev->timer_keyup); del_timer_sync(&dev->timer_keyup);
del_timer_sync(&dev->timer_repeat); del_timer_sync(&dev->timer_repeat);
rc_free_rx_device(dev);
mutex_lock(&dev->lock); mutex_lock(&dev->lock);
if (dev->users && dev->close) if (dev->users && dev->close)
dev->close(dev); dev->close(dev);
dev->registered = false; dev->registered = false;
mutex_unlock(&dev->lock); mutex_unlock(&dev->lock);
rc_free_rx_device(dev);
/* /*
* lirc device should be freed with dev->registered = false, so * lirc device should be freed with dev->registered = false, so
* that userspace polling will get notified. * that userspace polling will get notified.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment