diff options
| author | Sean Young <sean@mess.org> | 2017-08-04 10:12:03 -0400 |
|---|---|---|
| committer | Mauro Carvalho Chehab <mchehab@s-opensource.com> | 2017-09-05 07:28:59 -0400 |
| commit | a607f51e5a4c421e2097077db88105402099c528 (patch) | |
| tree | 0dee9497f7ef5aa3d574aca4eb6951c1c64aea0a /drivers | |
| parent | 0865c7429ed54876d01128030873b375778bf639 (diff) | |
media: Revert "[media] lirc_dev: remove superfluous get/put_device() calls"
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
Cc: stable@vger.kernel.org # For Kernel 4.13
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>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/media/rc/lirc_dev.c | 4 |
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) | |||
| 59 | { | 59 | { |
| 60 | struct irctl *ir = container_of(ld, struct irctl, dev); | 60 | struct irctl *ir = container_of(ld, struct irctl, dev); |
| 61 | 61 | ||
| 62 | put_device(ir->dev.parent); | ||
| 63 | |||
| 62 | if (ir->buf_internal) { | 64 | if (ir->buf_internal) { |
| 63 | lirc_buffer_free(ir->buf); | 65 | lirc_buffer_free(ir->buf); |
| 64 | kfree(ir->buf); | 66 | kfree(ir->buf); |
| @@ -218,6 +220,8 @@ int lirc_register_driver(struct lirc_driver *d) | |||
| 218 | 220 | ||
| 219 | mutex_unlock(&lirc_dev_lock); | 221 | mutex_unlock(&lirc_dev_lock); |
| 220 | 222 | ||
| 223 | get_device(ir->dev.parent); | ||
| 224 | |||
| 221 | dev_info(ir->d.dev, "lirc_dev: driver %s registered at minor = %d\n", | 225 | dev_info(ir->d.dev, "lirc_dev: driver %s registered at minor = %d\n", |
| 222 | ir->d.name, ir->d.minor); | 226 | ir->d.name, ir->d.minor); |
| 223 | 227 | ||
