futex: Remove unnecessary warning from get_futex_key

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>
Cc: stable@vger.kernel.org # 4.7+
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by Mel Gorman and committed by Linus Torvalds 48fb6f4d 358f8c26

+3 -2
+3 -2
kernel/futex.c
··· 670 670 * this reference was taken by ihold under the page lock 671 671 * pinning the inode in place so i_lock was unnecessary. The 672 672 * only way for this check to fail is if the inode was 673 - * truncated in parallel so warn for now if this happens. 673 + * truncated in parallel which is almost certainly an 674 + * application bug. In such a case, just retry. 674 675 * 675 676 * We are not calling into get_futex_key_refs() in file-backed 676 677 * cases, therefore a successful atomic_inc return below will 677 678 * guarantee that get_futex_key() will still imply smp_mb(); (B). 678 679 */ 679 - if (WARN_ON_ONCE(!atomic_inc_not_zero(&inode->i_count))) { 680 + if (!atomic_inc_not_zero(&inode->i_count)) { 680 681 rcu_read_unlock(); 681 682 put_page(page); 682 683