From: martynas Date: Tue, 6 May 2014 23:22:33 +0000 (+0000) Subject: Introduce -fstack-shuffle, which randomizes local stack variables. X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=121b8252e78edb2a35c749786359b07e61fda24a;p=openbsd 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@ --- 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.