Re: [PATCH] Fix a stack buffer overflow bug check_input_term

From: Hui Peng
Date: Thu Aug 15 2019 - 00:42:28 EST


The stack trace differs from test to test, the attached trace1 file is
taken from one of the tests.

The bug is confirmed by adding some printk statement in
`check_input_term`, the trace with output of printk is attached in
trace2 file.

This patch is a tentative fix to the bug, please give me feedback.

On 8/15/19 12:35 AM, Hui Peng wrote:
> `check_input_term` recursively calls itself with input
> from device side (e.g., uac_input_terminal_descriptor.bCSourceID)
> as argument (id). In `check_input_term`, if `check_input_term`
> is called with the same `id` argument as the caller, it triggers
> endless recursive call, resulting kernel space stack overflow.
>
> This patch fixes the bug by adding a bitmap to `struct mixer_build`
> to keep track of the checked ids by `check_input_term` and stop
> the execution if some id has been checked (similar to how
> parse_audio_unit handles unitid argument).
>
> Reported-by: Hui Peng <benquike@xxxxxxxxx>
> Reported-by: Mathias Payer <mathias.payer@xxxxxxxxxxxxx>
> Signed-off-by: Hui Peng <benquike@xxxxxxxxx>
> ---
> sound/usb/mixer.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
> index ea487378be17..1f6c8213df82 100644
> --- a/sound/usb/mixer.c
> +++ b/sound/usb/mixer.c
> @@ -68,6 +68,7 @@ struct mixer_build {
> unsigned char *buffer;
> unsigned int buflen;
> DECLARE_BITMAP(unitbitmap, MAX_ID_ELEMS);
> + DECLARE_BITMAP(termbitmap, MAX_ID_ELEMS);
> struct usb_audio_term oterm;
> const struct usbmix_name_map *map;
> const struct usbmix_selector_map *selector_map;
> @@ -782,6 +783,8 @@ static int check_input_term(struct mixer_build *state, int id,
> int err;
> void *p1;
>
> + if (test_and_set_bit(id, state->termbitmap))
> + return 0;
> memset(term, 0, sizeof(*term));
> while ((p1 = find_audio_control_unit(state, id)) != NULL) {
> unsigned char *hdr = p1;
[ 7.839002] usb 1-1: new high-speed USB device number 2 using xhci_hcd
[ 7.966787] usb 1-1: Using ep0 maxpacket: 16
[ 7.969898] usb 1-1: string descriptor 0 read error: -22
[ 7.971507] usb 1-1: New USB device found, idVendor=046d, idProduct=0a44, bcdDevice= 1.27
[ 7.973874] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[ 7.979864] usb 1-1: current rate 16732531 is different from the runtime rate 48000
[ 7.982029] usb 1-1: current rate 11254477 is different from the runtime rate 48000
[ 7.987190] [parse_audio_unit:2797] reached
[ 7.987741] [parse_audio_unit:2814] reached
[ 7.988310] [parse_audio_feature_unit:1855] reached
[ 7.988982] [parse_audio_feature_unit:1915] reached
[ 7.989605] [parse_audio_unit:2797] reached
[ 7.990173] [parse_audio_unit:2804] reached
[ 7.999615] [parse_audio_unit:2797] reached
[ 8.000166] [parse_audio_unit:2814] reached
[ 8.000734] [parse_audio_feature_unit:1855] reached
[ 8.001361] [parse_audio_feature_unit:1915] reached
[ 8.002011] [parse_audio_unit:2797] reached
[ 8.002590] [parse_audio_unit:2811] reached
[ 8.003180] [parse_audio_unit:2797] reached
[ 8.003754] [parse_audio_unit:2814] reached
[ 8.004342] [parse_audio_feature_unit:1855] reached
[ 8.004992] [parse_audio_feature_unit:1915] reached
[ 8.005656] [parse_audio_feature_unit:1921] reached
[ 8.006324] [check_input_term:804] reached
[ 8.006881] [check_input_term:860] reached
[ 8.007451] [check_input_term:804] reached
[ 8.008038] [check_input_term:860] reached
[ 8.008596] [check_input_term:804] reached
[ 8.009129] [check_input_term:860] reached
[ 8.009686] [check_input_term:804] reached
[ 8.010217] [check_input_term:860] reached
[ 8.010834] [check_input_term:804] reached
[ 8.011430] [check_input_term:860] reached
[ 8.011945] [check_input_term:804] reached
[ 8.012577] [check_input_term:860] reached
[ 8.013109] [check_input_term:804] reached
[ 8.013704] [check_input_term:860] reached
[ 8.014319] [check_input_term:804] reached
[ 8.014848] [check_input_term:860] reached
[ 8.015415] [check_input_term:804] reached
[ 8.015964] [check_input_term:860] reached
[ 8.016525] [check_input_term:804] reached
[ 8.017055] [check_input_term:860] reached
[ 8.017612] [check_input_term:804] reached
[ 8.018168] [check_input_term:860] reached
[ 8.018701] [check_input_term:804] reached
[ 8.019273] [check_input_term:860] reached
[ 8.019805] [check_input_term:804] reached
[ 8.020362] [check_input_term:860] reached
[ 8.020893] [check_input_term:804] reached
[ 8.021440] [check_input_term:860] reached
[ 8.021972] [check_input_term:804] reached
[ 8.022536] [check_input_term:860] reached
[ 8.023127] [check_input_term:804] reached
[ 8.023664] [check_input_term:860] reached
[ 8.024213] [check_input_term:804] reached
[ 8.024791] [check_input_term:860] reached
[ 8.025351] [check_input_term:804] reached
[ 8.025886] [check_input_term:860] reached
[ 8.026435] [check_input_term:804] reached
[ 8.026986] [check_input_term:860] reached
[ 8.027509] [check_input_term:804] reached
[ 8.028061] [check_input_term:860] reached
[ 8.028596] [check_input_term:804] reached
[ 8.029145] [check_input_term:860] reached
[ 8.029690] [check_input_term:804] reached
[ 8.030252] [check_input_term:860] reached
[ 8.030786] [check_input_term:804] reached
[ 8.031357] [check_input_term:860] reached
[ 8.031922] [check_input_term:804] reached
[ 8.032456] [check_input_term:860] reached
[ 8.033018] [check_input_term:804] reached
[ 8.033552] [check_input_term:860] reached
[ 8.034115] [check_input_term:804] reached
[ 8.034650] [check_input_term:860] reached
[ 8.035210] [check_input_term:804] reached
[ 8.035785] [check_input_term:860] reached
[ 8.036318] [check_input_term:804] reached
[ 8.036879] [check_input_term:860] reached
[ 8.037414] [check_input_term:804] reached
[ 8.037976] [check_input_term:860] reached
[ 8.038511] [check_input_term:804] reached
[ 8.039072] [check_input_term:860] reached
[ 8.039652] [check_input_term:804] reached
[ 8.040181] [check_input_term:860] reached
[ 8.040738] [check_input_term:804] reached
[ 8.041279] [check_input_term:860] reached
[ 8.041840] [check_input_term:804] reached
[ 8.042377] [check_input_term:860] reached
[ 8.042940] [check_input_term:804] reached
[ 8.043553] [check_input_term:860] reached
[ 8.044084] [check_input_term:804] reached
[ 8.044648] [check_input_term:860] reached
[ 8.045188] [check_input_term:804] reached
[ 8.045838] [check_input_term:860] reached
[ 8.046375] [check_input_term:804] reached
[ 8.046940] [check_input_term:860] reached
[ 8.047517] [check_input_term:804] reached
[ 8.048069] [check_input_term:860] reached
[ 8.048671] [check_input_term:804] reached
[ 8.049255] [check_input_term:860] reached
[ 8.049818] [check_input_term:804] reached
[ 8.050393] [check_input_term:860] reached
[ 8.050938] [check_input_term:804] reached
[ 8.051513] [check_input_term:860] reached
[ 8.052049] [check_input_term:804] reached
[ 8.052601] [check_input_term:860] reached
[ 8.053117] [check_input_term:804] reached
[ 8.053681] [check_input_term:860] reached
[ 8.054218] [check_input_term:804] reached
[ 8.054782] [check_input_term:860] reached
[ 8.055355] [check_input_term:804] reached
[ 8.055889] [check_input_term:860] reached
[ 8.056451] [check_input_term:804] reached
[ 8.056987] [check_input_term:860] reached
[ 8.057552] [check_input_term:804] reached
[ 8.058098] [check_input_term:860] reached
[ 8.058658] [check_input_term:804] reached
[ 8.059266] [check_input_term:860] reached
[ 8.059800] [check_input_term:804] reached
[ 8.060353] [check_input_term:860] reached
[ 8.060995] [check_input_term:804] reached
[ 8.061559] [check_input_term:860] reached
[ 8.062126] [check_input_term:804] reached
[ 8.062661] [check_input_term:860] reached
[ 8.063224] [check_input_term:804] reached
[ 8.063769] [check_input_term:860] reached
[ 8.064335] [check_input_term:804] reached
[ 8.064871] [check_input_term:860] reached
[ 8.065425] [check_input_term:804] reached
[ 8.065975] [check_input_term:860] reached
[ 8.066524] [check_input_term:804] reached
[ 8.067087] [check_input_term:860] reached
[ 8.067630] [check_input_term:804] reached
[ 8.068191] [check_input_term:860] reached
[ 8.068728] [check_input_term:804] reached
[ 8.069292] [check_input_term:860] reached
[ 8.069827] [check_input_term:804] reached
[ 8.070379] [check_input_term:860] reached
[ 8.070931] [check_input_term:804] reached
[ 8.071493] [check_input_term:860] reached
[ 8.072055] [check_input_term:804] reached
[ 8.072589] [check_input_term:860] reached
[ 8.073155] [check_input_term:804] reached
[ 8.073709] [check_input_term:860] reached
[ 8.074338] [check_input_term:804] reached
[ 8.074911] [check_input_term:860] reached
[ 8.075482] [check_input_term:804] reached
[ 8.076075] [check_input_term:860] reached
[ 8.076610] [check_input_term:804] reached
[ 8.077185] [check_input_term:860] reached
[ 8.077751] [check_input_term:804] reached
[ 8.078284] [check_input_term:860] reached
[ 8.078846] [check_input_term:804] reached
[ 8.079397] [check_input_term:860] reached
[ 8.079987] [check_input_term:804] reached
[ 8.080522] [check_input_term:860] reached
[ 8.081084] [check_input_term:804] reached
[ 8.081650] [check_input_term:860] reached
[ 8.082225] [check_input_term:804] reached
[ 8.082794] [check_input_term:860] reached
[ 8.085551] [check_input_term:804] reached
[ 8.086089] [check_input_term:860] reached
[ 8.086653] [check_input_term:804] reached
[ 8.087188] [check_input_term:860] reached
[ 8.087760] [check_input_term:804] reached
[ 8.088295] [check_input_term:860] reached
[ 8.088855] [check_input_term:804] reached
[ 8.089400] [check_input_term:860] reached
[ 8.089990] [check_input_term:804] reached
[ 8.090554] [check_input_term:860] reached
[ 8.091089] [check_input_term:804] reached
[ 8.091661] [check_input_term:860] reached
[ 8.092193] [check_input_term:804] reached
[ 8.092752] [check_input_term:860] reached
[ 8.093369] [check_input_term:804] reached
[ 8.093939] [check_input_term:860] reached
[ 8.094488] [check_input_term:804] reached
[ 8.095004] [check_input_term:860] reached
[ 8.095574] [check_input_term:804] reached
[ 8.096113] [check_input_term:860] reached
[ 8.096675] [check_input_term:804] reached
[ 8.097240] [check_input_term:860] reached
[ 8.097805] [check_input_term:804] reached
[ 8.098380] [check_input_term:860] reached
[ 8.098919] [check_input_term:804] reached
[ 8.099533] [check_input_term:860] reached
[ 8.100121] [check_input_term:804] reached
[ 8.100651] [check_input_term:860] reached
[ 8.101229] [check_input_term:804] reached
[ 8.101859] [check_input_term:860] reached
[ 8.102515] [check_input_term:804] reached
[ 8.103190] [check_input_term:860] reached
[ 8.103806] [check_input_term:804] reached
[ 8.104393] [check_input_term:860] reached
[ 8.104921] [check_input_term:804] reached
[ 8.105466] [check_input_term:860] reached
[ 8.106065] [check_input_term:804] reached
[ 8.106598] [check_input_term:860] reached
[ 8.107160] [check_input_term:804] reached
[ 8.107701] [check_input_term:860] reached
[ 8.108269] [check_input_term:804] reached
[ 8.108804] [check_input_term:860] reached
[ 8.109364] [check_input_term:804] reached
[ 8.109945] [check_input_term:860] reached
[ 8.110480] [check_input_term:804] reached
[ 8.111043] [check_input_term:860] reached
[ 8.111612] [check_input_term:804] reached
[ 8.112179] [check_input_term:860] reached
[ 8.112715] [check_input_term:804] reached
[ 8.113278] [check_input_term:860] reached
[ 8.113848] [check_input_term:804] reached
[ 8.114384] [check_input_term:860] reached
[ 8.114943] [check_input_term:804] reached
[ 8.115517] [check_input_term:860] reached
[ 8.116080] [check_input_term:804] reached
[ 8.116656] [check_input_term:860] reached
[ 8.117219] [check_input_term:804] reached
[ 8.117785] [check_input_term:860] reached
[ 8.118379] [check_input_term:804] reached
[ 8.118943] [check_input_term:860] reached
[ 8.119485] [check_input_term:804] reached
[ 8.120048] [check_input_term:860] reached
[ 8.120613] [check_input_term:804] reached
[ 8.121205] [check_input_term:860] reached
[ 8.121767] [check_input_term:804] reached
[ 8.122301] [check_input_term:860] reached
[ 8.122867] [check_input_term:804] reached
[ 8.123430] [check_input_term:860] reached
[ 8.123995] [check_input_term:804] reached
[ 8.124562] [check_input_term:860] reached
[ 8.125093] [check_input_term:804] reached
[ 8.125652] [check_input_term:860] reached
[ 8.126253] [check_input_term:804] reached
[ 8.126814] [check_input_term:860] reached
[ 8.127350] [check_input_term:804] reached
[ 8.127942] [check_input_term:860] reached
[ 8.128506] [check_input_term:804] reached
[ 8.129038] [check_input_term:860] reached
[ 8.129594] [check_input_term:804] reached
[ 8.130193] [check_input_term:860] reached
[ 8.130756] [check_input_term:804] reached
[ 8.131298] [check_input_term:860] reached
[ 8.131855] [check_input_term:804] reached
[ 8.132411] [check_input_term:860] reached
[ 8.132969] [check_input_term:804] reached
[ 8.133568] [check_input_term:860] reached
[ 8.134103] [check_input_term:804] reached
[ 8.134658] [check_input_term:860] reached
[ 8.135251] [check_input_term:804] reached
[ 8.135780] [check_input_term:860] reached
[ 8.136345] [check_input_term:804] reached
[ 8.136882] [check_input_term:860] reached
[ 8.137446] [check_input_term:804] reached
[ 8.137979] [check_input_term:860] reached
[ 8.138547] [check_input_term:804] reached
[ 8.139081] [check_input_term:860] reached
[ 8.139642] [check_input_term:804] reached
[ 8.140208] [check_input_term:860] reached
[ 8.140741] [check_input_term:804] reached
[ 8.141313] [check_input_term:860] reached
[ 8.141848] [check_input_term:804] reached
[ 8.142408] [check_input_term:860] reached
[ 8.142957] [check_input_term:804] reached
[ 8.143525] [check_input_term:860] reached
[ 8.144088] [check_input_term:804] reached
[ 8.144618] [check_input_term:860] reached
[ 8.145179] [check_input_term:804] reached
[ 8.145712] [check_input_term:860] reached
[ 8.146298] [check_input_term:804] reached
[ 8.146817] [check_input_term:860] reached
[ 8.147416] [check_input_term:804] reached
[ 8.147990] [check_input_term:860] reached
[ 8.148522] [check_input_term:804] reached
[ 8.149081] [check_input_term:860] reached
[ 8.149624] [check_input_term:804] reached
[ 8.150234] [check_input_term:860] reached
[ 8.150766] [check_input_term:804] reached
[ 8.151334] [check_input_term:860] reached
[ 8.151927] [check_input_term:804] reached
[ 8.152467] [check_input_term:860] reached
[ 8.153026] [check_input_term:804] reached
........[ 11.951264] usb 1-1: new high-speed USB device number 2 using xhci_hcd
[ 12.078302] usb 1-1: Using ep0 maxpacket: 16
[ 12.080698] usb 1-1: string descriptor 0 read error: -22
[ 12.081917] usb 1-1: New USB device found, idVendor=046d, idProduct=0a44, bcdDevice= 1.27
[ 12.083734] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[ 12.090675] usb 1-1: current rate 16732531 is different from the runtime rate 48000
[ 12.092985] usb 1-1: current rate 11254477 is different from the runtime rate 48000
[ 12.105244] BUG: KASAN: use-after-free in tick_sched_handle+0x51/0x90
[ 12.106010] Read of size 8 at addr ffff88815a1a9ed0 by task kworker/3:2/4772
[ 12.106841]
[ 12.107023] CPU: 3 PID: 4772 Comm: kworker/3:2 Not tainted 5.3.0-rc4+ #35
[ 12.107841] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.11.0-0-g63451fca13-prebuilt.qemu-project.org 04/01/2014
[ 12.109200] Workqueue: usb_hub_wq hub_event
[ 12.109734] Call Trace:
[ 12.110023] <IRQ>
[ 12.110266] dump_stack+0x5b/0x8b
[ 12.110665] ? tick_sched_handle+0x51/0x90
[ 12.111163] print_address_description+0x6e/0x390
[ 12.111749] ? tick_sched_handle+0x51/0x90
[ 12.112221] ? tick_sched_handle+0x51/0x90
[ 12.112732] __kasan_report+0x149/0x18d
[ 12.113175] ? tick_sched_handle+0x51/0x90
[ 12.113681] kasan_report+0xe/0x20
[ 12.114076] tick_sched_handle+0x51/0x90
[ 12.114529] tick_sched_timer+0x32/0x90
[ 12.115007] __hrtimer_run_queues+0x1f5/0x450
[ 12.115514] ? tick_sched_do_timer+0x80/0x80
[ 12.116041] ? enqueue_hrtimer+0x100/0x100
[ 12.116514] ? kvm_clock_get_cycles+0xd/0x10
[ 12.117038] ? ktime_get_update_offsets_now+0xa4/0x160
[ 12.117659] hrtimer_interrupt+0x192/0x350
[ 12.118133] smp_apic_timer_interrupt+0x83/0x1c0
[ 12.118696] apic_timer_interrupt+0xf/0x20
[ 12.119174] WARNING: can't dereference registers at 00000000394dde74 for ip apic_timer_interrupt+0xf/0x20
[ 12.119175] </IRQ>
[ 12.120550]
[ 12.120751] Allocated by task 1511944392:
[ 12.121216] BUG: unable to handle page fault for address: ffffffff8712da08
[ 12.122029] #PF: supervisor read access in kernel mode
[ 12.122649] #PF: error_code(0x0000) - not-present page
[ 12.123239] PGD 4212067 P4D 4212067 PUD 4213063 PMD 0
[ 12.123860] Thread overran stack, or stack corrupted
[ 12.124534] Oops: 0000 [#1] SMP KASAN PTI
[ 12.125009] CPU: 3 PID: 4772 Comm: kworker/3:2 Not tainted 5.3.0-rc4+ #35
[ 12.125816] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.11.0-0-g63451fca13-prebuilt.qemu-project.org 04/01/2014
[ 12.127172] Workqueue: usb_hub_wq hub_event
[ 12.127689] RIP: 0010:stack_depot_fetch+0x10/0x30
[ 12.128227] Code: ff 48 8b 73 18 48 89 ef 5b 5d e9 4b bb bd ff 0f 0b 90 90 90 90 90 90 90 90 90 89 f8 c1 ef 11 25 ff ff 1f 00 81 e7 f0 3f 00 00 <48> 03 3c c5 00 96 16 86 48 8d 47 18 48 89 06 8b 47 0c c3 0f 1f 00
[ 12.130392] RSP: 0018:ffff88815b189d68 EFLAGS: 00010006
[ 12.131022] RAX: 00000000001f8881 RBX: ffff88815a1aa100 RCX: ffffffff812150de
[ 12.131867] RDX: 0000000000000000 RSI: ffff88815b189d70 RDI: 0000000000003ff0
[ 12.132722] RBP: ffff88815a1a9ed0 R08: ffffed102b633ea3 R09: ffffed102b633ea3
[ 12.133554] R10: 0000000000000001 R11: ffffed102b633ea2 R12: ffff88815a9017c0
[ 12.134375] R13: ffff88815a1a9100 R14: ffff88815a1aa100 R15: ffff88815b1a5b00
[ 12.135209] FS: 0000000000000000(0000) GS:ffff88815b180000(0000) knlGS:0000000000000000
[ 12.136156] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 12.136845] CR2: ffffffff8712da08 CR3: 0000000152f26000 CR4: 00000000000006e0
[ 12.137688] Call Trace:
[ 12.137977] <IRQ>
[ 12.138218] print_track+0x35/0x6b
[ 12.138647] print_address_description+0x335/0x390
[ 12.139200] ? tick_sched_handle+0x51/0x90
[ 12.139706] ? tick_sched_handle+0x51/0x90
[ 12.140177] __kasan_report+0x149/0x18d
[ 12.140654] ? tick_sched_handle+0x51/0x90
[ 12.141126] kasan_report+0xe/0x20
[ 12.141557] tick_sched_handle+0x51/0x90
[ 12.142009] tick_sched_timer+0x32/0x90
[ 12.142486] __hrtimer_run_queues+0x1f5/0x450
[ 12.142986] ? tick_sched_do_timer+0x80/0x80
[ 12.143514] ? enqueue_hrtimer+0x100/0x100
[ 12.143986] ? kvm_clock_get_cycles+0xd/0x10
[ 12.144510] ? ktime_get_update_offsets_now+0xa4/0x160
[ 12.145097] hrtimer_interrupt+0x192/0x350
[ 12.145602] smp_apic_timer_interrupt+0x83/0x1c0
[ 12.146133] apic_timer_interrupt+0xf/0x20
[ 12.146637] </IRQ>
[ 12.146885] Modules linked in:
[ 12.147277] CR2: ffffffff8712da08
[ 12.147662] ---[ end trace 542cd123c33e7da5 ]---
[ 12.148203] RIP: 0010:stack_depot_fetch+0x10/0x30
[ 12.148765] Code: ff 48 8b 73 18 48 89 ef 5b 5d e9 4b bb bd ff 0f 0b 90 90 90 90 90 90 90 90 90 89 f8 c1 ef 11 25 ff ff 1f 00 81 e7 f0 3f 00 00 <48> 03 3c c5 00 96 16 86 48 8d 47 18 48 89 06 8b 47 0c c3 0f 1f 00
[ 12.150932] RSP: 0018:ffff88815b189d68 EFLAGS: 00010006
[ 12.151556] RAX: 00000000001f8881 RBX: ffff88815a1aa100 RCX: ffffffff812150de
[ 12.152395] RDX: 0000000000000000 RSI: ffff88815b189d70 RDI: 0000000000003ff0
[ 12.153233] RBP: ffff88815a1a9ed0 R08: ffffed102b633ea3 R09: ffffed102b633ea3
[ 12.154039] R10: 0000000000000001 R11: ffffed102b633ea2 R12: ffff88815a9017c0
[ 12.154973] R13: ffff88815a1a9100 R14: ffff88815a1aa100 R15: ffff88815b1a5b00
[ 12.155830] FS: 0000000000000000(0000) GS:ffff88815b180000(0000) knlGS:0000000000000000
[ 12.156777] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 12.157473] CR2: ffffffff8712da08 CR3: 0000000152f26000 CR4: 00000000000006e0
[ 12.158320] Kernel panic - not syncing: Fatal exception in interrupt
[ 12.159210] Kernel Offset: disabled
[ 12.159642] ---[ end Kernel panic - not syncing: Fatal exception in interrupt ]---