Bug 200961 - cx23885 crash on unload
Summary: cx23885 crash on unload
Status: NEW
Alias: None
Product: v4l-dvb
Classification: Unclassified
Component: dvb-other (show other bugs)
Hardware: x86-64 Linux
: P1 normal
Assignee: dvb-other
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2018-08-28 17:16 UTC by gdpt
Modified: 2020-02-02 18:33 UTC (History)
3 users (show)

See Also:
Kernel Version: 4.17
Subsystem:
Regression: No
Bisected commit-id:


Attachments
fix for crash on unload of cx23885 (674 bytes, patch)
2018-08-28 17:16 UTC, gdpt
Details | Diff
Fix use after free patch (2.39 KB, patch)
2020-01-19 19:12 UTC, Ahzo
Details | Diff

Description gdpt 2018-08-28 17:16:58 UTC
Created attachment 278173 [details]
fix for crash on unload of cx23885

The kernel module cx23885.ko crashes with kernel NULL pointer dereference in cx23885_dvb_unregister+0x8a/0x120 (as of 4.17.18-fedora). The module cannot be reloaded afterwards.

Temporarily unloading this module on suspend is a workaround to make the dvb card (in this case Hauppauge WinTV-HVR-5525) work after suspend-resume.

The patch in the attachment seems to fix the issue.
Comment 1 Ahzo 2020-01-19 19:12:56 UTC
Created attachment 286903 [details]
Fix use after free patch

Thanks for sharing your patch!

However, I think it is not entirely correct, because it basically reverts the following commit:
commit 412b16d623cf4fd794713f314db5aad10c46ad87
Author: Matthias Schwarzott <zzam@gentoo.org>
Date:   Wed Aug 2 12:45:59 2017 -0400

    media: cx23885: Fix use-after-free when unregistering the i2c_client for the dvb demod
    
    Unregistering the i2c_client of the demod driver destroys the frontend
    object.
    Calling vb2_dvb_unregister_bus later accesses the frontend (and with the
    refcount_t) conversion the refcount_t code complains:
    
    kernel: ------------[ cut here ]------------
    kernel: WARNING: CPU: 0 PID: 7883 at lib/refcount.c:128 refcount_sub_and_test+0x70/0x80
    kernel: refcount_t: underflow; use-after-free.
[...]
    kernel: ---[ end trace c3a4659b89086061 ]---
    
    Signed-off-by: Matthias Schwarzott <zzam@gentoo.org>
    Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>

While this commit caused the crash reported here, it also fixed a different problem. So reverting this commit would reintroduce that problem.

It all comes down to the ordering in which the different devices are freed. This ordering has to ensure that subdevices are freed before their parents, because otherwise already freed memory gets accessed (use-after-free).

Now in some cases like for the HVR-5525, the tuner is a subdevice of the frontend and thus has to be freed before it.
However, in other cases like for the HVR-4400, the frontend is a subdevice of the demod device and thus has to be freed before it.

The correct order for all cases should be:
 - free tuner
 - free frontend
 - free demod device

There are two places where this cleanup occurs. One is cx23885_dvb_unregister, which is called when unloading the module.
The other is the frontend_detach part of the dvb_register function, which is only executed upon errors during dvb_register.

Attached patch changes both places to the correct ordering.
Comment 2 Matthias Schwarzott 2020-02-02 14:14:26 UTC
I am missing some information here. Please attach at least:
* The full callstack of the crash.
* dmesg output
Comment 3 gdpt 2020-02-02 18:33:18 UTC
<pre>
with the original module from linux 5.4.15, fedora:

dmesg after boot:


[    0.000000] Linux version 5.4.15-200.fc31.x86_64   (mockbuild@bkernel04.phx2.fedoraproject.org) (gcc version 9.2.1 20190827 (Red Hat 9.2.1-1) (GCC)) #1 SMP Tue Jan 28 09:08:32 UTC 2020
    [    0.000000] Command line: BOOT_IMAGE=(hd4,gpt3)/boot/vmlinuz-5.4.15-200.fc31.x86_64 root=UUID=81b0c43e-cd93-4c98-aa41-8893baa344f0 ro rd.driver.blacklist=nouveau modprobe.blacklist=nouveau nvidia-drm.modeset=1 quiet
...

grep cx23885:

...
[    5.408031] cx23885: cx23885 driver version 0.0.4 loaded
[    5.408076] cx23885 0000:08:00.0: enabling device (0000 -> 0002)
[    5.408184] cx23885: CORE cx23885[0]: subsystem: 0070:f038, board: Hauppauge WinTV-HVR5525 [card=52,autodetected]
[    5.749293] cx23885: cx23885[0]: hauppauge eeprom: model=150329
[    5.749295] cx23885: cx23885_dvb_register() allocating 1 frontend(s)
[    5.749323] cx23885: cx23885[0]: cx23885 based dvb card
[    5.955172] dvbdev: DVB: registering new adapter (cx23885[0])
[    5.955173] cx23885 0000:08:00.0: DVB: registering adapter 0 frontend 0 (Montage Technology M88RS6000)...
[    5.955422] cx23885: cx23885_dvb_register() allocating 1 frontend(s)
[    5.955423] cx23885: cx23885[0]: cx23885 based dvb card
[    5.971049] dvbdev: DVB: registering new adapter (cx23885[0])
[    5.971051] cx23885 0000:08:00.0: DVB: registering adapter 1 frontend 0 (Silicon Labs Si2168)...
[    5.971264] cx23885: cx23885_dev_checkrevision() Hardware revision = 0xd0
[    5.971268] cx23885: cx23885[0]/0: found at 0000:08:00.0, rev: 4, irq: 39, latency: 0, mmio: 0xf7200000
~~~
after accessing the device:
~~~
...
[  131.441972] m88ds3103 2-0069: found a 'Montage Technology M88DS3103' in cold state
[  131.442608] m88ds3103 2-0069: downloading firmware from file 'dvb-demod-m88rs6000.fw'
[  132.385013] m88ds3103 2-0069: found a 'Montage Technology M88DS3103' in warm state
[  132.385014] m88ds3103 2-0069: firmware version: 4.1
[  132.508930] si2168 2-0064: downloading firmware from file 'dvb-demod-si2168-b40-01.fw'
[  133.141449] si2168 2-0064: firmware version: B 4.0.11
[  133.147989] si2157 3-0060: found a 'Silicon Labs Si2157-A30'
[  133.197482] si2157 3-0060: firmware version: 3.0.5
~~~

after rmmod cx23885:
~~~

...

[  271.230654] BUG: kernel NULL pointer dereference, 
address: 0000000000000010
[  271.230659] #PF: supervisor read access in kernel mode
[  271.230661] #PF: error_code(0x0000) - not-present page
[  271.230663] PGD 0 P4D 0
[  271.230667] Oops: 0000 [#1] SMP NOPTI
[  271.230671] CPU: 8 PID: 150488 Comm: rmmod Tainted: P           OE     5.4.15-200.fc31.x86_64 #1
[  271.230673] Hardware name: System manufacturer System Product Name/PRIME B450-PLUS, BIOS 0601 10/29/2018
[  271.230683] RIP: 0010:cx23885_dvb_unregister+0x8a/0x110 [cx23885]
[  271.230687] Code: 8b 85 88 00 00 00 48 8b 78 10 e8 c1 66 58 c8 48 89 ef e8 39 99 ba c8 48 8b ab a0 06 00 00 48 85 ed 74 18 48 8b 85 88 00 00 00 <48> 8b 78 10 e8 9d 66 58 c8 48 89 ef e8 15 99 ba c8 48 8b ab 98 06
[  271.230689] RSP: 0018:ffffb930c845fe00 EFLAGS: 00010286
[  271.230691] RAX: 0000000000000000 RBX: ffff94329fd09768 RCX: 000000008200018b
[  271.230693] RDX: 000000008200018c RSI: 000000008200018b RDI: ffff9432bb807b80
[  271.230694] RBP: ffff9432a64af000 R08: 0000000000000000 R09: 0000000000000001
[  271.230696] R10: ffff9430f3a1eb00 R11: fffff53ddfeb4620 R12: ffff9432ba01f000
[  271.230697] R13: ffff94329fd08008 R14: 0000000000000000 R15: 0000000000000000
[  271.230700] FS:  00007f1d0272b740(0000) GS:ffff9432bee00000(0000) knlGS:0000000000000000
[  271.230702] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  271.230703] CR2: 0000000000000010 CR3: 00000007f8238000 CR4: 00000000003406e0
[  271.230705] Call Trace:
[  271.230716]  cx23885_dev_unregister+0xe5/0x140 [cx23885]
[  271.230723]  cx23885_finidev+0x50/0x70 [cx23885]
[  271.230729]  pci_device_remove+0x3b/0xa0
[  271.230736]  device_release_driver_internal+0xe4/0x1c0
[  271.230739]  driver_detach+0x46/0x87
[  271.230742]  bus_remove_driver+0x58/0xcc
[  271.230745]  pci_unregister_driver+0x29/0xb0
[  271.230751]  __x64_sys_delete_module+0x13d/0x2a0
[  271.230755]  ? exit_to_usermode_loop+0xc7/0x130
[  271.230759]  do_syscall_64+0x5b/0x1a0
[  271.230763]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
[  271.230766] RIP: 0033:0x7f1d0285b03b
[  271.230769] Code: 73 01 c3 48 8b 0d 4d fe 0b 00 f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa b8 b0 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 1d fe 0b 00 f7 d8 64 89 01 48
[  271.230771] RSP: 002b:00007ffc993955e8 EFLAGS: 00000206 ORIG_RAX: 00000000000000b0
[  271.230773] RAX: ffffffffffffffda RBX: 000055ae80b347f0 RCX: 00007f1d0285b03b
[  271.230775] RDX: 000000000000000a RSI: 0000000000000800 RDI: 000055ae80b34858
[  271.230776] RBP: 00007ffc99395648 R08: 0000000000000000 R09: 0000000000000000
[  271.230778] R10: 00007f1d028ceac0 R11: 0000000000000206 R12: 00007ffc99395810
[  271.230779] R13: 00007ffc99396863 R14: 000055ae80b342a0 R15: 000055ae80b347f0
[  271.230782] Modules linked in: ip6_udp_tunnel udp_tunnel vboxnetadp(OE) vboxnetflt(OE) vboxdrv(OE) nvidia_drm(POE) nvidia_modeset(POE) nvidia_uvm(OE) nvidia(POE) drm_kms_helper drm ipmi_devintf ipmi_msghandler xt_MASQUERADE xt_CHECKSUM nf_nat_tftp nf_conntrack_tftp tun bridge stp llc nf_conntrack_netbios_ns nf_conntrack_broadcast xt_CT ip6t_REJECT nf_reject_ipv6 ip6t_rpfilter ipt_REJECT nf_reject_ipv4 xt_conntrack ebtable_nat ebtable_broute ip6table_nat ip6table_mangle ip6table_raw ip6table_security iptable_nat nf_nat iptable_mangle iptable_raw iptable_security nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 ip_set nfnetlink ebtable_filter ebtables ip6table_filter ip6_tables iptable_filter sunrpc vfat fat dm_multipath scsi_dh_rdac scsi_dh_emc scsi_dh_alua si2157 si2168 m88rs6000t a8293 snd_hda_codec_hdmi snd_hda_codec_realtek snd_hda_codec_generic btrfs ledtrig_audio cx23885(-) snd_hda_intel altera_ci xor snd_intel_dspcfg edac_mce_amd zstd_compress tda18271 raid6_pq snd_usb_audio snd_hda_codec
[  271.230819]  kvm_amd altera_stapl m88ds3103 pktcdvd zstd_decompress snd_hda_core snd_usbmidi_lib tveeprom cx2341x snd_rawmidi snd_hwdep uvcvideo kvm videobuf2_dma_sg videobuf2_vmalloc videobuf2_dvb joydev snd_seq videobuf2_memops snd_seq_device videobuf2_v4l2 irqbypass snd_pcm videobuf2_common dvb_core eeepc_wmi asus_wmi crct10dif_pclmul crc32_pclmul sparse_keymap videodev ghash_clmulni_intel snd_timer rfkill snd video mc sp5100_tco ccp wmi_bmof i2c_mux soundcore i2c_piix4 k10temp pcspkr gpio_amdpt gpio_generic acpi_cpufreq essiv authenc dm_crypt ip_tables xfs libcrc32c nvme crc32c_intel r8169 nvme_core wmi pinctrl_amd fuse
[  271.230854] CR2: 0000000000000010
[  271.230857] ---[ end trace 758929358279bc05 ]---
[  271.230864] RIP: 0010:cx23885_dvb_unregister+0x8a/0x110 [cx23885]
[  271.230867] Code: 8b 85 88 00 00 00 48 8b 78 10 e8 c1 66 58 c8 48 89 ef e8 39 99 ba c8 48 8b ab a0 06 00 00 48 85 ed 74 18 48 8b 85 88 00 00 00 <48> 8b 78 10 e8 9d 66 58 c8 48 89 ef e8 15 99 ba c8 48 8b ab 98 06
[  271.230868] RSP: 0018:ffffb930c845fe00 EFLAGS: 00010286
[  271.230870] RAX: 0000000000000000 RBX: ffff94329fd09768 RCX: 000000008200018b
[  271.230872] RDX: 000000008200018c RSI: 000000008200018b RDI: ffff9432bb807b80
[  271.230873] RBP: ffff9432a64af000 R08: 0000000000000000 R09: 0000000000000001
[  271.230874] R10: ffff9430f3a1eb00 R11: fffff53ddfeb4620 R12: ffff9432ba01f000
[  271.230876] R13: ffff94329fd08008 R14: 0000000000000000 R15: 0000000000000000
[  271.230878] FS:  00007f1d0272b740(0000) GS:ffff9432bee00000(0000) knlGS:0000000000000000
[  271.230879] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  271.230881] CR2: 0000000000000010 CR3: 00000007f8238000 CR4: 00000000003406e0

~~~

With my (workaround) patch reverting commit 412b16d623cf4fd794713f314db5aad10c46ad87 the module works reliably for 17 month and all kernel releases since the first post. 
The perfect solution would IMHO be to reload the firmware after suspend/resume without having to unloading the module.
</pre>

Note You need to log in before you can comment on or make changes to this bug.