]>
Commit | Line | Data |
---|---|---|
ac6c5db7 GKH |
1 | From foo@baz Wed 15 May 2019 07:51:30 AM CEST |
2 | From: Paul Bolle <pebolle@tiscali.nl> | |
3 | Date: Wed, 1 May 2019 23:19:03 +0200 | |
4 | Subject: isdn: bas_gigaset: use usb_fill_int_urb() properly | |
5 | ||
6 | From: Paul Bolle <pebolle@tiscali.nl> | |
7 | ||
8 | [ Upstream commit 4014dfae3ccaaf3ec19c9ae0691a3f14e7132eae ] | |
9 | ||
10 | The switch to make bas_gigaset use usb_fill_int_urb() - instead of | |
11 | filling that urb "by hand" - missed the subtle ordering of the previous | |
12 | code. | |
13 | ||
14 | See, before the switch urb->dev was set to a member somewhere deep in a | |
15 | complicated structure and then supplied to usb_rcvisocpipe() and | |
16 | usb_sndisocpipe(). After that switch urb->dev wasn't set to anything | |
17 | specific before being supplied to those two macros. This triggers a | |
18 | nasty oops: | |
19 | ||
20 | BUG: unable to handle kernel NULL pointer dereference at 00000000 | |
21 | #PF error: [normal kernel read fault] | |
22 | *pde = 00000000 | |
23 | Oops: 0000 [#1] SMP | |
24 | CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.1.0-0.rc4.1.local0.fc28.i686 #1 | |
25 | Hardware name: IBM 2525FAG/2525FAG, BIOS 74ET64WW (2.09 ) 12/14/2006 | |
26 | EIP: gigaset_init_bchannel+0x89/0x320 [bas_gigaset] | |
27 | Code: 75 07 83 8b 84 00 00 00 40 8d 47 74 c7 07 01 00 00 00 89 45 f0 8b 44 b7 68 85 c0 0f 84 6a 02 00 00 8b 48 28 8b 93 88 00 00 00 <8b> 09 8d 54 12 03 c1 e2 0f c1 e1 08 09 ca 8b 8b 8c 00 00 00 80 ca | |
28 | EAX: f05ec200 EBX: ed404200 ECX: 00000000 EDX: 00000000 | |
29 | ESI: 00000000 EDI: f065a000 EBP: f30c9f40 ESP: f30c9f20 | |
30 | DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 EFLAGS: 00010086 | |
31 | CR0: 80050033 CR2: 00000000 CR3: 0ddc7000 CR4: 000006d0 | |
32 | Call Trace: | |
33 | <SOFTIRQ> | |
34 | ? gigaset_isdn_connD+0xf6/0x140 [gigaset] | |
35 | gigaset_handle_event+0x173e/0x1b90 [gigaset] | |
36 | tasklet_action_common.isra.16+0x4e/0xf0 | |
37 | tasklet_action+0x1e/0x20 | |
38 | __do_softirq+0xb2/0x293 | |
39 | ? __irqentry_text_end+0x3/0x3 | |
40 | call_on_stack+0x45/0x50 | |
41 | </SOFTIRQ> | |
42 | ? irq_exit+0xb5/0xc0 | |
43 | ? do_IRQ+0x78/0xd0 | |
44 | ? acpi_idle_enter_s2idle+0x50/0x50 | |
45 | ? common_interrupt+0xd4/0xdc | |
46 | ? acpi_idle_enter_s2idle+0x50/0x50 | |
47 | ? sched_cpu_activate+0x1b/0xf0 | |
48 | ? acpi_fan_resume.cold.7+0x9/0x18 | |
49 | ? cpuidle_enter_state+0x152/0x4c0 | |
50 | ? cpuidle_enter+0x14/0x20 | |
51 | ? call_cpuidle+0x21/0x40 | |
52 | ? do_idle+0x1c8/0x200 | |
53 | ? cpu_startup_entry+0x25/0x30 | |
54 | ? rest_init+0x88/0x8a | |
55 | ? arch_call_rest_init+0xd/0x19 | |
56 | ? start_kernel+0x42f/0x448 | |
57 | ? i386_start_kernel+0xac/0xb0 | |
58 | ? startup_32_smp+0x164/0x168 | |
59 | Modules linked in: ppp_generic slhc capi bas_gigaset gigaset kernelcapi nf_conntrack_netbios_ns nf_conntrack_broadcast xt_CT ip6t_rpfilter ip6t_REJECT nf_reject_ipv6 xt_conntrack ip_set nfnetlink ebtable_nat ebtable_broute bridge stp llc ip6table_nat ip6table_mangle ip6table_raw ip6table_security iptable_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 libcrc32c iptable_mangle iptable_raw iptable_security ebtable_filter ebtables ip6table_filter ip6_tables sunrpc ipw2200 iTCO_wdt gpio_ich snd_intel8x0 libipw iTCO_vendor_support snd_ac97_codec lib80211 ppdev ac97_bus snd_seq cfg80211 snd_seq_device pcspkr thinkpad_acpi lpc_ich snd_pcm i2c_i801 snd_timer ledtrig_audio snd soundcore rfkill parport_pc parport pcc_cpufreq acpi_cpufreq i915 i2c_algo_bit drm_kms_helper syscopyarea sysfillrect sdhci_pci sysimgblt cqhci fb_sys_fops drm sdhci mmc_core tg3 ata_generic serio_raw yenta_socket pata_acpi video | |
60 | CR2: 0000000000000000 | |
61 | ---[ end trace 1fe07487b9200c73 ]--- | |
62 | EIP: gigaset_init_bchannel+0x89/0x320 [bas_gigaset] | |
63 | Code: 75 07 83 8b 84 00 00 00 40 8d 47 74 c7 07 01 00 00 00 89 45 f0 8b 44 b7 68 85 c0 0f 84 6a 02 00 00 8b 48 28 8b 93 88 00 00 00 <8b> 09 8d 54 12 03 c1 e2 0f c1 e1 08 09 ca 8b 8b 8c 00 00 00 80 ca | |
64 | EAX: f05ec200 EBX: ed404200 ECX: 00000000 EDX: 00000000 | |
65 | ESI: 00000000 EDI: f065a000 EBP: f30c9f40 ESP: cddcb3bc | |
66 | DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 EFLAGS: 00010086 | |
67 | CR0: 80050033 CR2: 00000000 CR3: 0ddc7000 CR4: 000006d0 | |
68 | Kernel panic - not syncing: Fatal exception in interrupt | |
69 | Kernel Offset: 0xcc00000 from 0xc0400000 (relocation range: 0xc0000000-0xf6ffdfff) | |
70 | ---[ end Kernel panic - not syncing: Fatal exception in interrupt ]--- | |
71 | ||
72 | No-one noticed because this Oops is apparently only triggered by setting | |
73 | up an ISDN data connection on a live ISDN line on a gigaset base (ie, | |
74 | the PBX that the gigaset driver support). Very few people do that | |
75 | running present day kernels. | |
76 | ||
77 | Anyhow, a little code reorganization makes this problem go away, while | |
78 | avoiding the subtle ordering that was used in the past. So let's do | |
79 | that. | |
80 | ||
81 | Fixes: 78c696c19578 ("isdn: gigaset: use usb_fill_int_urb()") | |
82 | Signed-off-by: Paul Bolle <pebolle@tiscali.nl> | |
83 | Signed-off-by: David S. Miller <davem@davemloft.net> | |
84 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
85 | --- | |
86 | drivers/isdn/gigaset/bas-gigaset.c | 9 +++++---- | |
87 | 1 file changed, 5 insertions(+), 4 deletions(-) | |
88 | ||
89 | --- a/drivers/isdn/gigaset/bas-gigaset.c | |
90 | +++ b/drivers/isdn/gigaset/bas-gigaset.c | |
91 | @@ -958,6 +958,7 @@ static void write_iso_callback(struct ur | |
92 | */ | |
93 | static int starturbs(struct bc_state *bcs) | |
94 | { | |
95 | + struct usb_device *udev = bcs->cs->hw.bas->udev; | |
96 | struct bas_bc_state *ubc = bcs->hw.bas; | |
97 | struct urb *urb; | |
98 | int j, k; | |
99 | @@ -975,8 +976,8 @@ static int starturbs(struct bc_state *bc | |
100 | rc = -EFAULT; | |
101 | goto error; | |
102 | } | |
103 | - usb_fill_int_urb(urb, bcs->cs->hw.bas->udev, | |
104 | - usb_rcvisocpipe(urb->dev, 3 + 2 * bcs->channel), | |
105 | + usb_fill_int_urb(urb, udev, | |
106 | + usb_rcvisocpipe(udev, 3 + 2 * bcs->channel), | |
107 | ubc->isoinbuf + k * BAS_INBUFSIZE, | |
108 | BAS_INBUFSIZE, read_iso_callback, bcs, | |
109 | BAS_FRAMETIME); | |
110 | @@ -1006,8 +1007,8 @@ static int starturbs(struct bc_state *bc | |
111 | rc = -EFAULT; | |
112 | goto error; | |
113 | } | |
114 | - usb_fill_int_urb(urb, bcs->cs->hw.bas->udev, | |
115 | - usb_sndisocpipe(urb->dev, 4 + 2 * bcs->channel), | |
116 | + usb_fill_int_urb(urb, udev, | |
117 | + usb_sndisocpipe(udev, 4 + 2 * bcs->channel), | |
118 | ubc->isooutbuf->data, | |
119 | sizeof(ubc->isooutbuf->data), | |
120 | write_iso_callback, &ubc->isoouturbs[k], |