From patchwork Mon Jul 24 13:38:23 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans Liljestrand X-Patchwork-Id: 9860089 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 47357601A1 for ; Mon, 24 Jul 2017 18:57:23 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 39D46284B2 for ; Mon, 24 Jul 2017 18:57:23 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2EAC62852B; Mon, 24 Jul 2017 18:57:23 +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=-4.1 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_MED, T_DKIM_INVALID 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 C94F5284B2 for ; Mon, 24 Jul 2017 18:57:21 +0000 (UTC) Received: (qmail 17439 invoked by uid 550); 24 Jul 2017 18:57:09 -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 Delivered-To: moderator for kernel-hardening@lists.openwall.com Received: (qmail 28647 invoked from network); 24 Jul 2017 13:39:45 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=xkyL+9TJWHufLrCuw+nCYJVJM9tXyyXkUC2WD+9Lc/4=; b=LPhNTIBOaDs4cjradtyxxJG8y7xOAnMMTJNEN36Cwg9PtO2vzOjFWuK1KQBc4ERP0L grMAckQZHN0tvAmUUUEOGz67udSf1TfmmxIcVx/Q4MiFhRp02Yg8cnGHcDr+gIVXwRwT jzeHfGx2yww+f9pGo3eIUEqWmzfjZ2PVyNGOVcYC0KEmbfb0JNmLJu53jFW4uuy/ZEmc yzTBsVotoEWgSsxHWDRkOCj+VYvd/oVRJ6Z25YbcXZ+0YMeJY/69JyCKV3NMbEHL6m9T PLDdb4G4n+dFsIrjJJGWSKBHYXUdY5BHl/sreuh3w6i/1pNMHLIP7Vw6pP+4lqBept1t BHWg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=xkyL+9TJWHufLrCuw+nCYJVJM9tXyyXkUC2WD+9Lc/4=; b=NjtN96xFWsPlobMkmchIgySuGcun5+YpzwVanWOEnPodmXKKv0JOvLKwwh/3smNJmb fMuWS/H9DREEGKOtjK70ALrbdPB8xRN8T+QnZ13OW/93eCd6cjE97HzXhyUM91brlgT0 e+eEcliPw4G2ZzfQNsQSOi9xzlJ2ZfOfLUzIx/iqOm44e0l41nIOaXJ/cXT3w4kiUG4h 1N4Mjz9G6axKndA3+jfomthBjP9AbutopaxCuhm/Lv4sSeLVR4m+mpwlFkxfPI9+9awp evAkmG1sTJH+ptft2VLfC+leYV51SbsoCJkbrctW6jppSmxxebEFUat49oBUQZUAv2Rv O1Yg== X-Gm-Message-State: AIVw110fvOLImHuhR2lClDz4yIA9rt9CnyoI3jClCl3xUZPsQKy4XDbh /0+YvskHscoJJud/ecsyCA== X-Received: by 10.25.219.7 with SMTP id s7mr5355471lfg.242.1500903573602; Mon, 24 Jul 2017 06:39:33 -0700 (PDT) Sender: Hans Liljestrand From: Hans Liljestrand X-Google-Original-From: Hans Liljestrand To: kernel-hardening@lists.openwall.com Cc: elena.reshetova@intel.com, dave.hansen@intel.com, keescook@chromium.org, hpa@zytor.com, Hans Liljestrand Date: Mon, 24 Jul 2017 16:38:23 +0300 Message-Id: <20170724133824.27223-5-LiljestrandH@gmail.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170724133824.27223-1-LiljestrandH@gmail.com> References: <20170724133824.27223-1-LiljestrandH@gmail.com> Subject: [kernel-hardening] [RFC PATCH 4/5] x86: MPXK base X-Virus-Scanned: ClamAV using ClamSMTP Enable and add needed support functionality for ring 0 MPX. MPXK is enabled in init/main.c by setting the BNDCFGS MSR registers. This also includes the mpxk_load_bounds implementation and error handling code for MPX errors, i.e. bound violations. Signed-off-by: Hans Liljestrand Signed-off-by: Elena Reshetova --- arch/x86/include/asm/mpxk.h | 18 ++++++++++++ arch/x86/kernel/traps.c | 44 ++++++++++++++++++++++++++++- arch/x86/lib/Makefile | 5 ++++ arch/x86/lib/mpxk.c | 69 +++++++++++++++++++++++++++++++++++++++++++++ include/asm-generic/mpxk.h | 20 +++++++++++++ init/main.c | 2 ++ 6 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 arch/x86/include/asm/mpxk.h create mode 100644 arch/x86/lib/mpxk.c create mode 100644 include/asm-generic/mpxk.h diff --git a/arch/x86/include/asm/mpxk.h b/arch/x86/include/asm/mpxk.h new file mode 100644 index 000000000000..b5cb684e24c6 --- /dev/null +++ b/arch/x86/include/asm/mpxk.h @@ -0,0 +1,18 @@ +/* + * arch/x86/include/asm/mpxk.h + * + * Copyright (C) 2017 Aalto University + */ +#ifndef _X86_INCLUDE_ASM_MPXK_H_ +#define _X86_INCLUDE_ASM_MPXK_H_ + +#ifndef CONFIG_X86_INTEL_MPX_KERNEL +/* Use the generic header that provides empty definitions */ +#include +#else /*CONFIG_X86_INTEL_MPX_KERNEL */ + +extern void mpxk_enable_mpx(void); +extern void mpxk_print_bounds(const char *str, const void *ptr); + +#endif /*CONFIG_X86_INTEL_MPX_KERNEL */ +#endif /* _X86_INCLUDE_ASM_MPXK_H_ */ diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index bf54309b85da..8291f57d4727 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -440,6 +440,48 @@ dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code) } #endif +inline bool do_bounds_kernel(struct pt_regs *regs, long error_code) +{ +#ifndef CONFIG_X86_INTEL_MPX_KERNEL + die("bounds", regs, error_code); +#else + const struct mpx_bndcsr *bndcsr; + const char *err = NULL; + + if (!cpu_feature_enabled(X86_FEATURE_MPX)) { + err = "cpu_feature_enabled(X86_FEATURE_MPX)"; + } else { + bndcsr = get_xsave_field_ptr(XFEATURE_MASK_BNDCSR); + if (!bndcsr) { + err = "get_xsave_field_ptr failed"; + } else { + trace_bounds_exception_mpx(bndcsr); + + switch (bndcsr->bndstatus & MPX_BNDSTA_ERROR_CODE) { + case 2: /* Bound directory has invalid entry. */ + err = "invalid bound directory entry"; + break; + case 1: /* Bound violation. */ + err = "bounds violation!!!!"; + break; + case 0: /* No exception caused by Intel MPX. */ + err = "no Intel MPX exception found!?!"; + break; + default: + err = "unrecognized bounds(?) error"; + break; + } + } + } + + if (err != NULL) { + pr_err("mpxk: %s\n", err); + BUG(); + } + return true; +#endif /* CONFIG_X86_INTEL_MPX_KERNEL */ +} + dotraplinkage void do_bounds(struct pt_regs *regs, long error_code) { const struct mpx_bndcsr *bndcsr; @@ -452,7 +494,7 @@ dotraplinkage void do_bounds(struct pt_regs *regs, long error_code) cond_local_irq_enable(regs); if (!user_mode(regs)) - die("bounds", regs, error_code); + do_bounds_kernel(regs, error_code); if (!cpu_feature_enabled(X86_FEATURE_MPX)) { /* The exception is not from Intel MPX */ diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index 34a74131a12c..7024c4848181 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -46,3 +46,8 @@ else lib-y += copy_user_64.o lib-y += cmpxchg16b_emu.o endif + +lib-$(CONFIG_X86_INTEL_MPX_KERNEL) += mpxk.o +lib-$(CONFIG_X86_INTEL_MPX_KERNEL) += mpxk-wrappers.o +CFLAGS_mpxk.o += $(MPXK_LIB_CFLAGS) +CFLAGS_mpxk-wrappers.o += $(MPXK_LIB_CFLAGS) diff --git a/arch/x86/lib/mpxk.c b/arch/x86/lib/mpxk.c new file mode 100644 index 000000000000..69a7dae3f200 --- /dev/null +++ b/arch/x86/lib/mpxk.c @@ -0,0 +1,69 @@ +/* + * arch/x86/lib/mpxk.c + * + * Copyright (C) 2017 Aalto University + */ +#include +#include +#include +#include +#include + +#include +#include + +static struct msr bnd_cfg_s; + +__attribute__((bnd_legacy)) +static void mpxk_enable_mpx_cfgs_cpu(void *info) +{ + (void) info; + wrmsrl(MSR_IA32_BNDCFGS, bnd_cfg_s.q); +} + +__attribute__((bnd_legacy)) +void mpxk_enable_mpx(void) +{ + void *ptr = get_vm_area(MPX_BD_SIZE_BYTES_64 + PAGE_SIZE, VM_MAP); + + bnd_cfg_s.q = PAGE_ALIGN((unsigned long) ptr); + bnd_cfg_s.q |= MPX_BNDCFG_ENABLE_FLAG; + + pr_info("mpxk: Setting up Intel MPX for kernel\n"); + + /* Config is passed via the global bnd_cfg_s.q */ + on_each_cpu(mpxk_enable_mpx_cfgs_cpu, NULL, 1); +} + +void mpxk_print_bounds(const char *str, const void *ptr) +{ + const unsigned long range = (((unsigned long)__bnd_get_ptr_ubound(ptr)) + - ((unsigned long)__bnd_get_ptr_lbound(ptr))); + + pr_info("%s: pointer %pK (bounds %pK + %ld\n", + str, ptr, __bnd_get_ptr_lbound(ptr), range); +} + +void *mpxk_load_bounds(void *ptr) +{ + size_t size; + + do { + if (ptr == NULL) + break; + + if (!virt_addr_valid(ptr)) + break; + + if (!PageSlab(virt_to_page(ptr))) + break; + + size = ksize(ptr); + + if (size == 0) + return __bnd_null_ptr_bounds(ptr); + return __bnd_set_ptr_bounds(ptr, size); + } while (0); + + return __bnd_init_ptr_bounds(ptr); +} diff --git a/include/asm-generic/mpxk.h b/include/asm-generic/mpxk.h new file mode 100644 index 000000000000..0d3af7e12901 --- /dev/null +++ b/include/asm-generic/mpxk.h @@ -0,0 +1,20 @@ +/* + * include/asm-generic/mpxk.h + * + * Copyright (C) 2017 Aalto University + */ +#ifndef _ASM_MPXK_H_ +#define _ASM_MPXK_H_ + +#include +#include + +static inline void mpxk_enable_mpx(void) +{} + +static inline void mpxk_print_bounds(const char *str, const void *ptr) +{ + pr_info("%s: MPXK disabled, no bounds for pointer %pK\n", str, ptr); +} + +#endif /* _ASM_MPXK_H_ */ diff --git a/init/main.c b/init/main.c index f866510472d7..eea12c81e7a9 100644 --- a/init/main.c +++ b/init/main.c @@ -94,6 +94,7 @@ #include #include #include +#include static int kernel_init(void *); @@ -883,6 +884,7 @@ static void __init do_basic_setup(void) driver_init(); init_irq_proc(); do_ctors(); + mpxk_enable_mpx(); usermodehelper_enable(); do_initcalls(); }