Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2d89e44d authored by Sean Young's avatar Sean Young Committed by Greg Kroah-Hartman
Browse files

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: default avatar <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>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 5925179b
Loading
Loading
Loading
Loading
+16 −16
Original line number Original line Diff line number Diff line
@@ -1577,25 +1577,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;
}
}


/*
/*
@@ -1987,14 +1987,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.