|
|
Message-ID: <CAGXu5j+Zz0F_Co+2LtFp6fGc5NnJF=j6NPr-xuFpqQ71eiad-w@mail.gmail.com>
Date: Mon, 7 Aug 2017 10:45:56 -0700
From: Kees Cook <keescook@...omium.org>
To: Ard Biesheuvel <ard.biesheuvel@...aro.org>
Cc: "kernel-hardening@...ts.openwall.com" <kernel-hardening@...ts.openwall.com>,
Daniel Micay <danielmicay@...il.com>, Linus Torvalds <torvalds@...ux-foundation.org>,
PaX Team <pageexec@...email.hu>, Arnd Bergmann <arnd@...db.de>
Subject: Re: [PATCH] gcc-plugins: structleak: add option to init all vars used
as byref args
On Sun, Aug 6, 2017 at 4:06 AM, Ard Biesheuvel
<ard.biesheuvel@...aro.org> wrote:
> In the Linux kernel, struct type variables are rarely passed by-value,
> and so functions that initialize such variables typically take an input
> reference to the variable rather than returning a value that can
> subsequently be used in an assignment.
>
> If the initalization function is not part of the same compilation unit,
> the lack of an assignment operation defeats any analysis the compiler
> can perform as to whether the variable may be used before having been
> initialized. This means we may end up passing on such variables
> uninitialized, resulting in potential information leaks.
>
> So extend the existing structleak GCC plugin so it will [optionally]
> apply to all struct type variables that have their address taken at any
> point, rather than only to variables of struct types that have a __user
> annotation.
>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@...aro.org>
Thanks! This looks good to me; I'll get it into -next.
-Kees
> ---
> arch/Kconfig | 7 +++++++
> scripts/Makefile.gcc-plugins | 1 +
> scripts/gcc-plugins/structleak_plugin.c | 13 +++++++++++--
> 3 files changed, 19 insertions(+), 2 deletions(-)
>
> diff --git a/arch/Kconfig b/arch/Kconfig
> index 21d0089117fe..edc6fd41b7ea 100644
> --- a/arch/Kconfig
> +++ b/arch/Kconfig
> @@ -468,6 +468,13 @@ config GCC_PLUGIN_STRUCTLEAK_VERBOSE
> initialized. Since not all existing initializers are detected
> by the plugin, this can produce false positive warnings.
>
> +config GCC_PLUGIN_STRUCTLEAK_BYREF_ALL
> + bool "Force initialize all struct type variables passed by reference"
> + depends on GCC_PLUGIN_STRUCTLEAK
> + help
> + Zero initialize any struct type local variable that may be passed by
> + reference without having been initialized.
> +
> config GCC_PLUGIN_RANDSTRUCT
> bool "Randomize layout of sensitive kernel structures"
> depends on GCC_PLUGINS
> diff --git a/scripts/Makefile.gcc-plugins b/scripts/Makefile.gcc-plugins
> index 2e0e2eaa397f..d1f7b0d6be66 100644
> --- a/scripts/Makefile.gcc-plugins
> +++ b/scripts/Makefile.gcc-plugins
> @@ -27,6 +27,7 @@ ifdef CONFIG_GCC_PLUGINS
>
> gcc-plugin-$(CONFIG_GCC_PLUGIN_STRUCTLEAK) += structleak_plugin.so
> gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STRUCTLEAK_VERBOSE) += -fplugin-arg-structleak_plugin-verbose
> + gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL) += -fplugin-arg-structleak_plugin-byref-all
> gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STRUCTLEAK) += -DSTRUCTLEAK_PLUGIN
>
> gcc-plugin-$(CONFIG_GCC_PLUGIN_RANDSTRUCT) += randomize_layout_plugin.so
> diff --git a/scripts/gcc-plugins/structleak_plugin.c b/scripts/gcc-plugins/structleak_plugin.c
> index fa3d7a4b26f2..3f8dd4868178 100644
> --- a/scripts/gcc-plugins/structleak_plugin.c
> +++ b/scripts/gcc-plugins/structleak_plugin.c
> @@ -16,6 +16,7 @@
> * Options:
> * -fplugin-arg-structleak_plugin-disable
> * -fplugin-arg-structleak_plugin-verbose
> + * -fplugin-arg-structleak_plugin-byref-all
> *
> * Usage:
> * $ # for 4.5/4.6/C based 4.7
> @@ -42,6 +43,7 @@ static struct plugin_info structleak_plugin_info = {
> };
>
> static bool verbose;
> +static bool byref_all;
>
> static tree handle_user_attribute(tree *node, tree name, tree args, int flags, bool *no_add_attrs)
> {
> @@ -150,7 +152,9 @@ static void initialize(tree var)
> /* these aren't the 0days you're looking for */
> if (verbose)
> inform(DECL_SOURCE_LOCATION(var),
> - "userspace variable will be forcibly initialized");
> + "%s variable will be forcibly initialized",
> + (byref_all && TREE_ADDRESSABLE(var)) ? "byref"
> + : "userspace");
>
> /* build the initializer expression */
> initializer = build_constructor(TREE_TYPE(var), NULL);
> @@ -190,7 +194,8 @@ static unsigned int structleak_execute(void)
> continue;
>
> /* if the type is of interest, examine the variable */
> - if (TYPE_USERSPACE(type))
> + if (TYPE_USERSPACE(type) ||
> + (byref_all && TREE_ADDRESSABLE(var)))
> initialize(var);
> }
>
> @@ -232,6 +237,10 @@ __visible int plugin_init(struct plugin_name_args *plugin_info, struct plugin_gc
> verbose = true;
> continue;
> }
> + if (!strcmp(argv[i].key, "byref-all")) {
> + byref_all = true;
> + continue;
> + }
> error(G_("unknown option '-fplugin-arg-%s-%s'"), plugin_name, argv[i].key);
> }
>
> --
> 2.11.0
>
--
Kees Cook
Pixel Security
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.