summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorSean Young <sean@mess.org>2017-08-04 10:12:03 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-09-27 14:43:20 +0200
commite2204d254f27087a71e58d371b2a60bddf3e7c54 (patch)
treec4385bc0685a4714aa8afebba80463b2eafc99d6 /drivers
parenta0416c1e96556d59de02b672b574994572a38444 (diff)
media: Revert "[media] lirc_dev: remove superfluous get/put_device() calls"
commit a607f51e5a4c421e2097077db88105402099c528 upstream. This reverts commit 5be2b76a9ca4ea5fd3e221114d62eeb0d78267ca. Only when the lirc device is freed, should we drop our reference to rc_dev, else we the rc_dev is freed to early. If userspace has a file descriptor open during unplug, it goes bang. ================================================================== BUG: KASAN: use-after-free in __lock_acquire+0x7bb/0x1e10 Read of size 8 at addr ffff8801d7d61ed0 by task ir-rec/2609 -snip- mutex_lock_nested+0x1b/0x20 ? mutex_lock_nested+0x1b/0x20 rc_close.part.6+0x20/0x60 [rc_core] rc_close+0x13/0x20 [rc_core] lirc_dev_fop_close+0x62/0xd0 [lirc_dev] __fput+0x236/0x410 ? fput+0xb0/0xb0 ? do_raw_spin_trylock+0x110/0x110 ? set_rq_offline.part.70+0xa0/0xa0 ____fput+0xe/0x10 task_work_run+0x116/0x180 ? task_work_cancel+0x170/0x170 ? _raw_spin_unlock+0x27/0x40 ? switch_task_namespaces+0x5f/0x90 do_exit+0x68b/0xe80 Fixes: 5be2b76a9ca4 ("[media] lirc_dev: remove superfluous get/put_device() calls") Signed-off-by: Sean Young <sean@mess.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/rc/lirc_dev.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
index db1e7b70c998..9080e39ea391 100644
--- a/drivers/media/rc/lirc_dev.c
+++ b/drivers/media/rc/lirc_dev.c
@@ -59,6 +59,8 @@ static void lirc_release(struct device *ld)
{
struct irctl *ir = container_of(ld, struct irctl, dev);
+ put_device(ir->dev.parent);
+
if (ir->buf_internal) {
lirc_buffer_free(ir->buf);
kfree(ir->buf);
@@ -218,6 +220,8 @@ int lirc_register_driver(struct lirc_driver *d)
mutex_unlock(&lirc_dev_lock);
+ get_device(ir->dev.parent);
+
dev_info(ir->d.dev, "lirc_dev: driver %s registered at minor = %d\n",
ir->d.name, ir->d.minor);