From: Max Kellermann Date: Tue, 9 Aug 2016 21:32:06 +0000 (-0300) Subject: [media] rc-main: clear rc_map.name in ir_free_table() X-Git-Tag: v4.14-rc1~332^2~1124 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c183d3584b1777be55b4c576385143210dc0dbd5;p=platform%2Fkernel%2Flinux-rpi.git [media] rc-main: clear rc_map.name in ir_free_table() rc_unregister_device() will first call ir_free_table(), and later device_del(); however, the latter causes a call to rc_dev_uevent(), which prints rc_map.name, which at this point has already bee freed. This fixes a use-after-free bug found with KASAN. As reported by Shuah: "I am seeing the following when I do rmmod on au0828 BUG: KASAN: use-after-free in string+0x170/0x1f0 at addr ffff8801bd513000 Read of size 1 by task rmmod/1831 CPU: 1 PID: 1831 Comm: rmmod Tainted: G W 4.9.0-rc5 #5 Hardware name: Hewlett-Packard HP ProBook 6475b/180F, BIOS 68TTU Ver. F.04 08/03/2012 ffff8801aea2f680 ffffffff81b37ad3 ffff8801fa403b80 ffff8801bd513000 ffff8801aea2f6a8 ffffffff8156c301 ffff8801aea2f738 ffff8801bd513000 ffff8801fa403b80 ffff8801aea2f728 ffffffff8156c59a ffff8801aea2f770 Call Trace: dump_stack+0x67/0x94 [] kasan_object_err+0x21/0x70 [] kasan_report_error+0x1fa/0x4d0 [] ? au0828_exit+0x10/0x21 [au0828] [] __asan_report_load1_noabort+0x43/0x50 [] ? string+0x170/0x1f0 [] string+0x170/0x1f0 [] vsnprintf+0x374/0x1c50 [] ? pointer+0xa80/0xa80 [] ? save_stack+0x46/0xd0 [] ? __kmalloc+0x14a/0x2a0 [] ? kobject_get_path+0x9a/0x200 [] ? kobject_uevent_env+0x282/0xca0 [] ? kobject_uevent+0xb/0x10 [] ? device_del+0x434/0x6d0 [] ? rc_unregister_device+0x177/0x240 [rc_core] [] ? au0828_rc_unregister+0x60/0xb0 [au0828] The problem is fixed with this patch on Linux 4.9-rc4" Signed-off-by: Max Kellermann Tested-by: Shuah Khan Signed-off-by: Mauro Carvalho Chehab --- diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index adb10fa..dedaf38 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -161,6 +161,7 @@ static void ir_free_table(struct rc_map *rc_map) { rc_map->size = 0; kfree(rc_map->name); + rc_map->name = NULL; kfree(rc_map->scan); rc_map->scan = NULL; }