The kernel NULL pointer dereference happens when accessing the task_struct by task_cpu() in function cpuacct_charge()

Bug #1775326 reported by Gavin Guo on 2018-06-06
8
This bug affects 1 person
Affects Status Importance Assigned to Milestone
linux (Ubuntu)
Undecided
Gavin Guo
Xenial
Undecided
Unassigned

Bug Description

[Impact]

In function cpuacct_charge(), the NULL pointer dereference happens
with the stack pointer being zero inside the task_struct when the
task_cpu() is trying to access the member CPU of the struct
thread_info inside the stack. It's a use-after-free corruption
happening in the situation that the task_struct is released almost
concurrently before accessing the task_struct->stack.

void cpuacct_charge(struct task_struct *tsk, u64 cputime)
 {
        struct cpuacct *ca;
        int cpu;

        cpu = task_cpu(tsk);

        rcu_read_lock();

        ca = task_ca(tsk);

        while (true) {
                u64 *cpuusage = per_cpu_ptr(ca->cpuusage, cpu);
                *cpuusage += cputime;

                ca = parent_ca(ca);
                if (!ca)
                        break;
        }

 rcu_read_unlock();
}

BUG: unable to handle kernel NULL pointer dereference at 0000000000000010
IP: [<ffffffff810c3ff4>] cpuacct_charge+0x14/0x40
PGD 0
Oops: 0000 [#1] SMP
CPU: 10 PID: 148614 Comm: qemu-system-x86 Tainted: P W OE 4.4.0-45-generic #66~14.04.1-Ubuntu
Hardware name: Dell Inc. PowerEdge R630/02C2CP, BIOS 2.1.7 06/16/2016
task: ffff881ff0f01b80 ti: ffff88018fd70000 task.ti: ffff88018fd70000
RIP: 0010:[<ffffffff810c3ff4>] [<ffffffff810c3ff4>] cpuacct_charge+0x14/0x40
RSP: 0018:ffff88018fd73d10 EFLAGS: 00010246
RAX: 0000000000000000 RBX: ffff8801931e8000 RCX: ffff88010caff200
RDX: ffff880124508000 RSI: 0066f757398831d6 RDI: ffff8801931e7fa0
RBP: ffff88018fd73d10 R08: ffffffffc04b8320 R09: 0000000000000001
R10: 0000000000000001 R11: 0000000000000000 R12: 0066f757398831d6
R13: 0066f757398b8997 R14: ffff8801931e7fa0 R15: 0000000000000001
FS: 00007f162aaf7700(0000) GS:ffff881ffe740000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000000010 CR3: 000000011d86e000 CR4: 00000000003426e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Stack:
 ffff88018fd73d28 ffffffff810b1a9f ffff8801931e8000 ffff88018fd73d40
 ffffffffc069df72 ffff8801931e8000 ffff88018fd73da8 ffffffffc069f121
 ffff881ff0f01b80 0000000000000000 ffff881ff0f01b80 ffffffff810bddc0
Call Trace:
 [<ffffffff810b1a9f>] update_curr+0xdf/0x170
 [<ffffffffc069df72>] kvm_vcpu_check_block+0x12/0x60 [kvm]
 [<ffffffffc069f121>] kvm_vcpu_block+0x191/0x2d0 [kvm]
 [<ffffffff810bddc0>] ? prepare_to_wait_event+0xf0/0xf0
 [<ffffffffc06bb9ee>] kvm_arch_vcpu_ioctl_run+0x17e/0x3d0 [kvm]
 [<ffffffffc06a1f8b>] kvm_vcpu_ioctl+0x2ab/0x640 [kvm]
 [<ffffffff81174517>] ? perf_event_context_sched_in+0x87/0xa0
 [<ffffffff81210d6d>] do_vfs_ioctl+0x2dd/0x4c0
 [<ffffffff8111fa1f>] ? __audit_syscall_entry+0xaf/0x100
 [<ffffffff81003176>] ? do_audit_syscall_entry+0x66/0x70
 [<ffffffff81210fc9>] SyS_ioctl+0x79/0x90
 [<ffffffff817fa4f6>] entry_SYSCALL_64_fastpath+0x16/0x75
Code: 9a 11 00 5b 48 c7 c0 f4 ff ff ff 5d eb df 66 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 55 48 8b 47 08 48 8b 97 78 07 00 00 48 89 e5 <48> 63 48 10 48 8b 52 60 48 8b 82 b8 00 00 00 48 03 04 cd c0 7a
RIP [<ffffffff810c3ff4>] cpuacct_charge+0x14/0x40
 RSP <ffff88018fd73d10>
CR2: 0000000000000010
---[ end trace 419a30375d0e4622 ]---

[Fix]

The patch uses this_cpu_ptr() instead of getting the CPU number by
task_cpu() and proceeds to get the cpu_usage by per_cpu_ptr(). And
that can avoid accessing the thread_info inside the stack.

commit 73e6aafd9ea81498d31361f01db84a0118da2d1c
Author: Zhao Lei <email address hidden>
Date: Thu Mar 17 12:19:43 2016 +0800

    sched/cpuacct: Simplify the cpuacct code

     - Use for() instead of while() loop in some functions
       to make the code simpler.

     - Use this_cpu_ptr() instead of per_cpu_ptr() to make the code
       cleaner and a bit faster.

    Suggested-by: Peter Zijlstra <email address hidden>
    Signed-off-by: Zhao Lei <email address hidden>
    Signed-off-by: Peter Zijlstra (Intel) <email address hidden>
    Cc: Linus Torvalds <email address hidden>
    Cc: Tejun Heo <email address hidden>
    Cc: Thomas Gleixner <email address hidden>
    Link: http://lkml.kernel.org/r<email address hidden>
    Signed-off-by: Ingo Molnar <email address hidden>

[Test]
The test kernel has been tested by the Qemu and cannot be reproduced.

CVE References

This bug is missing log files that will aid in diagnosing the problem. While running an Ubuntu kernel (not a mainline or third-party kernel) please enter the following command in a terminal window:

apport-collect 1775326

and then change the status of the bug to 'Confirmed'.

If, due to the nature of the issue you have encountered, you are unable to run this command, please add a comment stating that fact and change the bug status to 'Confirmed'.

This change has been made by an automated script, maintained by the Ubuntu Kernel Team.

Changed in linux (Ubuntu):
status: New → Incomplete
tags: added: xenial
Gavin Guo (mimi0213kimo) on 2018-06-06
summary: - The kernel NULL pointer dereference happens when accessing the task by
- task_cpu() in function cpuacct_charge()
+ The kernel NULL pointer dereference happens when accessing the
+ task_struct by task_cpu() in function cpuacct_charge()
Changed in linux (Ubuntu Xenial):
status: New → In Progress
Changed in linux (Ubuntu Xenial):
status: In Progress → Fix Committed
Brad Figg (brad-figg) wrote :

This bug is awaiting verification that the kernel in -proposed solves the problem. Please test the kernel and update this bug with the results. If the problem is solved, change the tag 'verification-needed-xenial' to 'verification-done-xenial'. If the problem still exists, change the tag 'verification-needed-xenial' to 'verification-failed-xenial'.

If verification is not done by 5 working days from today, this fix will be dropped from the source code, and this bug will be closed.

See https://wiki.ubuntu.com/Testing/EnableProposed for documentation how to enable and use -proposed. Thank you!

tags: added: verification-needed-xenial

Hello Gavin,

Could you please verify the fix(es) with the Xenial kernel currently in -proposed?

Thank you.

Gavin Guo (mimi0213kimo) on 2018-06-21
tags: added: verification-done-xenial
removed: verification-needed-xenial
Launchpad Janitor (janitor) wrote :
Download full text (29.8 KiB)

This bug was fixed in the package linux - 4.4.0-130.156

---------------
linux (4.4.0-130.156) xenial; urgency=medium

  * linux: 4.4.0-130.156 -proposed tracker (LP: #1776822)

  * CVE-2018-3665 (x86)
    - x86/fpu: Fix early FPU command-line parsing
    - x86/fpu: Fix 'no387' regression
    - x86/fpu: Disable MPX when eagerfpu is off
    - x86/fpu: Default eagerfpu=on on all CPUs
    - x86/fpu: Fix FNSAVE usage in eagerfpu mode
    - x86/fpu: Fix math emulation in eager fpu mode
    - x86/fpu: Fix eager-FPU handling on legacy FPU machines

linux (4.4.0-129.155) xenial; urgency=medium

  * linux: 4.4.0-129.155 -proposed tracker (LP: #1776352)

  * Xenial update to 4.4.134 stable release (LP: #1775771)
    - MIPS: ptrace: Expose FIR register through FP regset
    - MIPS: Fix ptrace(2) PTRACE_PEEKUSR and PTRACE_POKEUSR accesses to o32 FGRs
    - KVM: Fix spelling mistake: "cop_unsuable" -> "cop_unusable"
    - affs_lookup(): close a race with affs_remove_link()
    - aio: fix io_destroy(2) vs. lookup_ioctx() race
    - ALSA: timer: Fix pause event notification
    - mmc: sdhci-iproc: fix 32bit writes for TRANSFER_MODE register
    - libata: Blacklist some Sandisk SSDs for NCQ
    - libata: blacklist Micron 500IT SSD with MU01 firmware
    - xen-swiotlb: fix the check condition for xen_swiotlb_free_coherent
    - Revert "ipc/shm: Fix shmat mmap nil-page protection"
    - ipc/shm: fix shmat() nil address after round-down when remapping
    - kasan: fix memory hotplug during boot
    - kernel/sys.c: fix potential Spectre v1 issue
    - kernel/signal.c: avoid undefined behaviour in kill_something_info
    - xfs: remove racy hasattr check from attr ops
    - do d_instantiate/unlock_new_inode combinations safely
    - firewire-ohci: work around oversized DMA reads on JMicron controllers
    - NFSv4: always set NFS_LOCK_LOST when a lock is lost.
    - ALSA: hda - Use IS_REACHABLE() for dependency on input
    - ASoC: au1x: Fix timeout tests in au1xac97c_ac97_read()
    - kvm: x86: fix KVM_XEN_HVM_CONFIG ioctl
    - tracing/hrtimer: Fix tracing bugs by taking all clock bases and modes into
      account
    - PCI: Add function 1 DMA alias quirk for Marvell 9128
    - tools lib traceevent: Simplify pointer print logic and fix %pF
    - perf callchain: Fix attr.sample_max_stack setting
    - tools lib traceevent: Fix get_field_str() for dynamic strings
    - dm thin: fix documentation relative to low water mark threshold
    - nfs: Do not convert nfs_idmap_cache_timeout to jiffies
    - watchdog: sp5100_tco: Fix watchdog disable bit
    - kconfig: Don't leak main menus during parsing
    - kconfig: Fix automatic menu creation mem leak
    - kconfig: Fix expr_free() E_NOT leak
    - ipmi/powernv: Fix error return code in ipmi_powernv_probe()
    - Btrfs: set plug for fsync
    - btrfs: Fix out of bounds access in btrfs_search_slot
    - Btrfs: fix scrub to repair raid6 corruption
    - scsi: fas216: fix sense buffer initialization
    - HID: roccat: prevent an out of bounds read in kovaplus_profile_activated()
    - jffs2: Fix use-after-free bug in jffs2_iget()'s error handling path
    - powerpc/numa: Use ibm,max-associativity-domains to discover possib...

Changed in linux (Ubuntu Xenial):
status: Fix Committed → Fix Released
To post a comment you must log in.
This report contains Public information  Edit
Everyone can see this information.

Other bug subscribers