From patchwork Thu Jun 27 04:45:02 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Lutomirski X-Patchwork-Id: 11018715 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 69ACF14C0 for ; Thu, 27 Jun 2019 04:45:32 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5931D287B7 for ; Thu, 27 Jun 2019 04:45:32 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4BA5E287A3; Thu, 27 Jun 2019 04:45:32 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.3 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from mother.openwall.net (mother.openwall.net [195.42.179.200]) by mail.wl.linuxfoundation.org (Postfix) with SMTP id A0ED2287A3 for ; Thu, 27 Jun 2019 04:45:30 +0000 (UTC) Received: (qmail 11472 invoked by uid 550); 27 Jun 2019 04:45:25 -0000 Mailing-List: contact kernel-hardening-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Delivered-To: mailing list kernel-hardening@lists.openwall.com Received: (qmail 11429 invoked from network); 27 Jun 2019 04:45:24 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1561610712; bh=K5SUY54SELZy1+lViKPOPr+FMJUSCP3gUFGFg03T6N8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=VcAQbH78K3Q74ErLQKjNUikUSjDpjyRSUPz1TDnnl5xy5zK1TDA53Pageqwq/mjf2 kxa3bPlibB3B5DpHEs3RDfxs+aBW8hjS7XigMTp4u7tA70CpVo7JlDBKFKkF+k83Qa 9bORDvXcvy5/k/6Bba+OFLfWx5/CVLA2NCDIX2W0= From: Andy Lutomirski To: x86@kernel.org Cc: LKML , Kees Cook , Florian Weimer , Jann Horn , Andy Lutomirski , stable@vger.kernel.org, Borislav Petkov , Kernel Hardening , Peter Zijlstra , Thomas Gleixner Subject: [PATCH v2 1/8] x86/vsyscall: Remove the vsyscall=native documentation Date: Wed, 26 Jun 2019 21:45:02 -0700 Message-Id: X-Mailer: git-send-email 2.21.0 In-Reply-To: References: MIME-Version: 1.0 X-Virus-Scanned: ClamAV using ClamSMTP The vsyscall=native feature is gone -- remove the docs. Fixes: 076ca272a14c ("x86/vsyscall/64: Drop "native" vsyscalls") Cc: stable@vger.kernel.org Cc: Kees Cook Cc: Borislav Petkov Cc: Kernel Hardening Cc: Peter Zijlstra Cc: Thomas Gleixner Signed-off-by: Andy Lutomirski Acked-by: Kees Cook --- Documentation/admin-guide/kernel-parameters.txt | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 138f6664b2e2..0082d1e56999 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -5102,12 +5102,6 @@ emulate [default] Vsyscalls turn into traps and are emulated reasonably safely. - native Vsyscalls are native syscall instructions. - This is a little bit faster than trapping - and makes a few dynamic recompilers work - better than they would in emulation mode. - It also makes exploits much easier to write. - none Vsyscalls don't work at all. This makes them quite hard to use for exploits but might break your system. From patchwork Thu Jun 27 04:45:03 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Lutomirski X-Patchwork-Id: 11018717 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id CAC8414C0 for ; Thu, 27 Jun 2019 04:45:40 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B9634287A3 for ; Thu, 27 Jun 2019 04:45:40 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A8F4C287E3; Thu, 27 Jun 2019 04:45:40 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.3 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from mother.openwall.net (mother.openwall.net [195.42.179.200]) by mail.wl.linuxfoundation.org (Postfix) with SMTP id 7C3B4287A3 for ; Thu, 27 Jun 2019 04:45:39 +0000 (UTC) Received: (qmail 11498 invoked by uid 550); 27 Jun 2019 04:45:26 -0000 Mailing-List: contact kernel-hardening-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Delivered-To: mailing list kernel-hardening@lists.openwall.com Received: (qmail 11430 invoked from network); 27 Jun 2019 04:45:24 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1561610713; bh=uUdOygK0rqjRhfS2izHQWMTu74AdMVwZ8TIO8xwkgsk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=XSmilcwVR8LAIS4yO8RxBZPN+ITJVKAugnAB2Am0VWeEd9UiYUbVKo+W9VOZhViXF Dm/IBu3ebpUzRUBREK48RoIzXMJWVDInJo/s1CxGkQXhRCRELQy5TyyWTxoRN6g/iv /IBh4/FxdpO2bi6FGohuotd2+9juNYIsIRONCSHI= From: Andy Lutomirski To: x86@kernel.org Cc: LKML , Kees Cook , Florian Weimer , Jann Horn , Andy Lutomirski , Borislav Petkov , Kernel Hardening , Peter Zijlstra , Thomas Gleixner Subject: [PATCH v2 2/8] x86/vsyscall: Add a new vsyscall=xonly mode Date: Wed, 26 Jun 2019 21:45:03 -0700 Message-Id: X-Mailer: git-send-email 2.21.0 In-Reply-To: References: MIME-Version: 1.0 X-Virus-Scanned: ClamAV using ClamSMTP With vsyscall emulation on, we still expose a readable vsyscall page that contains syscall instructions that validly implement the vsyscalls. We need this because certain dynamic binary instrumentation tools attempt to read the call targets of call instructions in the instrumented code. If the instrumented code uses vsyscalls, then the vsyscal page needs to contain readable code. Unfortunately, leaving readable memory at a deterministic address can be used to help various ASLR bypasses, so we gain some hardening value if we disallow vsyscall reads. Given how rarely the vsyscall page needs to be readable, add a mechanism to make the vsyscall page be execute only. Cc: Kees Cook Cc: Borislav Petkov Cc: Kernel Hardening Cc: Peter Zijlstra Cc: Thomas Gleixner Signed-off-by: Andy Lutomirski Reviewed-by: Kees Cook --- .../admin-guide/kernel-parameters.txt | 7 +++- arch/x86/Kconfig | 33 ++++++++++++++----- arch/x86/entry/vsyscall/vsyscall_64.c | 16 +++++++-- 3 files changed, 44 insertions(+), 12 deletions(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 0082d1e56999..be8c3a680afa 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -5100,7 +5100,12 @@ targets for exploits that can control RIP. emulate [default] Vsyscalls turn into traps and are - emulated reasonably safely. + emulated reasonably safely. The vsyscall + page is readable. + + xonly Vsyscalls turn into traps and are + emulated reasonably safely. The vsyscall + page is not readable. none Vsyscalls don't work at all. This makes them quite hard to use for exploits but diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 2bbbd4d1ba31..0182d2c67590 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -2293,23 +2293,38 @@ choice it can be used to assist security vulnerability exploitation. This setting can be changed at boot time via the kernel command - line parameter vsyscall=[emulate|none]. + line parameter vsyscall=[emulate|xonly|none]. On a system with recent enough glibc (2.14 or newer) and no static binaries, you can say None without a performance penalty to improve security. - If unsure, select "Emulate". + If unsure, select "Emulate execution only". config LEGACY_VSYSCALL_EMULATE - bool "Emulate" + bool "Full emulation" help - The kernel traps and emulates calls into the fixed - vsyscall address mapping. This makes the mapping - non-executable, but it still contains known contents, - which could be used in certain rare security vulnerability - exploits. This configuration is recommended when userspace - still uses the vsyscall area. + The kernel traps and emulates calls into the fixed vsyscall + address mapping. This makes the mapping non-executable, but + it still contains readable known contents, which could be + used in certain rare security vulnerability exploits. This + configuration is recommended when using legacy userspace + that still uses vsyscalls along with legacy binary + instrumentation tools that require code to be readable. + + An example of this type of legacy userspace is running + Pin on an old binary that still uses vsyscalls. + + config LEGACY_VSYSCALL_XONLY + bool "Emulate execution only" + help + The kernel traps and emulates calls into the fixed vsyscall + address mapping and does not allow reads. This + configuration is recommended when userspace might use the + legacy vsyscall area but support for legacy binary + instrumentation of legacy code is not needed. It mitigates + certain uses of the vsyscall area as an ASLR-bypassing + buffer. config LEGACY_VSYSCALL_NONE bool "None" diff --git a/arch/x86/entry/vsyscall/vsyscall_64.c b/arch/x86/entry/vsyscall/vsyscall_64.c index d9d81ad7a400..fedd7628f3a6 100644 --- a/arch/x86/entry/vsyscall/vsyscall_64.c +++ b/arch/x86/entry/vsyscall/vsyscall_64.c @@ -42,9 +42,11 @@ #define CREATE_TRACE_POINTS #include "vsyscall_trace.h" -static enum { EMULATE, NONE } vsyscall_mode = +static enum { EMULATE, XONLY, NONE } vsyscall_mode = #ifdef CONFIG_LEGACY_VSYSCALL_NONE NONE; +#elif defined(CONFIG_LEGACY_VSYSCALL_XONLY) + XONLY; #else EMULATE; #endif @@ -54,6 +56,8 @@ static int __init vsyscall_setup(char *str) if (str) { if (!strcmp("emulate", str)) vsyscall_mode = EMULATE; + else if (!strcmp("xonly", str)) + vsyscall_mode = XONLY; else if (!strcmp("none", str)) vsyscall_mode = NONE; else @@ -357,12 +361,20 @@ void __init map_vsyscall(void) extern char __vsyscall_page; unsigned long physaddr_vsyscall = __pa_symbol(&__vsyscall_page); - if (vsyscall_mode != NONE) { + /* + * For full emulation, the page needs to exist for real. In + * execute-only mode, there is no PTE at all backing the vsyscall + * page. + */ + if (vsyscall_mode == EMULATE) { __set_fixmap(VSYSCALL_PAGE, physaddr_vsyscall, PAGE_KERNEL_VVAR); set_vsyscall_pgtable_user_bits(swapper_pg_dir); } + if (vsyscall_mode == XONLY) + gate_vma.vm_flags = VM_EXEC; + BUILD_BUG_ON((unsigned long)__fix_to_virt(VSYSCALL_PAGE) != (unsigned long)VSYSCALL_ADDR); } From patchwork Thu Jun 27 04:45:05 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Lutomirski X-Patchwork-Id: 11018719 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8C40D1575 for ; Thu, 27 Jun 2019 04:45:48 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7B47F287A3 for ; Thu, 27 Jun 2019 04:45:48 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6F52A287E3; Thu, 27 Jun 2019 04:45:48 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.3 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from mother.openwall.net (mother.openwall.net [195.42.179.200]) by mail.wl.linuxfoundation.org (Postfix) with SMTP id 8D376287A3 for ; Thu, 27 Jun 2019 04:45:47 +0000 (UTC) Received: (qmail 11592 invoked by uid 550); 27 Jun 2019 04:45:28 -0000 Mailing-List: contact kernel-hardening-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Delivered-To: mailing list kernel-hardening@lists.openwall.com Received: (qmail 11503 invoked from network); 27 Jun 2019 04:45:26 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1561610714; bh=VopC/H2LVqjcArgoYlGlZvUD87RJOZBksD278wuXTlA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=c/SGCTX2m4pgv/Y3apFKe1QA4IlTkvXgkc30v0hs5sKOSjFHEgmL/nyBoMJyqTTHD lQp8yX4hm+EUnbKBCJ7O3bpTy6DV8rNAc/eTc9LTlxl3JjIex4DtsxDyJfy4ghj/dn qF/bQizyevBTmoGNtHwJMXqDMQzU8P8RILEIYFUc= From: Andy Lutomirski To: x86@kernel.org Cc: LKML , Kees Cook , Florian Weimer , Jann Horn , Andy Lutomirski , Borislav Petkov , Kernel Hardening , Peter Zijlstra , Thomas Gleixner Subject: [PATCH v2 4/8] x86/vsyscall: Document odd SIGSEGV error code for vsyscalls Date: Wed, 26 Jun 2019 21:45:05 -0700 Message-Id: <75c91855fd850649ace162eec5495a1354221aaa.1561610354.git.luto@kernel.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: References: MIME-Version: 1.0 X-Virus-Scanned: ClamAV using ClamSMTP Even if vsyscall=none, we report uer page faults on the vsyscall page as though the PROT bit in the error code was set. Add a comment explaining why this is probably okay and display the value in the test case. While we're at it, explain why our behavior is correct with respect to PKRU. This also modifies the selftest to print the odd error code so that you can run the selftest and see that the behavior is odd. If anyone really cares about more accurate emulation, we could change the behavior. Cc: Kees Cook Cc: Borislav Petkov Cc: Kernel Hardening Cc: Peter Zijlstra Cc: Thomas Gleixner Signed-off-by: Andy Lutomirski Reviewed-by: Kees Cook --- arch/x86/mm/fault.c | 7 +++++++ tools/testing/selftests/x86/test_vsyscall.c | 9 ++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 288a5462076f..58e4f1f00bbc 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -710,6 +710,10 @@ static void set_signal_archinfo(unsigned long address, * To avoid leaking information about the kernel page * table layout, pretend that user-mode accesses to * kernel addresses are always protection faults. + * + * NB: This means that failed vsyscalls with vsyscall=none + * will have the PROT bit. This doesn't leak any + * information and does not appear to cause any problems. */ if (address >= TASK_SIZE_MAX) error_code |= X86_PF_PROT; @@ -1375,6 +1379,9 @@ void do_user_addr_fault(struct pt_regs *regs, * * The vsyscall page does not have a "real" VMA, so do this * emulation before we go searching for VMAs. + * + * PKRU never rejects instruction fetches, so we don't need + * to consider the PF_PK bit. */ if (is_vsyscall_vaddr(address)) { if (emulate_vsyscall(hw_error_code, regs, address)) diff --git a/tools/testing/selftests/x86/test_vsyscall.c b/tools/testing/selftests/x86/test_vsyscall.c index 0b4f1cc2291c..4c9a8d76dba0 100644 --- a/tools/testing/selftests/x86/test_vsyscall.c +++ b/tools/testing/selftests/x86/test_vsyscall.c @@ -183,9 +183,13 @@ static inline long sys_getcpu(unsigned * cpu, unsigned * node, } static jmp_buf jmpbuf; +static volatile unsigned long segv_err; static void sigsegv(int sig, siginfo_t *info, void *ctx_void) { + ucontext_t *ctx = (ucontext_t *)ctx_void; + + segv_err = ctx->uc_mcontext.gregs[REG_ERR]; siglongjmp(jmpbuf, 1); } @@ -416,8 +420,11 @@ static int test_vsys_r(void) } else if (!can_read && should_read_vsyscall) { printf("[FAIL]\tWe don't have read access, but we should\n"); return 1; + } else if (can_read) { + printf("[OK]\tWe have read access\n"); } else { - printf("[OK]\tgot expected result\n"); + printf("[OK]\tWe do not have read access: #PF(0x%lx)\n", + segv_err); } #endif From patchwork Thu Jun 27 04:45:06 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Lutomirski X-Patchwork-Id: 11018721 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 63D9314C0 for ; Thu, 27 Jun 2019 04:45:57 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5364B287A3 for ; Thu, 27 Jun 2019 04:45:57 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 46F62287E3; Thu, 27 Jun 2019 04:45:57 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.3 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from mother.openwall.net (mother.openwall.net [195.42.179.200]) by mail.wl.linuxfoundation.org (Postfix) with SMTP id 1ECA5287A3 for ; Thu, 27 Jun 2019 04:45:55 +0000 (UTC) Received: (qmail 11598 invoked by uid 550); 27 Jun 2019 04:45:28 -0000 Mailing-List: contact kernel-hardening-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Delivered-To: mailing list kernel-hardening@lists.openwall.com Received: (qmail 11530 invoked from network); 27 Jun 2019 04:45:26 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1561610715; bh=Gc0XYDh9VdKQArOdtCH+oMY6poNwXHQC/rBzPi9XHqw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=N6a64TQ59feOIvylVr9sPUS67s4qSRseGzQ/sY+cEsZxvrZzfWbeUuzD577bkr3XX h7ibBugOm+oHmrS0Z32G9lA5eXefgWLpovont/9fXq7GFqJzN4l2hmORhtmg1QcZGZ g7JErp2BRraz4SqhdzxUk9VPWGcaI9MMsmugSp18= From: Andy Lutomirski To: x86@kernel.org Cc: LKML , Kees Cook , Florian Weimer , Jann Horn , Andy Lutomirski , Borislav Petkov , Kernel Hardening , Peter Zijlstra , Thomas Gleixner Subject: [PATCH v2 5/8] selftests/x86/vsyscall: Verify that vsyscall=none blocks execution Date: Wed, 26 Jun 2019 21:45:06 -0700 Message-Id: X-Mailer: git-send-email 2.21.0 In-Reply-To: References: MIME-Version: 1.0 X-Virus-Scanned: ClamAV using ClamSMTP If vsyscall=none accidentally still allowed vsyscalls, the test wouldn't fail. Fix it. Cc: Kees Cook Cc: Borislav Petkov Cc: Kernel Hardening Cc: Peter Zijlstra Cc: Thomas Gleixner Signed-off-by: Andy Lutomirski Reviewed-by: Kees Cook --- tools/testing/selftests/x86/test_vsyscall.c | 76 ++++++++++++++------- 1 file changed, 52 insertions(+), 24 deletions(-) diff --git a/tools/testing/selftests/x86/test_vsyscall.c b/tools/testing/selftests/x86/test_vsyscall.c index 4c9a8d76dba0..34a1d35995ef 100644 --- a/tools/testing/selftests/x86/test_vsyscall.c +++ b/tools/testing/selftests/x86/test_vsyscall.c @@ -49,21 +49,21 @@ static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *), } /* vsyscalls and vDSO */ -bool should_read_vsyscall = false; +bool vsyscall_map_r = false, vsyscall_map_x = false; typedef long (*gtod_t)(struct timeval *tv, struct timezone *tz); -gtod_t vgtod = (gtod_t)VSYS(0xffffffffff600000); +const gtod_t vgtod = (gtod_t)VSYS(0xffffffffff600000); gtod_t vdso_gtod; typedef int (*vgettime_t)(clockid_t, struct timespec *); vgettime_t vdso_gettime; typedef long (*time_func_t)(time_t *t); -time_func_t vtime = (time_func_t)VSYS(0xffffffffff600400); +const time_func_t vtime = (time_func_t)VSYS(0xffffffffff600400); time_func_t vdso_time; typedef long (*getcpu_t)(unsigned *, unsigned *, void *); -getcpu_t vgetcpu = (getcpu_t)VSYS(0xffffffffff600800); +const getcpu_t vgetcpu = (getcpu_t)VSYS(0xffffffffff600800); getcpu_t vdso_getcpu; static void init_vdso(void) @@ -107,7 +107,7 @@ static int init_vsys(void) maps = fopen("/proc/self/maps", "r"); if (!maps) { printf("[WARN]\tCould not open /proc/self/maps -- assuming vsyscall is r-x\n"); - should_read_vsyscall = true; + vsyscall_map_r = true; return 0; } @@ -133,12 +133,8 @@ static int init_vsys(void) } printf("\tvsyscall permissions are %c-%c\n", r, x); - should_read_vsyscall = (r == 'r'); - if (x != 'x') { - vgtod = NULL; - vtime = NULL; - vgetcpu = NULL; - } + vsyscall_map_r = (r == 'r'); + vsyscall_map_x = (x == 'x'); found = true; break; @@ -148,10 +144,8 @@ static int init_vsys(void) if (!found) { printf("\tno vsyscall map in /proc/self/maps\n"); - should_read_vsyscall = false; - vgtod = NULL; - vtime = NULL; - vgetcpu = NULL; + vsyscall_map_r = false; + vsyscall_map_x = false; } return nerrs; @@ -242,7 +236,7 @@ static int test_gtod(void) err(1, "syscall gettimeofday"); if (vdso_gtod) ret_vdso = vdso_gtod(&tv_vdso, &tz_vdso); - if (vgtod) + if (vsyscall_map_x) ret_vsys = vgtod(&tv_vsys, &tz_vsys); if (sys_gtod(&tv_sys2, &tz_sys) != 0) err(1, "syscall gettimeofday"); @@ -256,7 +250,7 @@ static int test_gtod(void) } } - if (vgtod) { + if (vsyscall_map_x) { if (ret_vsys == 0) { nerrs += check_gtod(&tv_sys1, &tv_sys2, &tz_sys, "vsyscall", &tv_vsys, &tz_vsys); } else { @@ -277,7 +271,7 @@ static int test_time(void) { t_sys1 = sys_time(&t2_sys1); if (vdso_time) t_vdso = vdso_time(&t2_vdso); - if (vtime) + if (vsyscall_map_x) t_vsys = vtime(&t2_vsys); t_sys2 = sys_time(&t2_sys2); if (t_sys1 < 0 || t_sys1 != t2_sys1 || t_sys2 < 0 || t_sys2 != t2_sys2) { @@ -298,7 +292,7 @@ static int test_time(void) { } } - if (vtime) { + if (vsyscall_map_x) { if (t_vsys < 0 || t_vsys != t2_vsys) { printf("[FAIL]\tvsyscall failed (ret:%ld output:%ld)\n", t_vsys, t2_vsys); nerrs++; @@ -334,7 +328,7 @@ static int test_getcpu(int cpu) ret_sys = sys_getcpu(&cpu_sys, &node_sys, 0); if (vdso_getcpu) ret_vdso = vdso_getcpu(&cpu_vdso, &node_vdso, 0); - if (vgetcpu) + if (vsyscall_map_x) ret_vsys = vgetcpu(&cpu_vsys, &node_vsys, 0); if (ret_sys == 0) { @@ -373,7 +367,7 @@ static int test_getcpu(int cpu) } } - if (vgetcpu) { + if (vsyscall_map_x) { if (ret_vsys) { printf("[FAIL]\tvsyscall getcpu() failed\n"); nerrs++; @@ -414,10 +408,10 @@ static int test_vsys_r(void) can_read = false; } - if (can_read && !should_read_vsyscall) { + if (can_read && !vsyscall_map_r) { printf("[FAIL]\tWe have read access, but we shouldn't\n"); return 1; - } else if (!can_read && should_read_vsyscall) { + } else if (!can_read && vsyscall_map_r) { printf("[FAIL]\tWe don't have read access, but we should\n"); return 1; } else if (can_read) { @@ -431,6 +425,39 @@ static int test_vsys_r(void) return 0; } +static int test_vsys_x(void) +{ +#ifdef __x86_64__ + if (vsyscall_map_x) { + /* We already tested this adequately. */ + return 0; + } + + printf("[RUN]\tMake sure that vsyscalls really page fault\n"); + + bool can_exec; + if (sigsetjmp(jmpbuf, 1) == 0) { + vgtod(NULL, NULL); + can_exec = true; + } else { + can_exec = false; + } + + if (can_exec) { + printf("[FAIL]\tExecuting the vsyscall did not page fault\n"); + return 1; + } else if (segv_err & (1 << 4)) { /* INSTR */ + printf("[OK]\tExecuting the vsyscall page failed: #PF(0x%lx)\n", + segv_err); + } else { + printf("[FAILT]\tExecution failed with the wrong error: #PF(0x%lx)\n", + segv_err); + return 1; + } +#endif + + return 0; +} #ifdef __x86_64__ #define X86_EFLAGS_TF (1UL << 8) @@ -462,7 +489,7 @@ static int test_emulation(void) time_t tmp; bool is_native; - if (!vtime) + if (!vsyscall_map_x) return 0; printf("[RUN]\tchecking that vsyscalls are emulated\n"); @@ -504,6 +531,7 @@ int main(int argc, char **argv) sethandler(SIGSEGV, sigsegv, 0); nerrs += test_vsys_r(); + nerrs += test_vsys_x(); #ifdef __x86_64__ nerrs += test_emulation(); From patchwork Thu Jun 27 04:45:07 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Lutomirski X-Patchwork-Id: 11018723 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 9D49714C0 for ; Thu, 27 Jun 2019 04:46:06 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8DD77289FB for ; Thu, 27 Jun 2019 04:46:06 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7FC2028A19; Thu, 27 Jun 2019 04:46:06 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.3 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from mother.openwall.net (mother.openwall.net [195.42.179.200]) by mail.wl.linuxfoundation.org (Postfix) with SMTP id AB225289FB for ; Thu, 27 Jun 2019 04:46:05 +0000 (UTC) Received: (qmail 11652 invoked by uid 550); 27 Jun 2019 04:45:29 -0000 Mailing-List: contact kernel-hardening-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Delivered-To: mailing list kernel-hardening@lists.openwall.com Received: (qmail 11547 invoked from network); 27 Jun 2019 04:45:27 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1561610716; bh=p0mSFH+GsDKccYokNQY9U5gFq0x5WNQ6S5PD+LrfzU0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=uTh283EjoVkYy8NYAmHw6r4YbdNzOsWbgk48fBEV6zvVhTbiIdzHO+cnht4qUMwtD zk40Sv7qMUg18O4CIkzLoc1SPy570E0YH+DLSt55jrWGUF0kG2pR9AABVMR6EAHz/Q EVlF5gCHp6nSkDa08EkHw7r8W3hop8vqnwjaCus4= From: Andy Lutomirski To: x86@kernel.org Cc: LKML , Kees Cook , Florian Weimer , Jann Horn , Andy Lutomirski , Borislav Petkov , Kernel Hardening , Peter Zijlstra , Thomas Gleixner Subject: [PATCH v2 6/8] x86/vsyscall: Change the default vsyscall mode to xonly Date: Wed, 26 Jun 2019 21:45:07 -0700 Message-Id: <30539f8072d2376b9c9efcc07e6ed0d6bf20e882.1561610354.git.luto@kernel.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: References: MIME-Version: 1.0 X-Virus-Scanned: ClamAV using ClamSMTP The use case for full emulation over xonly is very esoteric. Let's change the default to the safer xonly mode. Cc: Kees Cook Cc: Borislav Petkov Cc: Kernel Hardening Cc: Peter Zijlstra Cc: Thomas Gleixner Signed-off-by: Andy Lutomirski Reviewed-by: Kees Cook --- arch/x86/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 0182d2c67590..32028edc1b0e 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -2285,7 +2285,7 @@ config COMPAT_VDSO choice prompt "vsyscall table for legacy applications" depends on X86_64 - default LEGACY_VSYSCALL_EMULATE + default LEGACY_VSYSCALL_XONLY help Legacy user code that does not know how to find the vDSO expects to be able to issue three syscalls by calling fixed addresses in From patchwork Thu Jun 27 04:45:08 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Lutomirski X-Patchwork-Id: 11018727 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 4F4CB1575 for ; Thu, 27 Jun 2019 04:46:26 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3D7AB289FB for ; Thu, 27 Jun 2019 04:46:26 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2F92B28A19; Thu, 27 Jun 2019 04:46:26 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.3 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from mother.openwall.net (mother.openwall.net [195.42.179.200]) by mail.wl.linuxfoundation.org (Postfix) with SMTP id 45FA1289FB for ; Thu, 27 Jun 2019 04:46:25 +0000 (UTC) Received: (qmail 13564 invoked by uid 550); 27 Jun 2019 04:45:39 -0000 Mailing-List: contact kernel-hardening-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Delivered-To: mailing list kernel-hardening@lists.openwall.com Received: (qmail 13381 invoked from network); 27 Jun 2019 04:45:37 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1561610716; bh=It8qNuorDHkN++30w/QRv2Qr7Cixz/gz1T4PqMIF4Kg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=q/S1g6tA36w5ZCGiw3DETjmxkhfWf0/8H4PK/ziyQkxVJCNMsRDQT/INUuLD/N/j/ vsRGwWDvAJ+aHq51RKzHWxsT6vVnXdZN9qZqIwHHw4E9mLLZa/tYI1tfURMEeUQ+P9 4OnNX7VYmYUw6ad95mECRjcB0g4vGLkbOjg+122c= From: Andy Lutomirski To: x86@kernel.org Cc: LKML , Kees Cook , Florian Weimer , Jann Horn , Andy Lutomirski , Borislav Petkov , Kernel Hardening , Peter Zijlstra , Thomas Gleixner Subject: [PATCH v2 7/8] x86/vsyscall: Add __ro_after_init to global variables Date: Wed, 26 Jun 2019 21:45:08 -0700 Message-Id: X-Mailer: git-send-email 2.21.0 In-Reply-To: References: MIME-Version: 1.0 X-Virus-Scanned: ClamAV using ClamSMTP The vDSO is only configurable by command-line options, so make its global variables __ro_after_init. This seems highly unlikely to ever stop an exploit, but I think it's nice anyway. Cc: Kees Cook Cc: Borislav Petkov Cc: Kernel Hardening Cc: Peter Zijlstra Cc: Thomas Gleixner Signed-off-by: Andy Lutomirski Reviewed-by: Kees Cook --- arch/x86/entry/vsyscall/vsyscall_64.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/entry/vsyscall/vsyscall_64.c b/arch/x86/entry/vsyscall/vsyscall_64.c index 9c58ab807aeb..07003f3f1bfc 100644 --- a/arch/x86/entry/vsyscall/vsyscall_64.c +++ b/arch/x86/entry/vsyscall/vsyscall_64.c @@ -42,7 +42,7 @@ #define CREATE_TRACE_POINTS #include "vsyscall_trace.h" -static enum { EMULATE, XONLY, NONE } vsyscall_mode = +static enum { EMULATE, XONLY, NONE } vsyscall_mode __ro_after_init = #ifdef CONFIG_LEGACY_VSYSCALL_NONE NONE; #elif defined(CONFIG_LEGACY_VSYSCALL_XONLY) @@ -305,7 +305,7 @@ static const char *gate_vma_name(struct vm_area_struct *vma) static const struct vm_operations_struct gate_vma_ops = { .name = gate_vma_name, }; -static struct vm_area_struct gate_vma = { +static struct vm_area_struct gate_vma __ro_after_init = { .vm_start = VSYSCALL_ADDR, .vm_end = VSYSCALL_ADDR + PAGE_SIZE, .vm_page_prot = PAGE_READONLY_EXEC, From patchwork Thu Jun 27 04:45:09 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Lutomirski X-Patchwork-Id: 11018725 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1F4A014C0 for ; Thu, 27 Jun 2019 04:46:16 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 11F2D289FB for ; Thu, 27 Jun 2019 04:46:16 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0644028A19; Thu, 27 Jun 2019 04:46:16 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.3 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from mother.openwall.net (mother.openwall.net [195.42.179.200]) by mail.wl.linuxfoundation.org (Postfix) with SMTP id 2F7F0289FB for ; Thu, 27 Jun 2019 04:46:15 +0000 (UTC) Received: (qmail 13498 invoked by uid 550); 27 Jun 2019 04:45:38 -0000 Mailing-List: contact kernel-hardening-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Delivered-To: mailing list kernel-hardening@lists.openwall.com Received: (qmail 13382 invoked from network); 27 Jun 2019 04:45:37 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1561610717; bh=GFanELS7mYpj+8Mm6kvXhJm6aJW1EglXpZSE4hvViJk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=yZUSulOZsbuP4mqVaY60lF4c5yu38hoUrhOvGCYAxsxU3t9mLiMCbCSNhN8O/F7za mrCzK9QUwpDh7LqegVtHNMZVACGfbezvwdZMKnJD7whUzSiWYBnL40UgG6sBmsiJcr ykTCw43v2QK5nnkizseAQuCFwKuf5NKJ9mb4Ffk4= From: Andy Lutomirski To: x86@kernel.org Cc: LKML , Kees Cook , Florian Weimer , Jann Horn , Andy Lutomirski , Borislav Petkov , Kernel Hardening , Peter Zijlstra , Thomas Gleixner Subject: [PATCH v2 8/8] selftests/x86: Add a test for process_vm_readv() on the vsyscall page Date: Wed, 26 Jun 2019 21:45:09 -0700 Message-Id: <0fe34229a9330e8f9de9765967939cc4f1cf26b1.1561610354.git.luto@kernel.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: References: MIME-Version: 1.0 X-Virus-Scanned: ClamAV using ClamSMTP get_gate_page() is a piece of somewhat alarming code to make get_user_pages() work on the vsyscall page. Test it via process_vm_readv(). Cc: Kees Cook Cc: Borislav Petkov Cc: Kernel Hardening Cc: Peter Zijlstra Cc: Thomas Gleixner Signed-off-by: Andy Lutomirski Reviewed-by: Kees Cook --- tools/testing/selftests/x86/test_vsyscall.c | 35 +++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/tools/testing/selftests/x86/test_vsyscall.c b/tools/testing/selftests/x86/test_vsyscall.c index 34a1d35995ef..4602326b8f5b 100644 --- a/tools/testing/selftests/x86/test_vsyscall.c +++ b/tools/testing/selftests/x86/test_vsyscall.c @@ -18,6 +18,7 @@ #include #include #include +#include #ifdef __x86_64__ # define VSYS(x) (x) @@ -459,6 +460,38 @@ static int test_vsys_x(void) return 0; } +static int test_process_vm_readv(void) +{ +#ifdef __x86_64__ + char buf[4096]; + struct iovec local, remote; + int ret; + + printf("[RUN]\tprocess_vm_readv() from vsyscall page\n"); + + local.iov_base = buf; + local.iov_len = 4096; + remote.iov_base = (void *)0xffffffffff600000; + remote.iov_len = 4096; + ret = process_vm_readv(getpid(), &local, 1, &remote, 1, 0); + if (ret != 4096) { + printf("[OK]\tprocess_vm_readv() failed (ret = %d, errno = %d)\n", ret, errno); + return 0; + } + + if (vsyscall_map_r) { + if (!memcmp(buf, (const void *)0xffffffffff600000, 4096)) { + printf("[OK]\tIt worked and read correct data\n"); + } else { + printf("[FAIL]\tIt worked but returned incorrect data\n"); + return 1; + } + } +#endif + + return 0; +} + #ifdef __x86_64__ #define X86_EFLAGS_TF (1UL << 8) static volatile sig_atomic_t num_vsyscall_traps; @@ -533,6 +566,8 @@ int main(int argc, char **argv) nerrs += test_vsys_r(); nerrs += test_vsys_x(); + nerrs += test_process_vm_readv(); + #ifdef __x86_64__ nerrs += test_emulation(); #endif