lkml.org 
[lkml]   [2017]   [Aug]   [14]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.12 03/65] futex: Remove unnecessary warning from get_futex_key
    Date
    4.12-stable review patch.  If anyone has any objections, please let me know.

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

    From: Mel Gorman <mgorman@suse.de>

    commit 48fb6f4db940e92cfb16cd878cddd59ea6120d06 upstream.

    Commit 65d8fc777f6d ("futex: Remove requirement for lock_page() in
    get_futex_key()") removed an unnecessary lock_page() with the
    side-effect that page->mapping needed to be treated very carefully.

    Two defensive warnings were added in case any assumption was missed and
    the first warning assumed a correct application would not alter a
    mapping backing a futex key. Since merging, it has not triggered for
    any unexpected case but Mark Rutland reported the following bug
    triggering due to the first warning.

    kernel BUG at kernel/futex.c:679!
    Internal error: Oops - BUG: 0 [#1] PREEMPT SMP
    Modules linked in:
    CPU: 0 PID: 3695 Comm: syz-executor1 Not tainted 4.13.0-rc3-00020-g307fec773ba3 #3
    Hardware name: linux,dummy-virt (DT)
    task: ffff80001e271780 task.stack: ffff000010908000
    PC is at get_futex_key+0x6a4/0xcf0 kernel/futex.c:679
    LR is at get_futex_key+0x6a4/0xcf0 kernel/futex.c:679
    pc : [<ffff00000821ac14>] lr : [<ffff00000821ac14>] pstate: 80000145

    The fact that it's a bug instead of a warning was due to an unrelated
    arm64 problem, but the warning itself triggered because the underlying
    mapping changed.

    This is an application issue but from a kernel perspective it's a
    recoverable situation and the warning is unnecessary so this patch
    removes the warning. The warning may potentially be triggered with the
    following test program from Mark although it may be necessary to adjust
    NR_FUTEX_THREADS to be a value smaller than the number of CPUs in the
    system.

    #include <linux/futex.h>
    #include <pthread.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/mman.h>
    #include <sys/syscall.h>
    #include <sys/time.h>
    #include <unistd.h>

    #define NR_FUTEX_THREADS 16
    pthread_t threads[NR_FUTEX_THREADS];

    void *mem;

    #define MEM_PROT (PROT_READ | PROT_WRITE)
    #define MEM_SIZE 65536

    static int futex_wrapper(int *uaddr, int op, int val,
    const struct timespec *timeout,
    int *uaddr2, int val3)
    {
    syscall(SYS_futex, uaddr, op, val, timeout, uaddr2, val3);
    }

    void *poll_futex(void *unused)
    {
    for (;;) {
    futex_wrapper(mem, FUTEX_CMP_REQUEUE_PI, 1, NULL, mem + 4, 1);
    }
    }

    int main(int argc, char *argv[])
    {
    int i;

    mem = mmap(NULL, MEM_SIZE, MEM_PROT,
    MAP_SHARED | MAP_ANONYMOUS, -1, 0);

    printf("Mapping @ %p\n", mem);

    printf("Creating futex threads...\n");

    for (i = 0; i < NR_FUTEX_THREADS; i++)
    pthread_create(&threads[i], NULL, poll_futex, NULL);

    printf("Flipping mapping...\n");
    for (;;) {
    mmap(mem, MEM_SIZE, MEM_PROT,
    MAP_FIXED | MAP_SHARED | MAP_ANONYMOUS, -1, 0);
    }

    return 0;
    }

    Reported-and-tested-by: Mark Rutland <mark.rutland@arm.com>
    Signed-off-by: Mel Gorman <mgorman@suse.de>
    Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
    Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    kernel/futex.c | 5 +++--
    1 file changed, 3 insertions(+), 2 deletions(-)

    --- a/kernel/futex.c
    +++ b/kernel/futex.c
    @@ -670,13 +670,14 @@ again:
    * this reference was taken by ihold under the page lock
    * pinning the inode in place so i_lock was unnecessary. The
    * only way for this check to fail is if the inode was
    - * truncated in parallel so warn for now if this happens.
    + * truncated in parallel which is almost certainly an
    + * application bug. In such a case, just retry.
    *
    * We are not calling into get_futex_key_refs() in file-backed
    * cases, therefore a successful atomic_inc return below will
    * guarantee that get_futex_key() will still imply smp_mb(); (B).
    */
    - if (WARN_ON_ONCE(!atomic_inc_not_zero(&inode->i_count))) {
    + if (!atomic_inc_not_zero(&inode->i_count)) {
    rcu_read_unlock();
    put_page(page);


    \
     
     \ /
      Last update: 2017-08-15 03:35    [W:4.201 / U:0.452 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site