lkml.org 
[lkml]   [2018]   [Apr]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.14 19/49] perf/core: Fix use-after-free in uprobe_perf_close()
    Date
    4.14-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Prashant Bhole <bhole_prashant_q7@lab.ntt.co.jp>

    commit 621b6d2ea297d0fb6030452c5bcd221f12165fcf upstream.

    A use-after-free bug was caught by KASAN while running usdt related
    code (BCC project. bcc/tests/python/test_usdt2.py):

    ==================================================================
    BUG: KASAN: use-after-free in uprobe_perf_close+0x222/0x3b0
    Read of size 4 at addr ffff880384f9b4a4 by task test_usdt2.py/870

    CPU: 4 PID: 870 Comm: test_usdt2.py Tainted: G W 4.16.0-next-20180409 #215
    Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Ubuntu-1.8.2-1ubuntu1 04/01/2014
    Call Trace:
    dump_stack+0xc7/0x15b
    ? show_regs_print_info+0x5/0x5
    ? printk+0x9c/0xc3
    ? kmsg_dump_rewind_nolock+0x6e/0x6e
    ? uprobe_perf_close+0x222/0x3b0
    print_address_description+0x83/0x3a0
    ? uprobe_perf_close+0x222/0x3b0
    kasan_report+0x1dd/0x460
    ? uprobe_perf_close+0x222/0x3b0
    uprobe_perf_close+0x222/0x3b0
    ? probes_open+0x180/0x180
    ? free_filters_list+0x290/0x290
    trace_uprobe_register+0x1bb/0x500
    ? perf_event_attach_bpf_prog+0x310/0x310
    ? probe_event_disable+0x4e0/0x4e0
    perf_uprobe_destroy+0x63/0xd0
    _free_event+0x2bc/0xbd0
    ? lockdep_rcu_suspicious+0x100/0x100
    ? ring_buffer_attach+0x550/0x550
    ? kvm_sched_clock_read+0x1a/0x30
    ? perf_event_release_kernel+0x3e4/0xc00
    ? __mutex_unlock_slowpath+0x12e/0x540
    ? wait_for_completion+0x430/0x430
    ? lock_downgrade+0x3c0/0x3c0
    ? lock_release+0x980/0x980
    ? do_raw_spin_trylock+0x118/0x150
    ? do_raw_spin_unlock+0x121/0x210
    ? do_raw_spin_trylock+0x150/0x150
    perf_event_release_kernel+0x5d4/0xc00
    ? put_event+0x30/0x30
    ? fsnotify+0xd2d/0xea0
    ? sched_clock_cpu+0x18/0x1a0
    ? __fsnotify_update_child_dentry_flags.part.0+0x1b0/0x1b0
    ? pvclock_clocksource_read+0x152/0x2b0
    ? pvclock_read_flags+0x80/0x80
    ? kvm_sched_clock_read+0x1a/0x30
    ? sched_clock_cpu+0x18/0x1a0
    ? pvclock_clocksource_read+0x152/0x2b0
    ? locks_remove_file+0xec/0x470
    ? pvclock_read_flags+0x80/0x80
    ? fcntl_setlk+0x880/0x880
    ? ima_file_free+0x8d/0x390
    ? lockdep_rcu_suspicious+0x100/0x100
    ? ima_file_check+0x110/0x110
    ? fsnotify+0xea0/0xea0
    ? kvm_sched_clock_read+0x1a/0x30
    ? rcu_note_context_switch+0x600/0x600
    perf_release+0x21/0x40
    __fput+0x264/0x620
    ? fput+0xf0/0xf0
    ? do_raw_spin_unlock+0x121/0x210
    ? do_raw_spin_trylock+0x150/0x150
    ? SyS_fchdir+0x100/0x100
    ? fsnotify+0xea0/0xea0
    task_work_run+0x14b/0x1e0
    ? task_work_cancel+0x1c0/0x1c0
    ? copy_fd_bitmaps+0x150/0x150
    ? vfs_read+0xe5/0x260
    exit_to_usermode_loop+0x17b/0x1b0
    ? trace_event_raw_event_sys_exit+0x1a0/0x1a0
    do_syscall_64+0x3f6/0x490
    ? syscall_return_slowpath+0x2c0/0x2c0
    ? lockdep_sys_exit+0x1f/0xaa
    ? syscall_return_slowpath+0x1a3/0x2c0
    ? lockdep_sys_exit+0x1f/0xaa
    ? prepare_exit_to_usermode+0x11c/0x1e0
    ? enter_from_user_mode+0x30/0x30
    random: crng init done
    ? __put_user_4+0x1c/0x30
    entry_SYSCALL_64_after_hwframe+0x3d/0xa2
    RIP: 0033:0x7f41d95f9340
    RSP: 002b:00007fffe71e4268 EFLAGS: 00000246 ORIG_RAX: 0000000000000003
    RAX: 0000000000000000 RBX: 000000000000000d RCX: 00007f41d95f9340
    RDX: 0000000000000000 RSI: 0000000000002401 RDI: 000000000000000d
    RBP: 0000000000000000 R08: 00007f41ca8ff700 R09: 00007f41d996dd1f
    R10: 00007fffe71e41e0 R11: 0000000000000246 R12: 00007fffe71e4330
    R13: 0000000000000000 R14: fffffffffffffffc R15: 00007fffe71e4290

    Allocated by task 870:
    kasan_kmalloc+0xa0/0xd0
    kmem_cache_alloc_node+0x11a/0x430
    copy_process.part.19+0x11a0/0x41c0
    _do_fork+0x1be/0xa20
    do_syscall_64+0x198/0x490
    entry_SYSCALL_64_after_hwframe+0x3d/0xa2

    Freed by task 0:
    __kasan_slab_free+0x12e/0x180
    kmem_cache_free+0x102/0x4d0
    free_task+0xfe/0x160
    __put_task_struct+0x189/0x290
    delayed_put_task_struct+0x119/0x250
    rcu_process_callbacks+0xa6c/0x1b60
    __do_softirq+0x238/0x7ae

    The buggy address belongs to the object at ffff880384f9b480
    which belongs to the cache task_struct of size 12928

    It occurs because task_struct is freed before perf_event which refers
    to the task and task flags are checked while teardown of the event.
    perf_event_alloc() assigns task_struct to hw.target of perf_event,
    but there is no reference counting for it.

    As a fix we get_task_struct() in perf_event_alloc() at above mentioned
    assignment and put_task_struct() in _free_event().

    Signed-off-by: Prashant Bhole <bhole_prashant_q7@lab.ntt.co.jp>
    Reviewed-by: Oleg Nesterov <oleg@redhat.com>
    Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
    Cc: <stable@kernel.org>
    Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
    Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
    Cc: Jiri Olsa <jolsa@redhat.com>
    Cc: Linus Torvalds <torvalds@linux-foundation.org>
    Cc: Namhyung Kim <namhyung@kernel.org>
    Cc: Peter Zijlstra <peterz@infradead.org>
    Cc: Thomas Gleixner <tglx@linutronix.de>
    Fixes: 63b6da39bb38e8f1a1ef3180d32a39d6 ("perf: Fix perf_event_exit_task() race")
    Link: http://lkml.kernel.org/r/20180409100346.6416-1-bhole_prashant_q7@lab.ntt.co.jp
    Signed-off-by: Ingo Molnar <mingo@kernel.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    kernel/events/core.c | 6 ++++++
    1 file changed, 6 insertions(+)

    --- a/kernel/events/core.c
    +++ b/kernel/events/core.c
    @@ -4199,6 +4199,9 @@ static void _free_event(struct perf_even
    if (event->ctx)
    put_ctx(event->ctx);

    + if (event->hw.target)
    + put_task_struct(event->hw.target);
    +
    exclusive_event_destroy(event);
    module_put(event->pmu->module);

    @@ -9508,6 +9511,7 @@ perf_event_alloc(struct perf_event_attr
    * and we cannot use the ctx information because we need the
    * pmu before we get a ctx.
    */
    + get_task_struct(task);
    event->hw.target = task;
    }

    @@ -9623,6 +9627,8 @@ err_ns:
    perf_detach_cgroup(event);
    if (event->ns)
    put_pid_ns(event->ns);
    + if (event->hw.target)
    + put_task_struct(event->hw.target);
    kfree(event);

    return ERR_PTR(err);

    \
     
     \ /
      Last update: 2018-04-17 18:42    [W:4.305 / U:0.368 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site