2014-06-28 22 views
10

moja wersja gcc to 4.8.2, a system operacyjny to Ubuntu 14.04 (64-bitowy). Zauważyłem, że czasami gcc automatycznie generuje kanarka, aby zrobić ochronę przed przepełnieniem bufora, nie, dlaczego?GCC generować Canary czy nie?

przypadku do wytworzenia kanarka: gdy rozmiar jest wielokrotnością czterech

#include<stdio.h> 
#define SIZE 4 

int main() 
{ 
    char s[SIZE]; 
    scanf("%s", s); 
    return 0; 
} 

ASM po gcc -c -g -wa, -a, -ad

... 
    4:a.c   **** int main() 
    5:a.c   **** { 
    13     .loc 1 5 0 
    14     .cfi_startproc 
    15 0000 55   pushq %rbp 
    16     .cfi_def_cfa_offset 16 
    17     .cfi_offset 6, -16 
    18 0001 4889E5  movq %rsp, %rbp 
    19     .cfi_def_cfa_register 6 
    20 0004 4883EC10  subq $16, %rsp 
    21     .loc 1 5 0 
    22 0008 64488B04  movq %fs:40, %rax 
    22  25280000 
    22  00 
    23 0011 488945F8  movq %rax, -8(%rbp) 
    24 0015 31C0   xorl %eax, %eax 
    6:a.c   ****  char s[SIZE]; 
    7:a.c   ****  scanf("%s", s); 
... 

przypadku nie generować kanarka: nie jest wielokrotnością czterech

#include<stdio.h> 
#define SIZE 2 

int main() 
{ 
    char s[SIZE]; 
    scanf("%s", s); 
    return 0; 
} 

ASM po gcc -c -g -wa, -a, -ad

... 
    4:a.c   **** int main() 
    5:a.c   **** { 
    13     .loc 1 5 0 
    14     .cfi_startproc 
    15 0000 55   pushq %rbp 
    16     .cfi_def_cfa_offset 16 
    17     .cfi_offset 6, -16 
    18 0001 4889E5  movq %rsp, %rbp 
    19     .cfi_def_cfa_register 6 
    20 0004 4883EC10  subq $16, %rsp 
    6:a.c   ****  char s[SIZE]; 
    7:a.c   ****  scanf("%s", s); 
... 
+2

Jaki jest twój system operacyjny (zarówno nazwa jak i wersja)? Jest to ważne, ponieważ różne dystrybucje zawierają różne łaty i domyślne flagi ([zobacz] (https://en.wikipedia.org/wiki/Stack-smashing_protection#GNU_Compiler_Collection_.28GCC.29)). Na przykład kanarki nie są generowane dla mnie, chyba że określę '-fstack-protector'. – xaizek

+0

Mój system operacyjny to Ubuntu 14.04 64bit – zongyuwu

+1

Najprawdopodobniej zostanie użyty '-fstack-protector', ale strona man mówi, że kanarek jest generowany dla wszystkich funkcji z buforami większymi niż 8 bajtów, a kompilator przydziela 16 bajtów dla obu buforów (tak samo na twoja maszyna i moja), więc obie wersje powinny ją mieć. Otrzymuję inne zachowanie w tej samej wersji GCC. Czy wypróbowałeś większe liczby, np. 17 i 20? – xaizek

Odpowiedz

10

OK, myślę, że znamy odpowiedź z komentarzy, więc opublikuję ją tutaj, aby wyraźnie ją podać.

Umieszczenie kanarków w wielu funkcjach może spowodować pogorszenie wydajności. Dlatego istnieje kilka sposobów, aby powiedzieć GCC, że chcemy z nich korzystać, które są dobrze opisane here. Główne pomysły:

  1. Kanarki nie są używane domyślnie, należy przekazać jedną z flag, które je umożliwiają.
  2. Aby zapisać czas wykonania, GCC używa prostej heurystyki z flagą -fstack-protector: dodaj kanarki dla funkcji używających alloca lub lokalnych buforów większych niż 8 bajtów (domyślnie).
  3. Heurystykę można poprawić przy pomocy parametru ssp-buffer-size: --param ssp-buffer-size=4.

Wygląda na to, że Ubuntu dostarcza wersję GCC z rozmiarem bufora zmienionym na 4, więc bufory o mniejszej pojemności nie powodują generowania kanarka. Potwierdzam (i każdy inny powinien móc powtórzyć), że kompilując dwa przykłady z --param ssp-buffer-size=4, który produkuje montaż z kanarkami tylko dla jednego z nich.