Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751817AbeAECCd (ORCPT + 1 other); Thu, 4 Jan 2018 21:02:33 -0500 Received: from smtp-fw-33001.amazon.com ([207.171.190.10]:26543 "EHLO smtp-fw-33001.amazon.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751660AbeAECB7 (ORCPT ); Thu, 4 Jan 2018 21:01:59 -0500 X-IronPort-AV: E=Sophos;i="5.46,316,1511827200"; d="scan'208";a="713532323" From: David Woodhouse To: Andi Kleen 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 Subject: [PATCH v4 10/13] retpoline/taint: Taint kernel for missing retpoline in compiler Date: Fri, 5 Jan 2018 02:01:06 +0000 Message-Id: <1515117669-24787-11-git-send-email-dwmw@amazon.co.uk> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1515117669-24787-1-git-send-email-dwmw@amazon.co.uk> References: <1515117669-24787-1-git-send-email-dwmw@amazon.co.uk> 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 1df03b5..800261b 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 8af2e8d..cc880b4 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 ce51455..fbb4d3b 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 dea01ac..92db3f5 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 2cfef40..6686c67 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 f51cf97..6510536 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.7.4