kernel/irq: Null-ptr deref on handle_irq_event_percpu function

From: Baozeng Ding
Date: Wed Mar 16 2016 - 11:00:27 EST


+linux-kernel and irq maitainer.

Best Regards,
Baozeng Ding

On Thu, Feb 25, 2016 at 04:16:10AM -0500, Red Hat Product Security wrote:
> On Wed Feb 24 08:44:30 2016, sploving1@xxxxxxxxx wrote:
> > Dear all,
> >
> > I hit the following bug when fuzzing kernel using
> > syzkaller:
> >
> > kasan: CONFIG_KASAN_INLINE enabled
> > kasan: GPF could be caused by NULL-ptr deref or user memory
> > accessgeneral protection fault: 0000 [#1] SMP KASAN
> > Modules linked in:
> > CPU: 3 PID: 0 Comm: swapper/3 Not tainted 4.4.0+ #5
> > Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS
> > rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014
> > task: ffff88002eb09700 ti: ffff88002eb88000 task.ti: ffff88002eb88000
> > RIP: 0010:[<ffffffff8143352d>] [<ffffffff8143352d>]
> > handle_irq_event_percpu+0xcd/0x6d0
> > RSP: 0018:ffff880053307e20 EFLAGS: 00010082
> > RAX: 0000000000000000 RBX: dffffc0000000000 RCX: 0000000000000001
> > RDX: 0000000000010000 RSI: ffff88002eb09f18 RDI: 0000000000000046
> > RBP: ffff880053307e70 R08: 0000000000000001 R09: 0000000000000001
> > R10: 0000000000000000 R11: 0000000000000001 R12: 0000000000000000
> > R13: ffff88002f1706b0 R14: ffffed0005e2e0de R15: ffff88002f1706b0
> > FS: 0000000000000000(0000) GS:ffff880053300000(0000)
> > knlGS:0000000000000000
> > CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b
> > CR2: 000000002000c000 CR3: 0000000000a82000 CR4: 00000000000006e0
> > Stack:
> > ffff88002f170680 000000002eb09700 1ffffffff0f464b2 fffffbfff0f464ba
> > 0000000400000000 ffff88002f170680 ffff88002f170720 ffff88002f1706b0
> > ffffed0005e2e0de ffff88002f1706b0 ffff880053307ea0 ffffffff81433bd7
> > Call Trace:
> > Call Trace:
> > <IRQ>
> > [<ffffffff81433bd7>] handle_irq_event+0xa7/0x140
> > kernel/irq/handle.c:193
> > [<ffffffff8143d7f1>] handle_edge_irq+0x1e1/0x8d0
> > kernel/irq/chip.c:623
> > [< inline >] generic_handle_irq_desc
> > kernel/include/linux/irqdesc.h:146
> > [<ffffffff811674e9>] handle_irq+0x109/0x2a0
> > kernel/arch/x86/kernel/irq_64.c:78
> > [< inline >] ? rcu_lock_release
> > kernel/include/linux/rcupdate.h:495
> > [< inline >] ? rcu_read_unlock
> > kernel/include/linux/rcupdate.h:930
> > [< inline >] ? __atomic_notifier_call_chain
> > kernel/kernel/notifier.c:184
> > [<ffffffff81362e5f>] ? atomic_notifier_call_chain+0xbf/0x140
> > kernel/kernel/notifier.c:193
> > [<ffffffff81362da0>] ? __atomic_notifier_call_chain+0x150/0x150
> > kernel/include/linux/rcupdate.h:926
> > [<ffffffff811660bd>] do_IRQ+0x7d/0x1a0
> > kernel/arch/x86/kernel/irq.c:240
> > [<ffffffff85d889cc>] common_interrupt+0x8c/0x8c
> > kernel/arch/x86/entry/entry_64.S:520
> > [<ffffffff81222526>] ? native_safe_halt+0x6/0x10
> > kernel/arch/x86/include/asm/irqflags.h:49
> > [< inline >] arch_safe_halt
> > kernel/arch/x86/include/asm/paravirt.h:117
> > [<ffffffff811790a2>] default_idle+0x22/0x2a0
> > kernel/arch/x86/kernel/process.c:304
> > [<ffffffff8117a41a>] arch_cpu_idle+0xa/0x10
> > kernel/arch/x86/kernel/process.c:295
> > [<ffffffff813e50f8>] default_idle_call+0x48/0x70
> > kernel/kernel/sched/idle.c:92
> > [< inline >] cpuidle_idle_call
> > kernel/kernel/sched/idle.c:156
> > [< inline >] cpu_idle_loop kernel/kernel/sched/idle.c:252
> > [<ffffffff813e56bf>] cpu_startup_entry+0x4bf/0x610
> > kernel/kernel/sched/idle.c:300
> > [<ffffffff811fe6d8>] start_secondary+0x2a8/0x380
> > kernel/arch/x86/kernel/smpboot.c:251
> > [<ffffffff811fe430>] ? set_cpu_sibling_map+0x1890/0x1890
> > kernel/include/linux/topology.h:80
> > Code: 48 89 45 c8 48 c7 c0 90 25 a3 87 48 c1 e8 03 48 89 45 c0 e9 4f
> > 01 00 00 e8 31 8e 0e 00 4c 89 e0 48 c1 e8 03 65 ff 0d 23 0a be 7e <80>
> > 3c 18 00 0f 85 8c 05 00 00 49 8d 7c 24 08 4d 8b 34 24 48 89
> > RIP [< inline >] __preempt_count_sub
> > kernel/arch/x86/include/asm/preempt.h:74
> > RIP [< inline >] rcu_read_unlock_sched_notrace
> > kernel/include/linux/rcupdate.h:1020
> > RIP [< inline >] trace_irq_handler_entry
> > kernel/include/trace/events/irq.h:52
> > RIP [<ffffffff8143352d>] handle_irq_event_percpu+0xcd/0x6d0
> > kernel/kernel/irq/handle.c:144
> > RSP <ffff880053307e20>
> > ---[ end trace 0984a7cc502bc978 ]---
> > Kernel panic - not syncing: Fatal exception in interrupt
> > Kernel Offset: disabled
> > ---[ end Kernel panic - not syncing: Fatal exception in interrupt
> >
> >
> > I cannot produce the bug, but by taking a look at the
> > code(irq/handle.c line176), it may
> > casue a null pointer deref:
> >
> > http://lxr.free-electrons.com/source/kernel/irq/handle.c#L176
> >
> > 141 do {
> > 142 irqreturn_t res;
> > 143
> > 144 trace_irq_handler_entry(irq, action);
> > 145 res = action->handler(irq, action->dev_id);
> > 146 trace_irq_handler_exit(irq, action, res);
> > 147
> > 148 if (WARN_ONCE(!irqs_disabled(),"irq %u handler %pF
> > enabled interrupts\n",
> > 149 irq, action->handler))
> > 150 local_irq_disable();
> > 151
> > 152 switch (res) {
> > 153 case IRQ_WAKE_THREAD:
> > 154 /*
> > 155 * Catch drivers which return WAKE_THREAD
> > but
> > 156 * did not set up a thread function
> > 157 */
> > 158 if (unlikely(!action->thread_fn)) {
> > 159 warn_no_thread(irq, action);
> > 160 break;
> > 161 }
> > 162
> > 163 __irq_wake_thread(desc, action);
> > 164
> > 165 /* Fall through to add to randomness */
> > 166 case IRQ_HANDLED:
> > 167 flags |= action->flags;
> > 168 break;
> > 169
> > 170 default:
> > 171 break;
> > 172 }
> > 173
> > 174 retval |= res;
> > 175 action = action->next;
> > 176 } while (action); //when action is null, it will
> > //cause a null pointer deref.
> >
> > The vulnerability was found in the latest Linux kernel version(4.4)
> > Could you allocate a CVE id for this? Thank you.
> >
> > ps:I have neither published it nor requested CVE from other CNA.
> >
> > Baozeng Ding
> >
> >
>
> Hello Baozeng,
>
> Thank you for reporting us this issue. We'll analyze it and respond to you
> soon. We'll assign CVE, once we confirm the vulnerability.
>
> Best Regards,
> --
> Adam MariÅ / Red Hat Product Security
>