From 121b8252e78edb2a35c749786359b07e61fda24a Mon Sep 17 00:00:00 2001 From: martynas Date: Tue, 6 May 2014 23:22:33 +0000 Subject: [PATCH] Introduce -fstack-shuffle, which randomizes local stack variables. This will make the environment more hostile and help detect bugs that depend on overrunning one variable into another, with almost no performance cost. Discussed with Theo at m2k14 hackathon. "oh god yes" tedu@, "oh nice" djm@ --- gnu/gcc/gcc/cfgexpand.c | 41 +++++++++++++++++++++++++++++------------ gnu/gcc/gcc/common.opt | 4 ++++ 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/gnu/gcc/gcc/cfgexpand.c b/gnu/gcc/gcc/cfgexpand.c index ccb534f0e18..88bc17a206c 100644 --- a/gnu/gcc/gcc/cfgexpand.c +++ b/gnu/gcc/gcc/cfgexpand.c @@ -429,7 +429,21 @@ partition_stack_vars (void) if (n == 1) return; - qsort (stack_vars_sorted, n, sizeof (size_t), stack_var_size_cmp); + if (flag_stack_shuffle) + { + /* Fisher-Yates shuffle */ + for (si = n - 1; si > 0; si--) + { + size_t tmp; + sj = arc4random_uniform(si); + + tmp = stack_vars_sorted[si]; + stack_vars_sorted[si] = stack_vars_sorted[sj]; + stack_vars_sorted[sj] = tmp; + } + } + else + qsort (stack_vars_sorted, n, sizeof (size_t), stack_var_size_cmp); /* Special case: detect when all variables conflict, and thus we can't do anything during the partitioning loop. It isn't uncommon (with @@ -1110,19 +1124,22 @@ expand_used_vars (void) /* Assign rtl to each variable based on these partitions. */ if (stack_vars_num > 0) { - /* Reorder decls to be protected by iterating over the variables - array multiple times, and allocating out of each phase in turn. */ - /* ??? We could probably integrate this into the qsort we did - earlier, such that we naturally see these variables first, - and thus naturally allocate things in the right order. */ - if (has_protected_decls) + if (!flag_stack_shuffle) { - /* Phase 1 contains only character arrays. */ - expand_stack_vars (stack_protect_decl_phase_1); + /* Reorder decls to be protected by iterating over the variables + array multiple times, and allocating out of each phase in turn. */ + /* ??? We could probably integrate this into the qsort we did + earlier, such that we naturally see these variables first, + and thus naturally allocate things in the right order. */ + if (has_protected_decls) + { + /* Phase 1 contains only character arrays. */ + expand_stack_vars (stack_protect_decl_phase_1); - /* Phase 2 contains other kinds of arrays. */ - if (flag_stack_protect == 2) - expand_stack_vars (stack_protect_decl_phase_2); + /* Phase 2 contains other kinds of arrays. */ + if (flag_stack_protect == 2) + expand_stack_vars (stack_protect_decl_phase_2); + } } expand_stack_vars (NULL); diff --git a/gnu/gcc/gcc/common.opt b/gnu/gcc/gcc/common.opt index c309c43249f..49f05b92e21 100644 --- a/gnu/gcc/gcc/common.opt +++ b/gnu/gcc/gcc/common.opt @@ -874,6 +874,10 @@ fstack-protector-strong Common Report RejectNegative Var(flag_stack_protect, 3) Use a smart stack protection method for certain functions +fstack-shuffle +Common Report Var(flag_stack_shuffle) +Shuffle local stack variables. + fstrength-reduce Common Does nothing. Preserved for backward compatibility. -- 2.20.1