Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753391AbeADOiS (ORCPT + 1 other); Thu, 4 Jan 2018 09:38:18 -0500 Received: from merlin.infradead.org ([205.233.59.134]:46826 "EHLO merlin.infradead.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753252AbeADOh1 (ORCPT ); Thu, 4 Jan 2018 09:37:27 -0500 From: David Woodhouse To: ak@linux.intel.com Cc: Paul Turner , LKML , Linus Torvalds , Greg Kroah-Hartman , Tim Chen , Dave Hansen , tglx@linutronix.de, Kees Cook , Rik van Riel , Peter Zijlstra , Andy Lutomirski , Jiri Kosina , gnomes@lxorguk.ukuu.org.uk, David Woodhouse Subject: [PATCH v3 11/13] retpoline/taint: Taint kernel for missing retpoline in compiler Date: Thu, 4 Jan 2018 14:37:08 +0000 Message-Id: <20180104143710.8961-11-dwmw@amazon.co.uk> X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180104143710.8961-1-dwmw@amazon.co.uk> References: <20180104143710.8961-1-dwmw@amazon.co.uk> In-Reply-To: <1515058213.12987.89.camel@amazon.co.uk> References: <1515058213.12987.89.camel@amazon.co.uk> X-SRS-Rewrite: SMTP reverse-path rewritten from by merlin.infradead.org. See http://www.infradead.org/rpr.html Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Return-Path: From: Andi Kleen When the kernel or a module hasn't been compiled with a retpoline aware compiler, print a warning and set a taint flag. For modules it is checked at compile time, however it cannot check assembler or other non compiled objects used in the module link. Due to lack of better letter it uses taint option 'Z' v2: Change warning message Signed-off-by: Andi Kleen Signed-off-by: David Woodhouse --- Documentation/admin-guide/tainted-kernels.rst | 3 +++ arch/x86/kernel/setup.c | 6 ++++++ include/linux/kernel.h | 4 +++- kernel/module.c | 11 ++++++++++- kernel/panic.c | 1 + scripts/mod/modpost.c | 9 +++++++++ 6 files changed, 32 insertions(+), 2 deletions(-) diff --git a/Documentation/admin-guide/tainted-kernels.rst b/Documentation/admin-guide/tainted-kernels.rst index 1df03b5cb02f..800261b6bd6f 100644 --- a/Documentation/admin-guide/tainted-kernels.rst +++ b/Documentation/admin-guide/tainted-kernels.rst @@ -52,6 +52,9 @@ characters, each representing a particular tainted value. 16) ``K`` if the kernel has been live patched. + 17) ``Z`` if the x86 kernel or a module hasn't been compiled with + a retpoline aware compiler and may be vulnerable to data leaks. + The primary reason for the **'Tainted: '** string is to tell kernel debuggers if this is a clean kernel or if anything unusual has occurred. Tainting is permanent: even if an offending module is diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 8af2e8d0c0a1..cc880b46b756 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -1296,6 +1296,12 @@ void __init setup_arch(char **cmdline_p) #endif unwind_init(); + +#ifndef RETPOLINE + add_taint(TAINT_NO_RETPOLINE, LOCKDEP_STILL_OK); + pr_warn("No support for retpoline in kernel compiler\n"); + pr_warn("System may be vulnerable to data leaks.\n"); +#endif } #ifdef CONFIG_X86_32 diff --git a/include/linux/kernel.h b/include/linux/kernel.h index ce51455e2adf..fbb4d3baffcc 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -550,7 +550,9 @@ extern enum system_states { #define TAINT_SOFTLOCKUP 14 #define TAINT_LIVEPATCH 15 #define TAINT_AUX 16 -#define TAINT_FLAGS_COUNT 17 +#define TAINT_NO_RETPOLINE 17 + +#define TAINT_FLAGS_COUNT 18 struct taint_flag { char c_true; /* character printed when tainted */ diff --git a/kernel/module.c b/kernel/module.c index dea01ac9cb74..92db3f59a29a 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -3028,7 +3028,16 @@ static int check_modinfo(struct module *mod, struct load_info *info, int flags) mod->name); add_taint_module(mod, TAINT_OOT_MODULE, LOCKDEP_STILL_OK); } - +#ifdef RETPOLINE + if (!get_modinfo(info, "retpoline")) { + if (!test_taint(TAINT_NO_RETPOLINE)) { + pr_warn("%s: loading module not compiled with retpoline compiler.\n", + mod->name); + pr_warn("Kernel may be vulnerable to data leaks.\n"); + } + add_taint_module(mod, TAINT_NO_RETPOLINE, LOCKDEP_STILL_OK); + } +#endif if (get_modinfo(info, "staging")) { add_taint_module(mod, TAINT_CRAP, LOCKDEP_STILL_OK); pr_warn("%s: module is from the staging directory, the quality " diff --git a/kernel/panic.c b/kernel/panic.c index 2cfef408fec9..6686c67b6e4b 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -325,6 +325,7 @@ const struct taint_flag taint_flags[TAINT_FLAGS_COUNT] = { { 'L', ' ', false }, /* TAINT_SOFTLOCKUP */ { 'K', ' ', true }, /* TAINT_LIVEPATCH */ { 'X', ' ', true }, /* TAINT_AUX */ + { 'Z', ' ', true }, /* TAINT_NO_RETPOLINE */ }; /** diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index f51cf977c65b..6510536c06df 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -2165,6 +2165,14 @@ static void add_intree_flag(struct buffer *b, int is_intree) buf_printf(b, "\nMODULE_INFO(intree, \"Y\");\n"); } +/* Cannot check for assembler */ +static void add_retpoline(struct buffer *b) +{ + buf_printf(b, "\n#ifdef RETPOLINE\n"); + buf_printf(b, "MODULE_INFO(retpoline, \"Y\");\n"); + buf_printf(b, "#endif\n"); +} + static void add_staging_flag(struct buffer *b, const char *name) { static const char *staging_dir = "drivers/staging"; @@ -2506,6 +2514,7 @@ int main(int argc, char **argv) err |= check_modname_len(mod); add_header(&buf, mod); add_intree_flag(&buf, !external_module); + add_retpoline(&buf); add_staging_flag(&buf, mod->name); err |= add_versions(&buf, mod); add_depends(&buf, mod, modules); -- 2.14.3