lkml.org 
[lkml]   [2016]   [Sep]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v2 2/5] perf: Fix aux_mmap_count vs aux_refcount order
    Date
    The order of accesses to ring buffer's aux_mmap_count and aux_refcount
    has to be preserved across the users, namely perf_mmap_close() and
    perf_aux_output_begin(), otherwise the inversion can result in the latter
    holding the last reference to the aux buffer and subsequently free'ing
    it in atomic context, triggering a warning.

    > ------------[ cut here ]------------
    > WARNING: CPU: 0 PID: 257 at kernel/events/ring_buffer.c:541 __rb_free_aux+0x11a/0x130
    > CPU: 0 PID: 257 Comm: stopbug Not tainted 4.8.0-rc1+ #2596
    > Call Trace:
    > [<ffffffff810f3e0b>] __warn+0xcb/0xf0
    > [<ffffffff810f3f3d>] warn_slowpath_null+0x1d/0x20
    > [<ffffffff8121182a>] __rb_free_aux+0x11a/0x130
    > [<ffffffff812127a8>] rb_free_aux+0x18/0x20
    > [<ffffffff81212913>] perf_aux_output_begin+0x163/0x1e0
    > [<ffffffff8100c33a>] bts_event_start+0x3a/0xd0
    > [<ffffffff8100c42d>] bts_event_add+0x5d/0x80
    > [<ffffffff81203646>] event_sched_in.isra.104+0xf6/0x2f0
    > [<ffffffff8120652e>] group_sched_in+0x6e/0x190
    > [<ffffffff8120694e>] ctx_sched_in+0x2fe/0x5f0
    > [<ffffffff81206ca0>] perf_event_sched_in+0x60/0x80
    > [<ffffffff81206d1b>] ctx_resched+0x5b/0x90
    > [<ffffffff81207281>] __perf_event_enable+0x1e1/0x240
    > [<ffffffff81200639>] event_function+0xa9/0x180
    > [<ffffffff81202000>] ? perf_cgroup_attach+0x70/0x70
    > [<ffffffff8120203f>] remote_function+0x3f/0x50
    > [<ffffffff811971f3>] flush_smp_call_function_queue+0x83/0x150
    > [<ffffffff81197bd3>] generic_smp_call_function_single_interrupt+0x13/0x60
    > [<ffffffff810a6477>] smp_call_function_single_interrupt+0x27/0x40
    > [<ffffffff81a26ea9>] call_function_single_interrupt+0x89/0x90
    > [<ffffffff81120056>] finish_task_switch+0xa6/0x210
    > [<ffffffff81120017>] ? finish_task_switch+0x67/0x210
    > [<ffffffff81a1e83d>] __schedule+0x3dd/0xb50
    > [<ffffffff81a1efe5>] schedule+0x35/0x80
    > [<ffffffff81128031>] sys_sched_yield+0x61/0x70
    > [<ffffffff81a25be5>] entry_SYSCALL_64_fastpath+0x18/0xa8
    > ---[ end trace 6235f556f5ea83a9 ]---

    This patch puts the checks in perf_aux_output_begin() in the same order
    as that of perf_mmap_close().

    Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
    ---
    kernel/events/ring_buffer.c | 16 ++++++++++------
    1 file changed, 10 insertions(+), 6 deletions(-)

    diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c
    index ae9b90dc9a..71c9194b1f 100644
    --- a/kernel/events/ring_buffer.c
    +++ b/kernel/events/ring_buffer.c
    @@ -330,15 +330,19 @@ void *perf_aux_output_begin(struct perf_output_handle *handle,
    if (!rb)
    return NULL;

    - if (!rb_has_aux(rb) || !atomic_inc_not_zero(&rb->aux_refcount))
    - goto err;
    -
    /*
    - * If rb::aux_mmap_count is zero (and rb_has_aux() above went through),
    - * the aux buffer is in perf_mmap_close(), about to get freed.
    + * If aux_mmap_count is zero, the aux buffer is in perf_mmap_close(),
    + * about to get freed, so we leave immediately.
    + *
    + * Checking rb::aux_mmap_count and rb::refcount has to be done in
    + * the same order, see perf_mmap_close. Otherwise we end up freeing
    + * aux pages in this path, which is a bug, because in_atomic().
    */
    if (!atomic_read(&rb->aux_mmap_count))
    - goto err_put;
    + goto err;
    +
    + if (!rb_has_aux(rb) || !atomic_inc_not_zero(&rb->aux_refcount))
    + goto err;

    /*
    * Nesting is not supported for AUX area, make sure nested
    --
    2.9.3
    \
     
     \ /
      Last update: 2016-09-17 09:58    [W:5.198 / U:0.032 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site