summaryrefslogtreecommitdiffstats
path: root/scripts/gcc-plugins
diff options
context:
space:
mode:
authorAlexander Popov <alex.popov@linux.com>2020-06-24 15:33:30 +0300
committerKees Cook <keescook@chromium.org>2020-06-24 07:48:44 -0700
commit8dd70543f795d1836003754f3c60226f21433c99 (patch)
tree0635f39547948251536a3cfde3f2c4c076760d1c /scripts/gcc-plugins
parentfeee1b8c490821f29aae416a5422795f5a29263d (diff)
downloadlinux-8dd70543f795d1836003754f3c60226f21433c99.tar.gz
linux-8dd70543f795d1836003754f3c60226f21433c99.tar.bz2
linux-8dd70543f795d1836003754f3c60226f21433c99.zip
gcc-plugins/stackleak: Add 'verbose' plugin parameter
Add 'verbose' plugin parameter for stackleak gcc plugin. It can be used for printing additional info about the kernel code instrumentation. For using it add the following to scripts/Makefile.gcc-plugins: gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STACKLEAK) \ += -fplugin-arg-stackleak_plugin-verbose Signed-off-by: Alexander Popov <alex.popov@linux.com> Link: https://lore.kernel.org/r/20200624123330.83226-6-alex.popov@linux.com Signed-off-by: Kees Cook <keescook@chromium.org>
Diffstat (limited to 'scripts/gcc-plugins')
-rw-r--r--scripts/gcc-plugins/stackleak_plugin.c47
1 files changed, 42 insertions, 5 deletions
diff --git a/scripts/gcc-plugins/stackleak_plugin.c b/scripts/gcc-plugins/stackleak_plugin.c
index a18b0d4af456..48e141e07956 100644
--- a/scripts/gcc-plugins/stackleak_plugin.c
+++ b/scripts/gcc-plugins/stackleak_plugin.c
@@ -34,6 +34,8 @@ __visible int plugin_is_GPL_compatible;
static int track_frame_size = -1;
static bool build_for_x86 = false;
static const char track_function[] = "stackleak_track_stack";
+static bool disable = false;
+static bool verbose = false;
/*
* Mark these global variables (roots) for gcc garbage collector since
@@ -46,6 +48,7 @@ static struct plugin_info stackleak_plugin_info = {
.help = "track-min-size=nn\ttrack stack for functions with a stack frame size >= nn bytes\n"
"arch=target_arch\tspecify target build arch\n"
"disable\t\tdo not activate the plugin\n"
+ "verbose\t\tprint info about the instrumentation\n"
};
static void add_stack_tracking_gcall(gimple_stmt_iterator *gsi, bool after)
@@ -102,6 +105,10 @@ static tree get_current_stack_pointer_decl(void)
return var;
}
+ if (verbose) {
+ fprintf(stderr, "stackleak: missing current_stack_pointer in %s()\n",
+ DECL_NAME_POINTER(current_function_decl));
+ }
return NULL_TREE;
}
@@ -195,6 +202,11 @@ static unsigned int stackleak_instrument_execute(void)
if (!is_alloca(stmt))
continue;
+ if (verbose) {
+ fprintf(stderr, "stackleak: be careful, alloca() in %s()\n",
+ DECL_NAME_POINTER(current_function_decl));
+ }
+
/* Insert stackleak_track_stack() call after alloca() */
add_stack_tracking(&gsi, true);
if (bb == entry_bb)
@@ -384,13 +396,31 @@ static bool remove_stack_tracking_gasm(void)
*/
static unsigned int stackleak_cleanup_execute(void)
{
+ const char *fn = DECL_NAME_POINTER(current_function_decl);
bool removed = false;
- if (cfun->calls_alloca)
+ /*
+ * Leave stack tracking in functions that call alloca().
+ * Additional case:
+ * gcc before version 7 called allocate_dynamic_stack_space() from
+ * expand_stack_vars() for runtime alignment of constant-sized stack
+ * variables. That caused cfun->calls_alloca to be set for functions
+ * that in fact don't use alloca().
+ * For more info see gcc commit 7072df0aae0c59ae437e.
+ * Let's leave such functions instrumented as well.
+ */
+ if (cfun->calls_alloca) {
+ if (verbose)
+ fprintf(stderr, "stackleak: instrument %s(): calls_alloca\n", fn);
return 0;
+ }
- if (large_stack_frame())
+ /* Leave stack tracking in functions with large stack frame */
+ if (large_stack_frame()) {
+ if (verbose)
+ fprintf(stderr, "stackleak: instrument %s()\n", fn);
return 0;
+ }
if (lookup_attribute_spec(get_identifier("no_caller_saved_registers")))
removed = remove_stack_tracking_gasm();
@@ -516,9 +546,6 @@ __visible int plugin_init(struct plugin_name_args *plugin_info,
/* Parse the plugin arguments */
for (i = 0; i < argc; i++) {
- if (!strcmp(argv[i].key, "disable"))
- return 0;
-
if (!strcmp(argv[i].key, "track-min-size")) {
if (!argv[i].value) {
error(G_("no value supplied for option '-fplugin-arg-%s-%s'"),
@@ -541,6 +568,10 @@ __visible int plugin_init(struct plugin_name_args *plugin_info,
if (!strcmp(argv[i].value, "x86"))
build_for_x86 = true;
+ } else if (!strcmp(argv[i].key, "disable")) {
+ disable = true;
+ } else if (!strcmp(argv[i].key, "verbose")) {
+ verbose = true;
} else {
error(G_("unknown option '-fplugin-arg-%s-%s'"),
plugin_name, argv[i].key);
@@ -548,6 +579,12 @@ __visible int plugin_init(struct plugin_name_args *plugin_info,
}
}
+ if (disable) {
+ if (verbose)
+ fprintf(stderr, "stackleak: disabled for this translation unit\n");
+ return 0;
+ }
+
/* Give the information about the plugin */
register_callback(plugin_name, PLUGIN_INFO, NULL,
&stackleak_plugin_info);