Jest -fstack-protect
w gcc, aby zmienić kolejność zmiennych stosu, domyślnie włączona w jakiś Linux Wersja systemu operacyjnego od prawie 10 lat, szczególnie Ubuntu, Redhat, gentoo. domyślnie również od gcc 4.8.3 ("4.9, a później włączyć -fstack-protector-silny.")
Ubuntu strona o gcc domyślne: https://wiki.ubuntu.com/ToolChain/CompilerFlags
Ubuntu specyficznych flag domyślny kompilator toolchain używane, aby pomóc zapewnić dodatkowe funkcje bezpieczeństwa do Ubuntu. ... Domyślne flagi -fstack-protector
... Pierwsza włączona w systemie Ubuntu 6.10.
Ubuntu strona o ochronie stosu https://wiki.ubuntu.com/GccSsp
gcc 4.1 pochodzi z SSP teraz, co jest miłym technologii w celu zmniejszenia możliwości wykorzystania wielu przepełnienia bufora. ... SSP dostarcza technologię, aby zatrzymać Exploitability tej klasy luki (1) zamianom zmienne stos ... RedHat i Gentoo używają SSP domyślnie lat
Ta zmiana kolejności wymaga kilku O(n^2)
spacery wszystkie lokalne zmienne funkcji, które spowodują spowolnienie kompilacji dla długich funkcji, na przykład "Dlaczego skompilowanie ponad 100 000 linii std :: vector :: push_back zajmuje dużo czasu?" - https://stackoverflow.com/a/14034393/196561
odroczony alokacja jest zmuszony gdy -fstack-protect
jest włączona (czasami musi uporządkować wszystkie zmienne stosu). ..cfgexpand.c
969 /* A subroutine of expand_one_var. VAR is a variable that will be
970 allocated to the local stack frame. Return true if we wish to
971 add VAR to STACK_VARS so that it will be coalesced with other
972 variables. Return false to allocate VAR immediately.
973
974 This function is used to reduce the number of variables considered
975 for coalescing, which reduces the size of the quadratic problem. */
976
977 static bool
978 defer_stack_allocation (tree var, bool toplevel)
980 /* If stack protection is enabled, *all* stack variables must be deferred,
981 so that we can re-order the strings to the top of the frame. */
Więc, gcc będzie uporządkować wszystkie zmienne stosu i ciągi będzie w górnej części ramki. Wypróbuj opcję -fno-stack-protector
, aby wyłączyć.
Jak zwykle autor gcc nie dokumentują jak -fstack-protect
prace w dokumentacji publicznej https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html:
-fstack-protector
Emit dodatkowego kodu w celu sprawdzenia przepełnienia bufora, takich jak ataki stosu rozbijając. Odbywa się to poprzez dodanie zmiennej strażnika do funkcji z obiektami wrażliwymi. Obejmuje to funkcje, które wywołują alloca
i działa z buforami większymi niż 8 bajtów. Osłony są inicjowane po wprowadzeniu funkcji, a następnie sprawdzane po jej wyjściu. Jeśli kontrola wartownika nie powiedzie się, zostanie wydrukowany komunikat o błędzie i program zostanie zamknięty.
-fstack-protector-all
Podobnie jak -fstack-protector
oprócz tego, że wszystkie funkcje są chronione.
Podobnie jak -fstack-protector
, ale zawiera dodatkowe funkcje, które mają być chronione - te, które mają lokalne definicje tablicowe lub zawierają odniesienia do lokalnych adresów ramek.
-fstack-protector-explicit
Podobnie jak -fstack-protector
, ale chroni tylko te funkcje, które mają atrybut stack_protect
.
A jedyna dokumentacja tablicy wcześniej nie mieszkańców widzę jest prawdziwe, najlepiej dokumentacja: kod źródłowy
https://gcc.gnu.org/viewcvs/gcc/branches/gcc-4_6-branch/gcc/cfgexpand.c?revision=175029&view=markup#l1526 - expand_used_vars()
1533 if (has_protected_decls)
1534 {
1535 /* Phase 1 contains only character arrays. */
1536 expand_stack_vars (stack_protect_decl_phase_1);
1537
1538 /* Phase 2 contains other kinds of arrays. */
1539 if (flag_stack_protect == 2)
1540 expand_stack_vars (stack_protect_decl_phase_2);
1541 }
1542
1543 expand_stack_vars (NULL);
faza 1 i faza 2 Vars są oddzielone stack_protect_decl_phase()
https://gcc.gnu.org/viewcvs/gcc/branches/gcc-4_6-branch/gcc/cfgexpand.c?revision=175029&view=markup#l1235
1235 /* Return nonzero if DECL should be segregated into the "vulnerable" upper
1236 part of the local stack frame. Remember if we ever return nonzero for
1237 any variable in this function. The return value is the phase number in
1238 which the variable should be allocated. */
1239
1240 static int
1241 stack_protect_decl_phase (tree decl)
...
1243 unsigned int bits = stack_protect_classify_type (TREE_TYPE (decl));
...
1249 if (flag_stack_protect == 2)
1250 {
1251 if ((bits & (SPCT_HAS_SMALL_CHAR_ARRAY | SPCT_HAS_LARGE_CHAR_ARRAY))
1252 && !(bits & SPCT_HAS_AGGREGATE))
1253 ret = 1;
1254 else if (bits & SPCT_HAS_ARRAY)
1255 ret = 2;
1256 }
stack_protect_classify_type
zwróci bity HAS_ARRAY
z HAS_*_CHAR_ARRAY
tylko dla tablic znaków (zarówno char, unsigned char and signed char)
Nie, kompilator nie musi przechowywać ich w określonej kolejności. Zmienne mogą wcale nie być w pamięci, jeśli mieszczą się w rejestrach lub są całkowicie zoptymalizowane. – Jester
Zmienne mogą mieć dowolną kolejność i może być dowolna liczba bajtów dopełnienia przed, po lub między zmiennymi. – user3386109
Dla zachowania przejrzystości, bajty dopełnienia służą do zachowania wyrównania. –