Skip to content

Commit

Permalink
gcc-plugins: structleak: add option to init all vars used as byref args
Browse files Browse the repository at this point in the history
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@linaro.org>
Signed-off-by: Kees Cook <keescook@chromium.org>
  • Loading branch information
Ard Biesheuvel authored and kees committed Aug 7, 2017
1 parent 520eccd commit f7dd250
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 2 deletions.
7 changes: 7 additions & 0 deletions arch/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,13 @@ config GCC_PLUGIN_STRUCTLEAK
* https://grsecurity.net/
* https://pax.grsecurity.net/

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_STRUCTLEAK_VERBOSE
bool "Report forcefully initialized variables"
depends on GCC_PLUGIN_STRUCTLEAK
Expand Down
1 change: 1 addition & 0 deletions scripts/Makefile.gcc-plugins
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
13 changes: 11 additions & 2 deletions scripts/gcc-plugins/structleak_plugin.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
{
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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);
}

Expand Down

0 comments on commit f7dd250

Please sign in to comment.