All of lore.kernel.org
 help / color / mirror / Atom feed
* usb/media/dtt200u: use-after-free in __dvb_frontend_free
@ 2017-10-23 14:41 Andrey Konovalov
  2017-10-23 18:58 ` Matthias Schwarzott
  2017-10-30  9:58 ` [PATCH] __dvb_frontend_free: Clear frontend_priv earlier Matthias Schwarzott
  0 siblings, 2 replies; 8+ messages in thread
From: Andrey Konovalov @ 2017-10-23 14:41 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Max Kellermann, linux-media, LKML
  Cc: Dmitry Vyukov, Kostya Serebryany, syzkaller

Hi!

I've got the following report while fuzzing the kernel with syzkaller.

On commit 3e0cc09a3a2c40ec1ffb6b4e12da86e98feccb11 (4.14-rc5+).

dvb-usb: found a 'WideView WT-220U PenType Receiver (based on ZL353)'
in warm state.
dvb-usb: bulk message failed: -22 (2/1102416563)
dvb-usb: will use the device's hardware PID filter (table count: 15).
dvbdev: DVB: registering new adapter (WideView WT-220U PenType
Receiver (based on ZL353))
usb 1-1: media controller created
dvbdev: dvb_create_media_entity: media entity 'dvb-demux' registered.
usb 1-1: DVB: registering adapter 0 frontend 0 (WideView USB DVB-T)...
dvbdev: dvb_create_media_entity: media entity 'WideView USB DVB-T' registered.
Registered IR keymap rc-dtt200u
rc rc1: IR-receiver inside an USB DVB receiver as
/devices/platform/dummy_hcd.0/usb1/1-1/rc/rc1
input: IR-receiver inside an USB DVB receiver as
/devices/platform/dummy_hcd.0/usb1/1-1/rc/rc1/input9
dvb-usb: schedule remote query interval to 300 msecs.
dvb-usb: WideView WT-220U PenType Receiver (based on ZL353)
successfully initialized and connected.
dvb-usb: bulk message failed: -22 (1/1807119384)
dvb-usb: error -22 while querying for an remote control event.
dvb-usb: bulk message failed: -22 (1/1807119384)
dvb-usb: error -22 while querying for an remote control event.
dvb-usb: bulk message failed: -22 (1/1807119384)
dvb-usb: error -22 while querying for an remote control event.
dvb-usb: bulk message failed: -22 (1/1807119384)
dvb-usb: error -22 while querying for an remote control event.
dvb-usb: bulk message failed: -22 (1/1807119384)
dvb-usb: error -22 while querying for an remote control event.
dvb-usb: bulk message failed: -22 (1/1807119384)
dvb-usb: error -22 while querying for an remote control event.
usb 1-1: USB disconnect, device number 2
==================================================================
BUG: KASAN: use-after-free in __dvb_frontend_free+0x113/0x120
Write of size 8 at addr ffff880067d45a00 by task kworker/0:1/24

CPU: 0 PID: 24 Comm: kworker/0:1 Not tainted 4.14.0-rc5-43687-g06ab8a23e0e6 #545
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
Workqueue: usb_hub_wq hub_event
Call Trace:
 __dump_stack lib/dump_stack.c:16
 dump_stack+0x292/0x395 lib/dump_stack.c:52
 print_address_description+0x78/0x280 mm/kasan/report.c:252
 kasan_report_error mm/kasan/report.c:351
 kasan_report+0x23d/0x350 mm/kasan/report.c:409
 __asan_report_store8_noabort+0x1c/0x20 mm/kasan/report.c:435
 __dvb_frontend_free+0x113/0x120 drivers/media/dvb-core/dvb_frontend.c:156
 dvb_frontend_put+0x59/0x70 drivers/media/dvb-core/dvb_frontend.c:176
 dvb_frontend_detach+0x120/0x150 drivers/media/dvb-core/dvb_frontend.c:2803
 dvb_usb_adapter_frontend_exit+0xd6/0x160
drivers/media/usb/dvb-usb/dvb-usb-dvb.c:340
 dvb_usb_adapter_exit drivers/media/usb/dvb-usb/dvb-usb-init.c:116
 dvb_usb_exit+0x9b/0x200 drivers/media/usb/dvb-usb/dvb-usb-init.c:132
 dvb_usb_device_exit+0xa5/0xf0 drivers/media/usb/dvb-usb/dvb-usb-init.c:295
 usb_unbind_interface+0x21c/0xa90 drivers/usb/core/driver.c:423
 __device_release_driver drivers/base/dd.c:861
 device_release_driver_internal+0x4f1/0x5c0 drivers/base/dd.c:893
 device_release_driver+0x1e/0x30 drivers/base/dd.c:918
 bus_remove_device+0x2f4/0x4b0 drivers/base/bus.c:565
 device_del+0x5c4/0xab0 drivers/base/core.c:1985
 usb_disable_device+0x1e9/0x680 drivers/usb/core/message.c:1170
 usb_disconnect+0x260/0x7a0 drivers/usb/core/hub.c:2124
 hub_port_connect drivers/usb/core/hub.c:4754
 hub_port_connect_change drivers/usb/core/hub.c:5009
 port_event drivers/usb/core/hub.c:5115
 hub_event+0x1318/0x3740 drivers/usb/core/hub.c:5195
 process_one_work+0xc73/0x1d90 kernel/workqueue.c:2119
 worker_thread+0x221/0x1850 kernel/workqueue.c:2253
 kthread+0x363/0x440 kernel/kthread.c:231
 ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:431

Allocated by task 24:
 save_stack_trace+0x1b/0x20 arch/x86/kernel/stacktrace.c:59
 save_stack+0x43/0xd0 mm/kasan/kasan.c:447
 set_track mm/kasan/kasan.c:459
 kasan_kmalloc+0xad/0xe0 mm/kasan/kasan.c:551
 kmem_cache_alloc_trace+0x11e/0x2d0 mm/slub.c:2772
 kmalloc ./include/linux/slab.h:493
 kzalloc ./include/linux/slab.h:666
 dtt200u_fe_attach+0x4c/0x110 drivers/media/usb/dvb-usb/dtt200u-fe.c:212
 dtt200u_frontend_attach+0x35/0x80 drivers/media/usb/dvb-usb/dtt200u.c:136
 dvb_usb_adapter_frontend_init+0x32b/0x660
drivers/media/usb/dvb-usb/dvb-usb-dvb.c:286
 dvb_usb_adapter_init drivers/media/usb/dvb-usb/dvb-usb-init.c:86
 dvb_usb_init drivers/media/usb/dvb-usb/dvb-usb-init.c:162
 dvb_usb_device_init+0xf73/0x17f0 drivers/media/usb/dvb-usb/dvb-usb-init.c:277
 dtt200u_usb_probe+0xa1/0xe0 drivers/media/usb/dvb-usb/dtt200u.c:155
 usb_probe_interface+0x35d/0x8e0 drivers/usb/core/driver.c:361
 really_probe drivers/base/dd.c:413
 driver_probe_device+0x610/0xa00 drivers/base/dd.c:557
 __device_attach_driver+0x230/0x290 drivers/base/dd.c:653
 bus_for_each_drv+0x161/0x210 drivers/base/bus.c:463
 __device_attach+0x26b/0x3c0 drivers/base/dd.c:710
 device_initial_probe+0x1f/0x30 drivers/base/dd.c:757
 bus_probe_device+0x1eb/0x290 drivers/base/bus.c:523
 device_add+0xd0b/0x1660 drivers/base/core.c:1835
 usb_set_configuration+0x104e/0x1870 drivers/usb/core/message.c:1932
 generic_probe+0x73/0xe0 drivers/usb/core/generic.c:174
 usb_probe_device+0xaf/0xe0 drivers/usb/core/driver.c:266
 really_probe drivers/base/dd.c:413
 driver_probe_device+0x610/0xa00 drivers/base/dd.c:557
 __device_attach_driver+0x230/0x290 drivers/base/dd.c:653
 bus_for_each_drv+0x161/0x210 drivers/base/bus.c:463
 __device_attach+0x26b/0x3c0 drivers/base/dd.c:710
 device_initial_probe+0x1f/0x30 drivers/base/dd.c:757
 bus_probe_device+0x1eb/0x290 drivers/base/bus.c:523
 device_add+0xd0b/0x1660 drivers/base/core.c:1835
 usb_new_device+0x7b8/0x1020 drivers/usb/core/hub.c:2457
 hub_port_connect drivers/usb/core/hub.c:4903
 hub_port_connect_change drivers/usb/core/hub.c:5009
 port_event drivers/usb/core/hub.c:5115
 hub_event+0x194d/0x3740 drivers/usb/core/hub.c:5195
 process_one_work+0xc73/0x1d90 kernel/workqueue.c:2119
 worker_thread+0x221/0x1850 kernel/workqueue.c:2253
 kthread+0x363/0x440 kernel/kthread.c:231
 ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:431

Freed by task 24:
 save_stack_trace+0x1b/0x20 arch/x86/kernel/stacktrace.c:59
 save_stack+0x43/0xd0 mm/kasan/kasan.c:447
 set_track mm/kasan/kasan.c:459
 kasan_slab_free+0x72/0xc0 mm/kasan/kasan.c:524
 slab_free_hook mm/slub.c:1390
 slab_free_freelist_hook mm/slub.c:1412
 slab_free mm/slub.c:2988
 kfree+0xf6/0x2f0 mm/slub.c:3919
 dtt200u_fe_release+0x3c/0x50 drivers/media/usb/dvb-usb/dtt200u-fe.c:202
 dvb_frontend_invoke_release.part.13+0x1c/0x30
drivers/media/dvb-core/dvb_frontend.c:2790
 dvb_frontend_invoke_release drivers/media/dvb-core/dvb_frontend.c:2789
 __dvb_frontend_free+0xad/0x120 drivers/media/dvb-core/dvb_frontend.c:153
 dvb_frontend_put+0x59/0x70 drivers/media/dvb-core/dvb_frontend.c:176
 dvb_frontend_detach+0x120/0x150 drivers/media/dvb-core/dvb_frontend.c:2803
 dvb_usb_adapter_frontend_exit+0xd6/0x160
drivers/media/usb/dvb-usb/dvb-usb-dvb.c:340
 dvb_usb_adapter_exit drivers/media/usb/dvb-usb/dvb-usb-init.c:116
 dvb_usb_exit+0x9b/0x200 drivers/media/usb/dvb-usb/dvb-usb-init.c:132
 dvb_usb_device_exit+0xa5/0xf0 drivers/media/usb/dvb-usb/dvb-usb-init.c:295
 usb_unbind_interface+0x21c/0xa90 drivers/usb/core/driver.c:423
 __device_release_driver drivers/base/dd.c:861
 device_release_driver_internal+0x4f1/0x5c0 drivers/base/dd.c:893
 device_release_driver+0x1e/0x30 drivers/base/dd.c:918
 bus_remove_device+0x2f4/0x4b0 drivers/base/bus.c:565
 device_del+0x5c4/0xab0 drivers/base/core.c:1985
 usb_disable_device+0x1e9/0x680 drivers/usb/core/message.c:1170
 usb_disconnect+0x260/0x7a0 drivers/usb/core/hub.c:2124
 hub_port_connect drivers/usb/core/hub.c:4754
 hub_port_connect_change drivers/usb/core/hub.c:5009
 port_event drivers/usb/core/hub.c:5115
 hub_event+0x1318/0x3740 drivers/usb/core/hub.c:5195
 process_one_work+0xc73/0x1d90 kernel/workqueue.c:2119
 worker_thread+0x221/0x1850 kernel/workqueue.c:2253
 kthread+0x363/0x440 kernel/kthread.c:231
 ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:431

The buggy address belongs to the object at ffff880067d45500
 which belongs to the cache kmalloc-2048 of size 2048
The buggy address is located 1280 bytes inside of
 2048-byte region [ffff880067d45500, ffff880067d45d00)
The buggy address belongs to the page:
page:ffffea00019f5000 count:1 mapcount:0 mapping:          (null)
index:0x0 compound_mapcount: 0
flags: 0x100000000008100(slab|head)
raw: 0100000000008100 0000000000000000 0000000000000000 00000001000f000f
raw: dead000000000100 dead000000000200 ffff88006c002d80 0000000000000000
page dumped because: kasan: bad access detected

Memory state around the buggy address:
 ffff880067d45900: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
 ffff880067d45980: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
>ffff880067d45a00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
                   ^
 ffff880067d45a80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
 ffff880067d45b00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
==================================================================

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: usb/media/dtt200u: use-after-free in __dvb_frontend_free
  2017-10-23 14:41 usb/media/dtt200u: use-after-free in __dvb_frontend_free Andrey Konovalov
@ 2017-10-23 18:58 ` Matthias Schwarzott
  2017-10-24 11:19   ` Andrey Konovalov
  2017-11-07 10:31   ` Mauro Carvalho Chehab
  2017-10-30  9:58 ` [PATCH] __dvb_frontend_free: Clear frontend_priv earlier Matthias Schwarzott
  1 sibling, 2 replies; 8+ messages in thread
From: Matthias Schwarzott @ 2017-10-23 18:58 UTC (permalink / raw)
  To: Andrey Konovalov, Mauro Carvalho Chehab, Max Kellermann,
	linux-media, LKML
  Cc: Dmitry Vyukov, Kostya Serebryany, syzkaller

Am 23.10.2017 um 16:41 schrieb Andrey Konovalov:
> Hi!
> 
> I've got the following report while fuzzing the kernel with syzkaller.
> 
> On commit 3e0cc09a3a2c40ec1ffb6b4e12da86e98feccb11 (4.14-rc5+).
> 
> dvb-usb: found a 'WideView WT-220U PenType Receiver (based on ZL353)'
> in warm state.
> dvb-usb: bulk message failed: -22 (2/1102416563)
> dvb-usb: will use the device's hardware PID filter (table count: 15).
> dvbdev: DVB: registering new adapter (WideView WT-220U PenType
> Receiver (based on ZL353))
> usb 1-1: media controller created
> dvbdev: dvb_create_media_entity: media entity 'dvb-demux' registered.
> usb 1-1: DVB: registering adapter 0 frontend 0 (WideView USB DVB-T)...
> dvbdev: dvb_create_media_entity: media entity 'WideView USB DVB-T' registered.
> Registered IR keymap rc-dtt200u
> rc rc1: IR-receiver inside an USB DVB receiver as
> /devices/platform/dummy_hcd.0/usb1/1-1/rc/rc1
> input: IR-receiver inside an USB DVB receiver as
> /devices/platform/dummy_hcd.0/usb1/1-1/rc/rc1/input9
> dvb-usb: schedule remote query interval to 300 msecs.
> dvb-usb: WideView WT-220U PenType Receiver (based on ZL353)
> successfully initialized and connected.
> dvb-usb: bulk message failed: -22 (1/1807119384)
> dvb-usb: error -22 while querying for an remote control event.
> dvb-usb: bulk message failed: -22 (1/1807119384)
> dvb-usb: error -22 while querying for an remote control event.
> dvb-usb: bulk message failed: -22 (1/1807119384)
> dvb-usb: error -22 while querying for an remote control event.
> dvb-usb: bulk message failed: -22 (1/1807119384)
> dvb-usb: error -22 while querying for an remote control event.
> dvb-usb: bulk message failed: -22 (1/1807119384)
> dvb-usb: error -22 while querying for an remote control event.
> dvb-usb: bulk message failed: -22 (1/1807119384)
> dvb-usb: error -22 while querying for an remote control event.
> usb 1-1: USB disconnect, device number 2
> ==================================================================
> BUG: KASAN: use-after-free in __dvb_frontend_free+0x113/0x120
> Write of size 8 at addr ffff880067d45a00 by task kworker/0:1/24
> 
> CPU: 0 PID: 24 Comm: kworker/0:1 Not tainted 4.14.0-rc5-43687-g06ab8a23e0e6 #545
> Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
> Workqueue: usb_hub_wq hub_event
> Call Trace:
>  __dump_stack lib/dump_stack.c:16
>  dump_stack+0x292/0x395 lib/dump_stack.c:52
>  print_address_description+0x78/0x280 mm/kasan/report.c:252
>  kasan_report_error mm/kasan/report.c:351
>  kasan_report+0x23d/0x350 mm/kasan/report.c:409
>  __asan_report_store8_noabort+0x1c/0x20 mm/kasan/report.c:435
>  __dvb_frontend_free+0x113/0x120 drivers/media/dvb-core/dvb_frontend.c:156
>  dvb_frontend_put+0x59/0x70 drivers/media/dvb-core/dvb_frontend.c:176
>  dvb_frontend_detach+0x120/0x150 drivers/media/dvb-core/dvb_frontend.c:2803
>  dvb_usb_adapter_frontend_exit+0xd6/0x160
> drivers/media/usb/dvb-usb/dvb-usb-dvb.c:340
>  dvb_usb_adapter_exit drivers/media/usb/dvb-usb/dvb-usb-init.c:116
>  dvb_usb_exit+0x9b/0x200 drivers/media/usb/dvb-usb/dvb-usb-init.c:132
>  dvb_usb_device_exit+0xa5/0xf0 drivers/media/usb/dvb-usb/dvb-usb-init.c:295
>  usb_unbind_interface+0x21c/0xa90 drivers/usb/core/driver.c:423
>  __device_release_driver drivers/base/dd.c:861
>  device_release_driver_internal+0x4f1/0x5c0 drivers/base/dd.c:893
>  device_release_driver+0x1e/0x30 drivers/base/dd.c:918
>  bus_remove_device+0x2f4/0x4b0 drivers/base/bus.c:565
>  device_del+0x5c4/0xab0 drivers/base/core.c:1985
>  usb_disable_device+0x1e9/0x680 drivers/usb/core/message.c:1170
>  usb_disconnect+0x260/0x7a0 drivers/usb/core/hub.c:2124
>  hub_port_connect drivers/usb/core/hub.c:4754
>  hub_port_connect_change drivers/usb/core/hub.c:5009
>  port_event drivers/usb/core/hub.c:5115
>  hub_event+0x1318/0x3740 drivers/usb/core/hub.c:5195
>  process_one_work+0xc73/0x1d90 kernel/workqueue.c:2119
>  worker_thread+0x221/0x1850 kernel/workqueue.c:2253
>  kthread+0x363/0x440 kernel/kthread.c:231
>  ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:431
> 
It looks like this is caused by commit
ead666000a5fe34bdc82d61838e4df2d416ea15e ("media: dvb_frontend: only use
kref after initialized").

The writing to "fe->frontend_priv" in dvb_frontend.c:156 is a
use-after-free in case the object dvb_frontend *fe is already freed by
the release callback called in line 153.
Only if the demod driver is based on new style i2c_client the memory is
still accessible.

There are two possible solutions:
1. Clear fe->frontend_priv earlier (before line 153).
2. Do not clear fe->frontend_priv

Can you try if the following patch (solution 1) fixes the issue?

Regards
Matthias

diff --git a/drivers/media/dvb-core/dvb_frontend.c
b/drivers/media/dvb-core/dvb_frontend.c
index daaf969719e4..f552acdb7d8c 100644
--- a/drivers/media/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb-core/dvb_frontend.c
@@ -150,10 +150,11 @@ static void __dvb_frontend_free(struct
dvb_frontend *fe)

        dvb_free_device(fepriv->dvbdev);

+       fe->frontend_priv = NULL;
+
        dvb_frontend_invoke_release(fe, fe->ops.release);

        kfree(fepriv);
-       fe->frontend_priv = NULL;
 }

 static void dvb_frontend_free(struct kref *ref)

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: usb/media/dtt200u: use-after-free in __dvb_frontend_free
  2017-10-23 18:58 ` Matthias Schwarzott
@ 2017-10-24 11:19   ` Andrey Konovalov
  2017-11-07 10:31   ` Mauro Carvalho Chehab
  1 sibling, 0 replies; 8+ messages in thread
From: Andrey Konovalov @ 2017-10-24 11:19 UTC (permalink / raw)
  To: Matthias Schwarzott
  Cc: Mauro Carvalho Chehab, Max Kellermann, linux-media, LKML,
	Dmitry Vyukov, Kostya Serebryany, syzkaller

On Mon, Oct 23, 2017 at 8:58 PM, Matthias Schwarzott <zzam@gentoo.org> wrote:
> Am 23.10.2017 um 16:41 schrieb Andrey Konovalov:
>> Hi!
>>
>> I've got the following report while fuzzing the kernel with syzkaller.
>>
>> On commit 3e0cc09a3a2c40ec1ffb6b4e12da86e98feccb11 (4.14-rc5+).
>>
>> dvb-usb: found a 'WideView WT-220U PenType Receiver (based on ZL353)'
>> in warm state.
>> dvb-usb: bulk message failed: -22 (2/1102416563)
>> dvb-usb: will use the device's hardware PID filter (table count: 15).
>> dvbdev: DVB: registering new adapter (WideView WT-220U PenType
>> Receiver (based on ZL353))
>> usb 1-1: media controller created
>> dvbdev: dvb_create_media_entity: media entity 'dvb-demux' registered.
>> usb 1-1: DVB: registering adapter 0 frontend 0 (WideView USB DVB-T)...
>> dvbdev: dvb_create_media_entity: media entity 'WideView USB DVB-T' registered.
>> Registered IR keymap rc-dtt200u
>> rc rc1: IR-receiver inside an USB DVB receiver as
>> /devices/platform/dummy_hcd.0/usb1/1-1/rc/rc1
>> input: IR-receiver inside an USB DVB receiver as
>> /devices/platform/dummy_hcd.0/usb1/1-1/rc/rc1/input9
>> dvb-usb: schedule remote query interval to 300 msecs.
>> dvb-usb: WideView WT-220U PenType Receiver (based on ZL353)
>> successfully initialized and connected.
>> dvb-usb: bulk message failed: -22 (1/1807119384)
>> dvb-usb: error -22 while querying for an remote control event.
>> dvb-usb: bulk message failed: -22 (1/1807119384)
>> dvb-usb: error -22 while querying for an remote control event.
>> dvb-usb: bulk message failed: -22 (1/1807119384)
>> dvb-usb: error -22 while querying for an remote control event.
>> dvb-usb: bulk message failed: -22 (1/1807119384)
>> dvb-usb: error -22 while querying for an remote control event.
>> dvb-usb: bulk message failed: -22 (1/1807119384)
>> dvb-usb: error -22 while querying for an remote control event.
>> dvb-usb: bulk message failed: -22 (1/1807119384)
>> dvb-usb: error -22 while querying for an remote control event.
>> usb 1-1: USB disconnect, device number 2
>> ==================================================================
>> BUG: KASAN: use-after-free in __dvb_frontend_free+0x113/0x120
>> Write of size 8 at addr ffff880067d45a00 by task kworker/0:1/24
>>
>> CPU: 0 PID: 24 Comm: kworker/0:1 Not tainted 4.14.0-rc5-43687-g06ab8a23e0e6 #545
>> Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
>> Workqueue: usb_hub_wq hub_event
>> Call Trace:
>>  __dump_stack lib/dump_stack.c:16
>>  dump_stack+0x292/0x395 lib/dump_stack.c:52
>>  print_address_description+0x78/0x280 mm/kasan/report.c:252
>>  kasan_report_error mm/kasan/report.c:351
>>  kasan_report+0x23d/0x350 mm/kasan/report.c:409
>>  __asan_report_store8_noabort+0x1c/0x20 mm/kasan/report.c:435
>>  __dvb_frontend_free+0x113/0x120 drivers/media/dvb-core/dvb_frontend.c:156
>>  dvb_frontend_put+0x59/0x70 drivers/media/dvb-core/dvb_frontend.c:176
>>  dvb_frontend_detach+0x120/0x150 drivers/media/dvb-core/dvb_frontend.c:2803
>>  dvb_usb_adapter_frontend_exit+0xd6/0x160
>> drivers/media/usb/dvb-usb/dvb-usb-dvb.c:340
>>  dvb_usb_adapter_exit drivers/media/usb/dvb-usb/dvb-usb-init.c:116
>>  dvb_usb_exit+0x9b/0x200 drivers/media/usb/dvb-usb/dvb-usb-init.c:132
>>  dvb_usb_device_exit+0xa5/0xf0 drivers/media/usb/dvb-usb/dvb-usb-init.c:295
>>  usb_unbind_interface+0x21c/0xa90 drivers/usb/core/driver.c:423
>>  __device_release_driver drivers/base/dd.c:861
>>  device_release_driver_internal+0x4f1/0x5c0 drivers/base/dd.c:893
>>  device_release_driver+0x1e/0x30 drivers/base/dd.c:918
>>  bus_remove_device+0x2f4/0x4b0 drivers/base/bus.c:565
>>  device_del+0x5c4/0xab0 drivers/base/core.c:1985
>>  usb_disable_device+0x1e9/0x680 drivers/usb/core/message.c:1170
>>  usb_disconnect+0x260/0x7a0 drivers/usb/core/hub.c:2124
>>  hub_port_connect drivers/usb/core/hub.c:4754
>>  hub_port_connect_change drivers/usb/core/hub.c:5009
>>  port_event drivers/usb/core/hub.c:5115
>>  hub_event+0x1318/0x3740 drivers/usb/core/hub.c:5195
>>  process_one_work+0xc73/0x1d90 kernel/workqueue.c:2119
>>  worker_thread+0x221/0x1850 kernel/workqueue.c:2253
>>  kthread+0x363/0x440 kernel/kthread.c:231
>>  ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:431
>>
> It looks like this is caused by commit
> ead666000a5fe34bdc82d61838e4df2d416ea15e ("media: dvb_frontend: only use
> kref after initialized").
>
> The writing to "fe->frontend_priv" in dvb_frontend.c:156 is a
> use-after-free in case the object dvb_frontend *fe is already freed by
> the release callback called in line 153.
> Only if the demod driver is based on new style i2c_client the memory is
> still accessible.
>
> There are two possible solutions:
> 1. Clear fe->frontend_priv earlier (before line 153).
> 2. Do not clear fe->frontend_priv
>
> Can you try if the following patch (solution 1) fixes the issue?

Hi Matthias,

Your patch fixes the issue.

Thanks!

Tested-by: Andrey Konovalov <andreyknvl@google.com>

>
> Regards
> Matthias
>
> diff --git a/drivers/media/dvb-core/dvb_frontend.c
> b/drivers/media/dvb-core/dvb_frontend.c
> index daaf969719e4..f552acdb7d8c 100644
> --- a/drivers/media/dvb-core/dvb_frontend.c
> +++ b/drivers/media/dvb-core/dvb_frontend.c
> @@ -150,10 +150,11 @@ static void __dvb_frontend_free(struct
> dvb_frontend *fe)
>
>         dvb_free_device(fepriv->dvbdev);
>
> +       fe->frontend_priv = NULL;
> +
>         dvb_frontend_invoke_release(fe, fe->ops.release);
>
>         kfree(fepriv);
> -       fe->frontend_priv = NULL;
>  }
>
>  static void dvb_frontend_free(struct kref *ref)

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH] __dvb_frontend_free: Clear frontend_priv earlier
  2017-10-23 14:41 usb/media/dtt200u: use-after-free in __dvb_frontend_free Andrey Konovalov
  2017-10-23 18:58 ` Matthias Schwarzott
@ 2017-10-30  9:58 ` Matthias Schwarzott
  1 sibling, 0 replies; 8+ messages in thread
From: Matthias Schwarzott @ 2017-10-30  9:58 UTC (permalink / raw)
  To: mchehab, linux-media; +Cc: andreyknvl, Matthias Schwarzott

The writing to "fe->frontend_priv" in dvb_frontend.c:156 is a
use-after-free in case the object pointed to by "dvb_frontend *fe" is already freed by
the release callback called in line 153.
Only if the demod driver is based on new style i2c_client the memory is
still accessible.

There are two possible solutions:
1. Clear fe->frontend_priv earlier (before line 153).
2. Do not clear fe->frontend_priv

This fix is using solution 1.

The KASAN report looks like this (running on kernel 3e0cc09a3a2c40ec1ffb6b4e12da86e98feccb11 (4.14-rc5+)):
==================================================================
BUG: KASAN: use-after-free in __dvb_frontend_free+0x113/0x120
Write of size 8 at addr ffff880067d45a00 by task kworker/0:1/24

CPU: 0 PID: 24 Comm: kworker/0:1 Not tainted 4.14.0-rc5-43687-g06ab8a23e0e6 #545
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
Workqueue: usb_hub_wq hub_event
Call Trace:
 __dump_stack lib/dump_stack.c:16
 dump_stack+0x292/0x395 lib/dump_stack.c:52
 print_address_description+0x78/0x280 mm/kasan/report.c:252
 kasan_report_error mm/kasan/report.c:351
 kasan_report+0x23d/0x350 mm/kasan/report.c:409
 __asan_report_store8_noabort+0x1c/0x20 mm/kasan/report.c:435
 __dvb_frontend_free+0x113/0x120 drivers/media/dvb-core/dvb_frontend.c:156
 dvb_frontend_put+0x59/0x70 drivers/media/dvb-core/dvb_frontend.c:176
 dvb_frontend_detach+0x120/0x150 drivers/media/dvb-core/dvb_frontend.c:2803
 dvb_usb_adapter_frontend_exit+0xd6/0x160 drivers/media/usb/dvb-usb/dvb-usb-dvb.c:340
 dvb_usb_adapter_exit drivers/media/usb/dvb-usb/dvb-usb-init.c:116
 dvb_usb_exit+0x9b/0x200 drivers/media/usb/dvb-usb/dvb-usb-init.c:132
 dvb_usb_device_exit+0xa5/0xf0 drivers/media/usb/dvb-usb/dvb-usb-init.c:295
 usb_unbind_interface+0x21c/0xa90 drivers/usb/core/driver.c:423
 __device_release_driver drivers/base/dd.c:861
 device_release_driver_internal+0x4f1/0x5c0 drivers/base/dd.c:893
 device_release_driver+0x1e/0x30 drivers/base/dd.c:918
 bus_remove_device+0x2f4/0x4b0 drivers/base/bus.c:565
 device_del+0x5c4/0xab0 drivers/base/core.c:1985
 usb_disable_device+0x1e9/0x680 drivers/usb/core/message.c:1170
 usb_disconnect+0x260/0x7a0 drivers/usb/core/hub.c:2124
 hub_port_connect drivers/usb/core/hub.c:4754
 hub_port_connect_change drivers/usb/core/hub.c:5009
 port_event drivers/usb/core/hub.c:5115
 hub_event+0x1318/0x3740 drivers/usb/core/hub.c:5195
 process_one_work+0xc73/0x1d90 kernel/workqueue.c:2119
 worker_thread+0x221/0x1850 kernel/workqueue.c:2253
 kthread+0x363/0x440 kernel/kthread.c:231
 ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:431

Allocated by task 24:
 save_stack_trace+0x1b/0x20 arch/x86/kernel/stacktrace.c:59
 save_stack+0x43/0xd0 mm/kasan/kasan.c:447
 set_track mm/kasan/kasan.c:459
 kasan_kmalloc+0xad/0xe0 mm/kasan/kasan.c:551
 kmem_cache_alloc_trace+0x11e/0x2d0 mm/slub.c:2772
 kmalloc ./include/linux/slab.h:493
 kzalloc ./include/linux/slab.h:666
 dtt200u_fe_attach+0x4c/0x110 drivers/media/usb/dvb-usb/dtt200u-fe.c:212
 dtt200u_frontend_attach+0x35/0x80 drivers/media/usb/dvb-usb/dtt200u.c:136
 dvb_usb_adapter_frontend_init+0x32b/0x660 drivers/media/usb/dvb-usb/dvb-usb-dvb.c:286
 dvb_usb_adapter_init drivers/media/usb/dvb-usb/dvb-usb-init.c:86
 dvb_usb_init drivers/media/usb/dvb-usb/dvb-usb-init.c:162
 dvb_usb_device_init+0xf73/0x17f0 drivers/media/usb/dvb-usb/dvb-usb-init.c:277
 dtt200u_usb_probe+0xa1/0xe0 drivers/media/usb/dvb-usb/dtt200u.c:155
 usb_probe_interface+0x35d/0x8e0 drivers/usb/core/driver.c:361
 really_probe drivers/base/dd.c:413
 driver_probe_device+0x610/0xa00 drivers/base/dd.c:557
 __device_attach_driver+0x230/0x290 drivers/base/dd.c:653
 bus_for_each_drv+0x161/0x210 drivers/base/bus.c:463
 __device_attach+0x26b/0x3c0 drivers/base/dd.c:710
 device_initial_probe+0x1f/0x30 drivers/base/dd.c:757
 bus_probe_device+0x1eb/0x290 drivers/base/bus.c:523
 device_add+0xd0b/0x1660 drivers/base/core.c:1835
 usb_set_configuration+0x104e/0x1870 drivers/usb/core/message.c:1932
 generic_probe+0x73/0xe0 drivers/usb/core/generic.c:174
 usb_probe_device+0xaf/0xe0 drivers/usb/core/driver.c:266
 really_probe drivers/base/dd.c:413
 driver_probe_device+0x610/0xa00 drivers/base/dd.c:557
 __device_attach_driver+0x230/0x290 drivers/base/dd.c:653
 bus_for_each_drv+0x161/0x210 drivers/base/bus.c:463
 __device_attach+0x26b/0x3c0 drivers/base/dd.c:710
 device_initial_probe+0x1f/0x30 drivers/base/dd.c:757
 bus_probe_device+0x1eb/0x290 drivers/base/bus.c:523
 device_add+0xd0b/0x1660 drivers/base/core.c:1835
 usb_new_device+0x7b8/0x1020 drivers/usb/core/hub.c:2457
 hub_port_connect drivers/usb/core/hub.c:4903
 hub_port_connect_change drivers/usb/core/hub.c:5009
 port_event drivers/usb/core/hub.c:5115
 hub_event+0x194d/0x3740 drivers/usb/core/hub.c:5195
 process_one_work+0xc73/0x1d90 kernel/workqueue.c:2119
 worker_thread+0x221/0x1850 kernel/workqueue.c:2253
 kthread+0x363/0x440 kernel/kthread.c:231
 ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:431

Freed by task 24:
 save_stack_trace+0x1b/0x20 arch/x86/kernel/stacktrace.c:59
 save_stack+0x43/0xd0 mm/kasan/kasan.c:447
 set_track mm/kasan/kasan.c:459
 kasan_slab_free+0x72/0xc0 mm/kasan/kasan.c:524
 slab_free_hook mm/slub.c:1390
 slab_free_freelist_hook mm/slub.c:1412
 slab_free mm/slub.c:2988
 kfree+0xf6/0x2f0 mm/slub.c:3919
 dtt200u_fe_release+0x3c/0x50 drivers/media/usb/dvb-usb/dtt200u-fe.c:202
 dvb_frontend_invoke_release.part.13+0x1c/0x30 drivers/media/dvb-core/dvb_frontend.c:2790
 dvb_frontend_invoke_release drivers/media/dvb-core/dvb_frontend.c:2789
 __dvb_frontend_free+0xad/0x120 drivers/media/dvb-core/dvb_frontend.c:153
 dvb_frontend_put+0x59/0x70 drivers/media/dvb-core/dvb_frontend.c:176
 dvb_frontend_detach+0x120/0x150 drivers/media/dvb-core/dvb_frontend.c:2803
 dvb_usb_adapter_frontend_exit+0xd6/0x160 drivers/media/usb/dvb-usb/dvb-usb-dvb.c:340
 dvb_usb_adapter_exit drivers/media/usb/dvb-usb/dvb-usb-init.c:116
 dvb_usb_exit+0x9b/0x200 drivers/media/usb/dvb-usb/dvb-usb-init.c:132
 dvb_usb_device_exit+0xa5/0xf0 drivers/media/usb/dvb-usb/dvb-usb-init.c:295
 usb_unbind_interface+0x21c/0xa90 drivers/usb/core/driver.c:423
 __device_release_driver drivers/base/dd.c:861
 device_release_driver_internal+0x4f1/0x5c0 drivers/base/dd.c:893
 device_release_driver+0x1e/0x30 drivers/base/dd.c:918
 bus_remove_device+0x2f4/0x4b0 drivers/base/bus.c:565
 device_del+0x5c4/0xab0 drivers/base/core.c:1985
 usb_disable_device+0x1e9/0x680 drivers/usb/core/message.c:1170
 usb_disconnect+0x260/0x7a0 drivers/usb/core/hub.c:2124
 hub_port_connect drivers/usb/core/hub.c:4754
 hub_port_connect_change drivers/usb/core/hub.c:5009
 port_event drivers/usb/core/hub.c:5115
 hub_event+0x1318/0x3740 drivers/usb/core/hub.c:5195
 process_one_work+0xc73/0x1d90 kernel/workqueue.c:2119
 worker_thread+0x221/0x1850 kernel/workqueue.c:2253
 kthread+0x363/0x440 kernel/kthread.c:231
 ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:431

The buggy address belongs to the object at ffff880067d45500
 which belongs to the cache kmalloc-2048 of size 2048
The buggy address is located 1280 bytes inside of
 2048-byte region [ffff880067d45500, ffff880067d45d00)
The buggy address belongs to the page:
page:ffffea00019f5000 count:1 mapcount:0 mapping:          (null)
index:0x0 compound_mapcount: 0
flags: 0x100000000008100(slab|head)
raw: 0100000000008100 0000000000000000 0000000000000000 00000001000f000f
raw: dead000000000100 dead000000000200 ffff88006c002d80 0000000000000000
page dumped because: kasan: bad access detected

Memory state around the buggy address:
 ffff880067d45900: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
 ffff880067d45980: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
> ffff880067d45a00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
                   ^
 ffff880067d45a80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
 ffff880067d45b00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
==================================================================

Fixes: ead666000a5f ("media: dvb_frontend: only use kref after initialized")

Reported-by: Andrey Konovalov <andreyknvl@google.com>
Signed-off-by: Matthias Schwarzott <zzam@gentoo.org>
Tested-by: Andrey Konovalov <andreyknvl@google.com>
---
 drivers/media/dvb-core/dvb_frontend.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c
index daaf969719e4..f552acdb7d8c 100644
--- a/drivers/media/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb-core/dvb_frontend.c
@@ -150,10 +150,11 @@ static void __dvb_frontend_free(struct dvb_frontend *fe)
 
 	dvb_free_device(fepriv->dvbdev);
 
+	fe->frontend_priv = NULL;
+
 	dvb_frontend_invoke_release(fe, fe->ops.release);
 
 	kfree(fepriv);
-	fe->frontend_priv = NULL;
 }
 
 static void dvb_frontend_free(struct kref *ref)
-- 
2.14.2

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: usb/media/dtt200u: use-after-free in __dvb_frontend_free
  2017-10-23 18:58 ` Matthias Schwarzott
  2017-10-24 11:19   ` Andrey Konovalov
@ 2017-11-07 10:31   ` Mauro Carvalho Chehab
  2017-11-07 12:51     ` Andrey Konovalov
  1 sibling, 1 reply; 8+ messages in thread
From: Mauro Carvalho Chehab @ 2017-11-07 10:31 UTC (permalink / raw)
  To: Matthias Schwarzott, Andrey Konovalov
  Cc: Mauro Carvalho Chehab, Max Kellermann, linux-media, LKML,
	Dmitry Vyukov, Kostya Serebryany, syzkaller

Em Mon, 23 Oct 2017 20:58:09 +0200
Matthias Schwarzott <zzam@gentoo.org> escreveu:

> Am 23.10.2017 um 16:41 schrieb Andrey Konovalov:
> > Hi!
> > 
> > I've got the following report while fuzzing the kernel with syzkaller.
> > 
> > On commit 3e0cc09a3a2c40ec1ffb6b4e12da86e98feccb11 (4.14-rc5+).
> > 
> > dvb-usb: found a 'WideView WT-220U PenType Receiver (based on ZL353)'
> > in warm state.
> > dvb-usb: bulk message failed: -22 (2/1102416563)
> > dvb-usb: will use the device's hardware PID filter (table count: 15).
> > dvbdev: DVB: registering new adapter (WideView WT-220U PenType
> > Receiver (based on ZL353))
> > usb 1-1: media controller created
> > dvbdev: dvb_create_media_entity: media entity 'dvb-demux' registered.
> > usb 1-1: DVB: registering adapter 0 frontend 0 (WideView USB DVB-T)...
> > dvbdev: dvb_create_media_entity: media entity 'WideView USB DVB-T' registered.
> > Registered IR keymap rc-dtt200u
> > rc rc1: IR-receiver inside an USB DVB receiver as
> > /devices/platform/dummy_hcd.0/usb1/1-1/rc/rc1
> > input: IR-receiver inside an USB DVB receiver as
> > /devices/platform/dummy_hcd.0/usb1/1-1/rc/rc1/input9
> > dvb-usb: schedule remote query interval to 300 msecs.
> > dvb-usb: WideView WT-220U PenType Receiver (based on ZL353)
> > successfully initialized and connected.
> > dvb-usb: bulk message failed: -22 (1/1807119384)
> > dvb-usb: error -22 while querying for an remote control event.
> > dvb-usb: bulk message failed: -22 (1/1807119384)
> > dvb-usb: error -22 while querying for an remote control event.
> > dvb-usb: bulk message failed: -22 (1/1807119384)
> > dvb-usb: error -22 while querying for an remote control event.
> > dvb-usb: bulk message failed: -22 (1/1807119384)
> > dvb-usb: error -22 while querying for an remote control event.
> > dvb-usb: bulk message failed: -22 (1/1807119384)
> > dvb-usb: error -22 while querying for an remote control event.
> > dvb-usb: bulk message failed: -22 (1/1807119384)
> > dvb-usb: error -22 while querying for an remote control event.
> > usb 1-1: USB disconnect, device number 2
> > ==================================================================
> > BUG: KASAN: use-after-free in __dvb_frontend_free+0x113/0x120
> > Write of size 8 at addr ffff880067d45a00 by task kworker/0:1/24
> > 
> > CPU: 0 PID: 24 Comm: kworker/0:1 Not tainted 4.14.0-rc5-43687-g06ab8a23e0e6 #545
> > Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
> > Workqueue: usb_hub_wq hub_event
> > Call Trace:
> >  __dump_stack lib/dump_stack.c:16
> >  dump_stack+0x292/0x395 lib/dump_stack.c:52
> >  print_address_description+0x78/0x280 mm/kasan/report.c:252
> >  kasan_report_error mm/kasan/report.c:351
> >  kasan_report+0x23d/0x350 mm/kasan/report.c:409
> >  __asan_report_store8_noabort+0x1c/0x20 mm/kasan/report.c:435
> >  __dvb_frontend_free+0x113/0x120 drivers/media/dvb-core/dvb_frontend.c:156
> >  dvb_frontend_put+0x59/0x70 drivers/media/dvb-core/dvb_frontend.c:176
> >  dvb_frontend_detach+0x120/0x150 drivers/media/dvb-core/dvb_frontend.c:2803
> >  dvb_usb_adapter_frontend_exit+0xd6/0x160
> > drivers/media/usb/dvb-usb/dvb-usb-dvb.c:340
> >  dvb_usb_adapter_exit drivers/media/usb/dvb-usb/dvb-usb-init.c:116
> >  dvb_usb_exit+0x9b/0x200 drivers/media/usb/dvb-usb/dvb-usb-init.c:132
> >  dvb_usb_device_exit+0xa5/0xf0 drivers/media/usb/dvb-usb/dvb-usb-init.c:295
> >  usb_unbind_interface+0x21c/0xa90 drivers/usb/core/driver.c:423
> >  __device_release_driver drivers/base/dd.c:861
> >  device_release_driver_internal+0x4f1/0x5c0 drivers/base/dd.c:893
> >  device_release_driver+0x1e/0x30 drivers/base/dd.c:918
> >  bus_remove_device+0x2f4/0x4b0 drivers/base/bus.c:565
> >  device_del+0x5c4/0xab0 drivers/base/core.c:1985
> >  usb_disable_device+0x1e9/0x680 drivers/usb/core/message.c:1170
> >  usb_disconnect+0x260/0x7a0 drivers/usb/core/hub.c:2124
> >  hub_port_connect drivers/usb/core/hub.c:4754
> >  hub_port_connect_change drivers/usb/core/hub.c:5009
> >  port_event drivers/usb/core/hub.c:5115
> >  hub_event+0x1318/0x3740 drivers/usb/core/hub.c:5195
> >  process_one_work+0xc73/0x1d90 kernel/workqueue.c:2119
> >  worker_thread+0x221/0x1850 kernel/workqueue.c:2253
> >  kthread+0x363/0x440 kernel/kthread.c:231
> >  ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:431
> >   
> It looks like this is caused by commit
> ead666000a5fe34bdc82d61838e4df2d416ea15e ("media: dvb_frontend: only use
> kref after initialized").
> 
> The writing to "fe->frontend_priv" in dvb_frontend.c:156 is a
> use-after-free in case the object dvb_frontend *fe is already freed by
> the release callback called in line 153.
> Only if the demod driver is based on new style i2c_client the memory is
> still accessible.
> 
> There are two possible solutions:
> 1. Clear fe->frontend_priv earlier (before line 153).
> 2. Do not clear fe->frontend_priv
> 
> Can you try if the following patch (solution 1) fixes the issue?

The problem with (1) is that drivers may need to use frontend_priv
on their own release callbacks.

So, I don't think this is the right fix.

I guess option (2) is the best one here.

Andrey,

Could you please test the enclosed patch?

Thanks!
Mauro

dvb_frontend: don't use-after-free the frontend struct

dvb_frontend_invoke_release() may free the frontend struct.
So, we can't update it anymore after calling it.
That's OK, as __dvb_frontend_free() is called only when the
krefs are zeroed, so nobody is using it anymore.

Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>


diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c
index daaf969719e4..80191a15cd89 100644
--- a/drivers/media/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb-core/dvb_frontend.c
@@ -153,7 +153,6 @@ static void __dvb_frontend_free(struct dvb_frontend *fe)
 	dvb_frontend_invoke_release(fe, fe->ops.release);
 
 	kfree(fepriv);
-	fe->frontend_priv = NULL;
 }
 
 static void dvb_frontend_free(struct kref *ref)


Thanks,
Mauro

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: usb/media/dtt200u: use-after-free in __dvb_frontend_free
  2017-11-07 10:31   ` Mauro Carvalho Chehab
@ 2017-11-07 12:51     ` Andrey Konovalov
  2017-11-07 13:44       ` [PATCH] dvb_frontend: don't use-after-free the frontend struct Mauro Carvalho Chehab
  0 siblings, 1 reply; 8+ messages in thread
From: Andrey Konovalov @ 2017-11-07 12:51 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Matthias Schwarzott, Mauro Carvalho Chehab, Max Kellermann,
	linux-media, LKML, Dmitry Vyukov, Kostya Serebryany, syzkaller

On Tue, Nov 7, 2017 at 11:31 AM, Mauro Carvalho Chehab
<mchehab@s-opensource.com> wrote:
> Em Mon, 23 Oct 2017 20:58:09 +0200
> Matthias Schwarzott <zzam@gentoo.org> escreveu:
>
>> Am 23.10.2017 um 16:41 schrieb Andrey Konovalov:
>> > Hi!
>> >
>> > I've got the following report while fuzzing the kernel with syzkaller.
>> >
>> > On commit 3e0cc09a3a2c40ec1ffb6b4e12da86e98feccb11 (4.14-rc5+).
>> >
>> > dvb-usb: found a 'WideView WT-220U PenType Receiver (based on ZL353)'
>> > in warm state.
>> > dvb-usb: bulk message failed: -22 (2/1102416563)
>> > dvb-usb: will use the device's hardware PID filter (table count: 15).
>> > dvbdev: DVB: registering new adapter (WideView WT-220U PenType
>> > Receiver (based on ZL353))
>> > usb 1-1: media controller created
>> > dvbdev: dvb_create_media_entity: media entity 'dvb-demux' registered.
>> > usb 1-1: DVB: registering adapter 0 frontend 0 (WideView USB DVB-T)...
>> > dvbdev: dvb_create_media_entity: media entity 'WideView USB DVB-T' registered.
>> > Registered IR keymap rc-dtt200u
>> > rc rc1: IR-receiver inside an USB DVB receiver as
>> > /devices/platform/dummy_hcd.0/usb1/1-1/rc/rc1
>> > input: IR-receiver inside an USB DVB receiver as
>> > /devices/platform/dummy_hcd.0/usb1/1-1/rc/rc1/input9
>> > dvb-usb: schedule remote query interval to 300 msecs.
>> > dvb-usb: WideView WT-220U PenType Receiver (based on ZL353)
>> > successfully initialized and connected.
>> > dvb-usb: bulk message failed: -22 (1/1807119384)
>> > dvb-usb: error -22 while querying for an remote control event.
>> > dvb-usb: bulk message failed: -22 (1/1807119384)
>> > dvb-usb: error -22 while querying for an remote control event.
>> > dvb-usb: bulk message failed: -22 (1/1807119384)
>> > dvb-usb: error -22 while querying for an remote control event.
>> > dvb-usb: bulk message failed: -22 (1/1807119384)
>> > dvb-usb: error -22 while querying for an remote control event.
>> > dvb-usb: bulk message failed: -22 (1/1807119384)
>> > dvb-usb: error -22 while querying for an remote control event.
>> > dvb-usb: bulk message failed: -22 (1/1807119384)
>> > dvb-usb: error -22 while querying for an remote control event.
>> > usb 1-1: USB disconnect, device number 2
>> > ==================================================================
>> > BUG: KASAN: use-after-free in __dvb_frontend_free+0x113/0x120
>> > Write of size 8 at addr ffff880067d45a00 by task kworker/0:1/24
>> >
>> > CPU: 0 PID: 24 Comm: kworker/0:1 Not tainted 4.14.0-rc5-43687-g06ab8a23e0e6 #545
>> > Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
>> > Workqueue: usb_hub_wq hub_event
>> > Call Trace:
>> >  __dump_stack lib/dump_stack.c:16
>> >  dump_stack+0x292/0x395 lib/dump_stack.c:52
>> >  print_address_description+0x78/0x280 mm/kasan/report.c:252
>> >  kasan_report_error mm/kasan/report.c:351
>> >  kasan_report+0x23d/0x350 mm/kasan/report.c:409
>> >  __asan_report_store8_noabort+0x1c/0x20 mm/kasan/report.c:435
>> >  __dvb_frontend_free+0x113/0x120 drivers/media/dvb-core/dvb_frontend.c:156
>> >  dvb_frontend_put+0x59/0x70 drivers/media/dvb-core/dvb_frontend.c:176
>> >  dvb_frontend_detach+0x120/0x150 drivers/media/dvb-core/dvb_frontend.c:2803
>> >  dvb_usb_adapter_frontend_exit+0xd6/0x160
>> > drivers/media/usb/dvb-usb/dvb-usb-dvb.c:340
>> >  dvb_usb_adapter_exit drivers/media/usb/dvb-usb/dvb-usb-init.c:116
>> >  dvb_usb_exit+0x9b/0x200 drivers/media/usb/dvb-usb/dvb-usb-init.c:132
>> >  dvb_usb_device_exit+0xa5/0xf0 drivers/media/usb/dvb-usb/dvb-usb-init.c:295
>> >  usb_unbind_interface+0x21c/0xa90 drivers/usb/core/driver.c:423
>> >  __device_release_driver drivers/base/dd.c:861
>> >  device_release_driver_internal+0x4f1/0x5c0 drivers/base/dd.c:893
>> >  device_release_driver+0x1e/0x30 drivers/base/dd.c:918
>> >  bus_remove_device+0x2f4/0x4b0 drivers/base/bus.c:565
>> >  device_del+0x5c4/0xab0 drivers/base/core.c:1985
>> >  usb_disable_device+0x1e9/0x680 drivers/usb/core/message.c:1170
>> >  usb_disconnect+0x260/0x7a0 drivers/usb/core/hub.c:2124
>> >  hub_port_connect drivers/usb/core/hub.c:4754
>> >  hub_port_connect_change drivers/usb/core/hub.c:5009
>> >  port_event drivers/usb/core/hub.c:5115
>> >  hub_event+0x1318/0x3740 drivers/usb/core/hub.c:5195
>> >  process_one_work+0xc73/0x1d90 kernel/workqueue.c:2119
>> >  worker_thread+0x221/0x1850 kernel/workqueue.c:2253
>> >  kthread+0x363/0x440 kernel/kthread.c:231
>> >  ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:431
>> >
>> It looks like this is caused by commit
>> ead666000a5fe34bdc82d61838e4df2d416ea15e ("media: dvb_frontend: only use
>> kref after initialized").
>>
>> The writing to "fe->frontend_priv" in dvb_frontend.c:156 is a
>> use-after-free in case the object dvb_frontend *fe is already freed by
>> the release callback called in line 153.
>> Only if the demod driver is based on new style i2c_client the memory is
>> still accessible.
>>
>> There are two possible solutions:
>> 1. Clear fe->frontend_priv earlier (before line 153).
>> 2. Do not clear fe->frontend_priv
>>
>> Can you try if the following patch (solution 1) fixes the issue?

Hi Mauro,

This patch also fixes the issue.

Thanks!

Tested-by: Andrey Konovalov <andreyknvl@google.com>

>
> The problem with (1) is that drivers may need to use frontend_priv
> on their own release callbacks.
>
> So, I don't think this is the right fix.
>
> I guess option (2) is the best one here.
>
> Andrey,
>
> Could you please test the enclosed patch?
>
> Thanks!
> Mauro
>
> dvb_frontend: don't use-after-free the frontend struct
>
> dvb_frontend_invoke_release() may free the frontend struct.
> So, we can't update it anymore after calling it.
> That's OK, as __dvb_frontend_free() is called only when the
> krefs are zeroed, so nobody is using it anymore.
>
> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
>
>
> diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c
> index daaf969719e4..80191a15cd89 100644
> --- a/drivers/media/dvb-core/dvb_frontend.c
> +++ b/drivers/media/dvb-core/dvb_frontend.c
> @@ -153,7 +153,6 @@ static void __dvb_frontend_free(struct dvb_frontend *fe)
>         dvb_frontend_invoke_release(fe, fe->ops.release);
>
>         kfree(fepriv);
> -       fe->frontend_priv = NULL;
>  }
>
>  static void dvb_frontend_free(struct kref *ref)
>
>
> Thanks,
> Mauro

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH] dvb_frontend: don't use-after-free the frontend struct
  2017-11-07 12:51     ` Andrey Konovalov
@ 2017-11-07 13:44       ` Mauro Carvalho Chehab
  2017-11-07 16:28         ` Matthias Schwarzott
  0 siblings, 1 reply; 8+ messages in thread
From: Mauro Carvalho Chehab @ 2017-11-07 13:44 UTC (permalink / raw)
  To: Matthias Schwarzott, Andrey Konovalov
  Cc: Mauro Carvalho Chehab, Linux Media Mailing List,
	Mauro Carvalho Chehab, Shuah Khan, Max Kellermann,
	Colin Ian King, Satendra Singh Thakur

dvb_frontend_invoke_release() may free the frontend struct.
So, the free logic can't update it anymore after calling it.

That's OK, as __dvb_frontend_free() is called only when the
krefs are zeroed, so nobody is using it anymore.

That should fix the following KASAN error:

The KASAN report looks like this (running on kernel 3e0cc09a3a2c40ec1ffb6b4e12da86e98feccb11 (4.14-rc5+)):
==================================================================
BUG: KASAN: use-after-free in __dvb_frontend_free+0x113/0x120
Write of size 8 at addr ffff880067d45a00 by task kworker/0:1/24

CPU: 0 PID: 24 Comm: kworker/0:1 Not tainted 4.14.0-rc5-43687-g06ab8a23e0e6 #545
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
Workqueue: usb_hub_wq hub_event
Call Trace:
 __dump_stack lib/dump_stack.c:16
 dump_stack+0x292/0x395 lib/dump_stack.c:52
 print_address_description+0x78/0x280 mm/kasan/report.c:252
 kasan_report_error mm/kasan/report.c:351
 kasan_report+0x23d/0x350 mm/kasan/report.c:409
 __asan_report_store8_noabort+0x1c/0x20 mm/kasan/report.c:435
 __dvb_frontend_free+0x113/0x120 drivers/media/dvb-core/dvb_frontend.c:156
 dvb_frontend_put+0x59/0x70 drivers/media/dvb-core/dvb_frontend.c:176
 dvb_frontend_detach+0x120/0x150 drivers/media/dvb-core/dvb_frontend.c:2803
 dvb_usb_adapter_frontend_exit+0xd6/0x160 drivers/media/usb/dvb-usb/dvb-usb-dvb.c:340
 dvb_usb_adapter_exit drivers/media/usb/dvb-usb/dvb-usb-init.c:116
 dvb_usb_exit+0x9b/0x200 drivers/media/usb/dvb-usb/dvb-usb-init.c:132
 dvb_usb_device_exit+0xa5/0xf0 drivers/media/usb/dvb-usb/dvb-usb-init.c:295
 usb_unbind_interface+0x21c/0xa90 drivers/usb/core/driver.c:423
 __device_release_driver drivers/base/dd.c:861
 device_release_driver_internal+0x4f1/0x5c0 drivers/base/dd.c:893
 device_release_driver+0x1e/0x30 drivers/base/dd.c:918
 bus_remove_device+0x2f4/0x4b0 drivers/base/bus.c:565
 device_del+0x5c4/0xab0 drivers/base/core.c:1985
 usb_disable_device+0x1e9/0x680 drivers/usb/core/message.c:1170
 usb_disconnect+0x260/0x7a0 drivers/usb/core/hub.c:2124
 hub_port_connect drivers/usb/core/hub.c:4754
 hub_port_connect_change drivers/usb/core/hub.c:5009
 port_event drivers/usb/core/hub.c:5115
 hub_event+0x1318/0x3740 drivers/usb/core/hub.c:5195
 process_one_work+0xc73/0x1d90 kernel/workqueue.c:2119
 worker_thread+0x221/0x1850 kernel/workqueue.c:2253
 kthread+0x363/0x440 kernel/kthread.c:231
 ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:431

Allocated by task 24:
 save_stack_trace+0x1b/0x20 arch/x86/kernel/stacktrace.c:59
 save_stack+0x43/0xd0 mm/kasan/kasan.c:447
 set_track mm/kasan/kasan.c:459
 kasan_kmalloc+0xad/0xe0 mm/kasan/kasan.c:551
 kmem_cache_alloc_trace+0x11e/0x2d0 mm/slub.c:2772
 kmalloc ./include/linux/slab.h:493
 kzalloc ./include/linux/slab.h:666
 dtt200u_fe_attach+0x4c/0x110 drivers/media/usb/dvb-usb/dtt200u-fe.c:212
 dtt200u_frontend_attach+0x35/0x80 drivers/media/usb/dvb-usb/dtt200u.c:136
 dvb_usb_adapter_frontend_init+0x32b/0x660 drivers/media/usb/dvb-usb/dvb-usb-dvb.c:286
 dvb_usb_adapter_init drivers/media/usb/dvb-usb/dvb-usb-init.c:86
 dvb_usb_init drivers/media/usb/dvb-usb/dvb-usb-init.c:162
 dvb_usb_device_init+0xf73/0x17f0 drivers/media/usb/dvb-usb/dvb-usb-init.c:277
 dtt200u_usb_probe+0xa1/0xe0 drivers/media/usb/dvb-usb/dtt200u.c:155
 usb_probe_interface+0x35d/0x8e0 drivers/usb/core/driver.c:361
 really_probe drivers/base/dd.c:413
 driver_probe_device+0x610/0xa00 drivers/base/dd.c:557
 __device_attach_driver+0x230/0x290 drivers/base/dd.c:653
 bus_for_each_drv+0x161/0x210 drivers/base/bus.c:463
 __device_attach+0x26b/0x3c0 drivers/base/dd.c:710
 device_initial_probe+0x1f/0x30 drivers/base/dd.c:757
 bus_probe_device+0x1eb/0x290 drivers/base/bus.c:523
 device_add+0xd0b/0x1660 drivers/base/core.c:1835
 usb_set_configuration+0x104e/0x1870 drivers/usb/core/message.c:1932
 generic_probe+0x73/0xe0 drivers/usb/core/generic.c:174
 usb_probe_device+0xaf/0xe0 drivers/usb/core/driver.c:266
 really_probe drivers/base/dd.c:413
 driver_probe_device+0x610/0xa00 drivers/base/dd.c:557
 __device_attach_driver+0x230/0x290 drivers/base/dd.c:653
 bus_for_each_drv+0x161/0x210 drivers/base/bus.c:463
 __device_attach+0x26b/0x3c0 drivers/base/dd.c:710
 device_initial_probe+0x1f/0x30 drivers/base/dd.c:757
 bus_probe_device+0x1eb/0x290 drivers/base/bus.c:523
 device_add+0xd0b/0x1660 drivers/base/core.c:1835
 usb_new_device+0x7b8/0x1020 drivers/usb/core/hub.c:2457
 hub_port_connect drivers/usb/core/hub.c:4903
 hub_port_connect_change drivers/usb/core/hub.c:5009
 port_event drivers/usb/core/hub.c:5115
 hub_event+0x194d/0x3740 drivers/usb/core/hub.c:5195
 process_one_work+0xc73/0x1d90 kernel/workqueue.c:2119
 worker_thread+0x221/0x1850 kernel/workqueue.c:2253
 kthread+0x363/0x440 kernel/kthread.c:231
 ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:431

Freed by task 24:
 save_stack_trace+0x1b/0x20 arch/x86/kernel/stacktrace.c:59
 save_stack+0x43/0xd0 mm/kasan/kasan.c:447
 set_track mm/kasan/kasan.c:459
 kasan_slab_free+0x72/0xc0 mm/kasan/kasan.c:524
 slab_free_hook mm/slub.c:1390
 slab_free_freelist_hook mm/slub.c:1412
 slab_free mm/slub.c:2988
 kfree+0xf6/0x2f0 mm/slub.c:3919
 dtt200u_fe_release+0x3c/0x50 drivers/media/usb/dvb-usb/dtt200u-fe.c:202
 dvb_frontend_invoke_release.part.13+0x1c/0x30 drivers/media/dvb-core/dvb_frontend.c:2790
 dvb_frontend_invoke_release drivers/media/dvb-core/dvb_frontend.c:2789
 __dvb_frontend_free+0xad/0x120 drivers/media/dvb-core/dvb_frontend.c:153
 dvb_frontend_put+0x59/0x70 drivers/media/dvb-core/dvb_frontend.c:176
 dvb_frontend_detach+0x120/0x150 drivers/media/dvb-core/dvb_frontend.c:2803
 dvb_usb_adapter_frontend_exit+0xd6/0x160 drivers/media/usb/dvb-usb/dvb-usb-dvb.c:340
 dvb_usb_adapter_exit drivers/media/usb/dvb-usb/dvb-usb-init.c:116
 dvb_usb_exit+0x9b/0x200 drivers/media/usb/dvb-usb/dvb-usb-init.c:132
 dvb_usb_device_exit+0xa5/0xf0 drivers/media/usb/dvb-usb/dvb-usb-init.c:295
 usb_unbind_interface+0x21c/0xa90 drivers/usb/core/driver.c:423
 __device_release_driver drivers/base/dd.c:861
 device_release_driver_internal+0x4f1/0x5c0 drivers/base/dd.c:893
 device_release_driver+0x1e/0x30 drivers/base/dd.c:918
 bus_remove_device+0x2f4/0x4b0 drivers/base/bus.c:565
 device_del+0x5c4/0xab0 drivers/base/core.c:1985
 usb_disable_device+0x1e9/0x680 drivers/usb/core/message.c:1170
 usb_disconnect+0x260/0x7a0 drivers/usb/core/hub.c:2124
 hub_port_connect drivers/usb/core/hub.c:4754
 hub_port_connect_change drivers/usb/core/hub.c:5009
 port_event drivers/usb/core/hub.c:5115
 hub_event+0x1318/0x3740 drivers/usb/core/hub.c:5195
 process_one_work+0xc73/0x1d90 kernel/workqueue.c:2119
 worker_thread+0x221/0x1850 kernel/workqueue.c:2253
 kthread+0x363/0x440 kernel/kthread.c:231
 ret_from_fork+0x2a/0x40 arch/x86/entry/entry_64.S:431

The buggy address belongs to the object at ffff880067d45500
 which belongs to the cache kmalloc-2048 of size 2048
The buggy address is located 1280 bytes inside of
 2048-byte region [ffff880067d45500, ffff880067d45d00)
The buggy address belongs to the page:
page:ffffea00019f5000 count:1 mapcount:0 mapping:          (null)
index:0x0 compound_mapcount: 0
flags: 0x100000000008100(slab|head)
raw: 0100000000008100 0000000000000000 0000000000000000 00000001000f000f
raw: dead000000000100 dead000000000200 ffff88006c002d80 0000000000000000
page dumped because: kasan: bad access detected

Memory state around the buggy address:
 ffff880067d45900: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
 ffff880067d45980: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
 ffff880067d45a00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
                   ^
 ffff880067d45a80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
 ffff880067d45b00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
==================================================================

Fixes: ead666000a5f ("media: dvb_frontend: only use kref after initialized")

Reported-by: Andrey Konovalov <andreyknvl@google.com>
Suggested-by: Matthias Schwarzott <zzam@gentoo.org>
Tested-by: Andrey Konovalov <andreyknvl@google.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
---
 drivers/media/dvb-core/dvb_frontend.c | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c
index d485d5f6cc88..3ad83359098b 100644
--- a/drivers/media/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb-core/dvb_frontend.c
@@ -150,11 +150,8 @@ static void __dvb_frontend_free(struct dvb_frontend *fe)
 
 	dvb_frontend_invoke_release(fe, fe->ops.release);
 
-	if (!fepriv)
-		return;
-
-	kfree(fepriv);
-	fe->frontend_priv = NULL;
+	if (fepriv)
+		kfree(fepriv);
 }
 
 static void dvb_frontend_free(struct kref *ref)
-- 
2.13.6

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH] dvb_frontend: don't use-after-free the frontend struct
  2017-11-07 13:44       ` [PATCH] dvb_frontend: don't use-after-free the frontend struct Mauro Carvalho Chehab
@ 2017-11-07 16:28         ` Matthias Schwarzott
  0 siblings, 0 replies; 8+ messages in thread
From: Matthias Schwarzott @ 2017-11-07 16:28 UTC (permalink / raw)
  To: Mauro Carvalho Chehab, Andrey Konovalov
  Cc: Linux Media Mailing List, Mauro Carvalho Chehab, Shuah Khan,
	Max Kellermann, Colin Ian King, Satendra Singh Thakur

Am 07.11.2017 um 14:44 schrieb Mauro Carvalho Chehab:
> diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c
> index d485d5f6cc88..3ad83359098b 100644
> --- a/drivers/media/dvb-core/dvb_frontend.c
> +++ b/drivers/media/dvb-core/dvb_frontend.c
> @@ -150,11 +150,8 @@ static void __dvb_frontend_free(struct dvb_frontend *fe)
>  
>  	dvb_frontend_invoke_release(fe, fe->ops.release);
>  
> -	if (!fepriv)
> -		return;
> -
> -	kfree(fepriv);
> -	fe->frontend_priv = NULL;
> +	if (fepriv)
> +		kfree(fepriv);

I think the condition is redundant and should be removed.
kfree(NULL) is fine.

>  }
>  
>  static void dvb_frontend_free(struct kref *ref)
> 

Regards
Matthias

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2017-11-07 16:28 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-10-23 14:41 usb/media/dtt200u: use-after-free in __dvb_frontend_free Andrey Konovalov
2017-10-23 18:58 ` Matthias Schwarzott
2017-10-24 11:19   ` Andrey Konovalov
2017-11-07 10:31   ` Mauro Carvalho Chehab
2017-11-07 12:51     ` Andrey Konovalov
2017-11-07 13:44       ` [PATCH] dvb_frontend: don't use-after-free the frontend struct Mauro Carvalho Chehab
2017-11-07 16:28         ` Matthias Schwarzott
2017-10-30  9:58 ` [PATCH] __dvb_frontend_free: Clear frontend_priv earlier Matthias Schwarzott

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.