From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755409AbcGHNRl (ORCPT ); Fri, 8 Jul 2016 09:17:41 -0400 Received: from terminus.zytor.com ([198.137.202.10]:54020 "EHLO terminus.zytor.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754985AbcGHNRc (ORCPT ); Fri, 8 Jul 2016 09:17:32 -0400 Date: Fri, 8 Jul 2016 06:16:31 -0700 From: tip-bot for Dmitry Safonov Message-ID: Cc: shuahkh@osg.samsung.com, hpa@zytor.com, dsafonov@virtuozzo.com, tglx@linutronix.de, mingo@kernel.org, torvalds@linux-foundation.org, dvlasenk@redhat.com, brgerst@gmail.com, bp@alien8.de, peterz@infradead.org, luto@kernel.org, jpoimboe@redhat.com, linux-kernel@vger.kernel.org Reply-To: dvlasenk@redhat.com, mingo@kernel.org, torvalds@linux-foundation.org, tglx@linutronix.de, shuahkh@osg.samsung.com, dsafonov@virtuozzo.com, hpa@zytor.com, linux-kernel@vger.kernel.org, bp@alien8.de, peterz@infradead.org, jpoimboe@redhat.com, luto@kernel.org, brgerst@gmail.com In-Reply-To: <20160628113539.13606-3-dsafonov@virtuozzo.com> References: <20160628113539.13606-3-dsafonov@virtuozzo.com> To: linux-tip-commits@vger.kernel.org Subject: [tip:x86/mm] selftests/x86: Add vDSO mremap() test Git-Commit-ID: f80fd3a5fff88a9ace7e8cd11d07cf874a63ea9f X-Mailer: tip-git-log-daemon Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset=UTF-8 Content-Disposition: inline Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Commit-ID: f80fd3a5fff88a9ace7e8cd11d07cf874a63ea9f Gitweb: http://git.kernel.org/tip/f80fd3a5fff88a9ace7e8cd11d07cf874a63ea9f Author: Dmitry Safonov AuthorDate: Tue, 28 Jun 2016 14:35:39 +0300 Committer: Ingo Molnar CommitDate: Fri, 8 Jul 2016 14:17:51 +0200 selftests/x86: Add vDSO mremap() test Should print this on vDSO remapping success (on new kernels): [root@localhost ~]# ./test_mremap_vdso_32 AT_SYSINFO_EHDR is 0xf773f000 [NOTE] Moving vDSO: [f773f000, f7740000] -> [a000000, a001000] [OK] Or print that mremap() for vDSOs is unsupported: [root@localhost ~]# ./test_mremap_vdso_32 AT_SYSINFO_EHDR is 0xf773c000 [NOTE] Moving vDSO: [0xf773c000, 0xf773d000] -> [0xf7737000, 0xf7738000] [FAIL] mremap() of the vDSO does not work on this kernel! Suggested-by: Andy Lutomirski Signed-off-by: Dmitry Safonov Acked-by: Andy Lutomirski Cc: 0x7f454c46@gmail.com Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Josh Poimboeuf Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Shuah Khan Cc: Thomas Gleixner Cc: linux-kselftest@vger.kernel.org Cc: linux-mm@kvack.org Link: http://lkml.kernel.org/r/20160628113539.13606-3-dsafonov@virtuozzo.com Signed-off-by: Ingo Molnar --- tools/testing/selftests/x86/Makefile | 2 +- tools/testing/selftests/x86/test_mremap_vdso.c | 111 +++++++++++++++++++++++++ 2 files changed, 112 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile index c73425d..543a6d0 100644 --- a/tools/testing/selftests/x86/Makefile +++ b/tools/testing/selftests/x86/Makefile @@ -4,7 +4,7 @@ include ../lib.mk .PHONY: all all_32 all_64 warn_32bit_failure clean -TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt ptrace_syscall \ +TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt ptrace_syscall test_mremap_vdso \ check_initial_reg_state sigreturn ldt_gdt iopl TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault test_syscall_vdso unwind_vdso \ test_FCMOV test_FCOMI test_FISTTP \ diff --git a/tools/testing/selftests/x86/test_mremap_vdso.c b/tools/testing/selftests/x86/test_mremap_vdso.c new file mode 100644 index 0000000..bf0d687 --- /dev/null +++ b/tools/testing/selftests/x86/test_mremap_vdso.c @@ -0,0 +1,111 @@ +/* + * 32-bit test to check vDSO mremap. + * + * Copyright (c) 2016 Dmitry Safonov + * Suggested-by: Andrew Lutomirski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ +/* + * Can be built statically: + * gcc -Os -Wall -static -m32 test_mremap_vdso.c + */ +#define _GNU_SOURCE +#include +#include +#include +#include + +#include +#include +#include +#include + +#define PAGE_SIZE 4096 + +static int try_to_remap(void *vdso_addr, unsigned long size) +{ + void *dest_addr, *new_addr; + + /* Searching for memory location where to remap */ + dest_addr = mmap(0, size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); + if (dest_addr == MAP_FAILED) { + printf("[WARN]\tmmap failed (%d): %m\n", errno); + return 0; + } + + printf("[NOTE]\tMoving vDSO: [%p, %#lx] -> [%p, %#lx]\n", + vdso_addr, (unsigned long)vdso_addr + size, + dest_addr, (unsigned long)dest_addr + size); + fflush(stdout); + + new_addr = mremap(vdso_addr, size, size, + MREMAP_FIXED|MREMAP_MAYMOVE, dest_addr); + if ((unsigned long)new_addr == (unsigned long)-1) { + munmap(dest_addr, size); + if (errno == EINVAL) { + printf("[NOTE]\tvDSO partial move failed, will try with bigger size\n"); + return -1; /* Retry with larger */ + } + printf("[FAIL]\tmremap failed (%d): %m\n", errno); + return 1; + } + + return 0; + +} + +int main(int argc, char **argv, char **envp) +{ + pid_t child; + + child = fork(); + if (child == -1) { + printf("[WARN]\tfailed to fork (%d): %m\n", errno); + return 1; + } + + if (child == 0) { + unsigned long vdso_size = PAGE_SIZE; + unsigned long auxval; + int ret = -1; + + auxval = getauxval(AT_SYSINFO_EHDR); + printf("\tAT_SYSINFO_EHDR is %#lx\n", auxval); + if (!auxval || auxval == -ENOENT) { + printf("[WARN]\tgetauxval failed\n"); + return 0; + } + + /* Simpler than parsing ELF header */ + while (ret < 0) { + ret = try_to_remap((void *)auxval, vdso_size); + vdso_size += PAGE_SIZE; + } + + /* Glibc is likely to explode now - exit with raw syscall */ + asm volatile ("int $0x80" : : "a" (__NR_exit), "b" (!!ret)); + } else { + int status; + + if (waitpid(child, &status, 0) != child || + !WIFEXITED(status)) { + printf("[FAIL]\tmremap() of the vDSO does not work on this kernel!\n"); + return 1; + } else if (WEXITSTATUS(status) != 0) { + printf("[FAIL]\tChild failed with %d\n", + WEXITSTATUS(status)); + return 1; + } + printf("[OK]\n"); + } + + return 0; +}