skip to Main Content

*I’m on an Ubuntu x86_64 system, gcc 11.4.0

I have this C program in a file test.c :

int fx( int a, int* b ){

     *b = 12;
      return a;

}


int main(){
    
    int a = 20;
    int b = fx(10,&a);
    b+= 5;
    
}

I compile this file with "gcc test.c -o test". Then I inspect it with "objdump -dw -M suffix test" and I get :

0000000000001149 <fx>:
    1149:   f3 0f 1e fa             endbr64 
    114d:   55                      pushq  %rbp
    114e:   48 89 e5                movq   %rsp,%rbp
    1151:   89 7d fc                movl   %edi,-0x4(%rbp)
    1154:   48 89 75 f0             movq   %rsi,-0x10(%rbp)
    1158:   48 8b 45 f0             movq   -0x10(%rbp),%rax
    115c:   c7 00 0c 00 00 00       movl   $0xc,(%rax)
    1162:   8b 45 fc                movl   -0x4(%rbp),%eax
    1165:   5d                      popq   %rbp
    1166:   c3                      retq   

0000000000001167 <main>:
    1167:   f3 0f 1e fa                     endbr64 
    116b:   55                              pushq  %rbp
    116c:   48 89 e5                        movq   %rsp,%rbp
    116f:   48 83 ec 10                     subq   $0x10,%rsp
    1173:   64 48 8b 04 25 28 00 00 00      movq   %fs:0x28,%rax
    117c:   48 89 45 f8                     movq   %rax,-0x8(%rbp)
    1180:   31 c0                           xorl   %eax,%eax
    1182:   c7 45 f0 14 00 00 00            movl   $0x14,-0x10(%rbp)
    1189:   48 8d 45 f0                     leaq   -0x10(%rbp),%rax
    118d:   48 89 c6                        movq   %rax,%rsi
    1190:   bf 0a 00 00 00                  movl   $0xa,%edi
    1195:   e8 af ff ff ff                  callq  1149 <fx>
    119a:   89 45 f4                        movl   %eax,-0xc(%rbp)
    119d:   83 45 f4 05                     addl   $0x5,-0xc(%rbp)
    11a1:   b8 00 00 00 00                  movl   $0x0,%eax
    11a6:   48 8b 55 f8                     movq   -0x8(%rbp),%rdx
    11aa:   64 48 2b 14 25 28 00 00 00      subq   %fs:0x28,%rdx
    11b3:   74 05                           je     11ba <main+0x53>
    11b5:   e8 96 fe ff ff                  callq  1050 <__stack_chk_fail@plt>
    11ba:   c9                              leaveq 
    11bb:   c3                              retq

It looks like the compiler uses stack protector by default as you can tell by looking at the main instructions.

My questions :

  1. Is it ok to compile my C program with "gcc test.c -fno-stack-protector -o test"?

  2. Is -fno-stack-protector just a safety option that makes us vulnerable to some stack attacks or we should be careful when using this option while compiling because it could break something or create some errors/incompatibilities of some kind ?

  3. Why doesn’t my gcc compiler have it on by default whereas in other systems ( macOS x86_64 clang ) I’ve noticed it is on ?

  4. What are the scenarios where it makes sense using it versus the ones we should absolutely avoid it ?

2

Answers


    1. Yes, it’s perfectly fine to do so. At your own risk though. Without it, you will have one less protection against potential stack buffer-overflow vulnerabilities in your program.
    2. Yeah it’s just a safety feature/option, compiling with/without it will not break stuff unless you are developing complex low-level standard library code.
    3. Depends on your compiler version and OS/distro. Each OS/distribution has its own compiler build with different configurations and defaults. Yours apparently decided to configure GCC with default stack protector. Actually, if I am not mistaken, from a certain version onwards GCC just enabled -fstack-protector by default so a distro would need to explicitly configure GCC to disable it by default to change that.
    4. The only scenario when you may want to avoid it is microbenchmarks or particular low-level programming situations where code has to be exactly what you expect without additional compiler-generated noise. In the general case, it doesn’t make much sense to disable it, its overhead should be negligible.
    Login or Signup to reply.
  1. Is it ok to compile my C program with "gcc test.c -fno-stack-protector -o test"?

    I do not see any problem with doing that. For convention, it might be better to place options before operands like so:

    gcc -fno-stack-protector -o test test.c
    

    Is -fno-stack-protector just a safety option that makes us vulnerable to some stack attacks or we should be careful when using this option while compiling because it could break something or create some errors/incompatibilities of some kind ?

    The option -fstack-protector=... enables extra hardening against stack smashing attacks. If you disable it with -fno-stack-protector, your code will not benefit from this hardening and may be easier to exploit if it already has an exploitable defect. You can mix and match object files compiled with and without the stack protector as you desire, use of the stack protector causes no incompatibilities. However, only functions defined in translation units that have been compiled with stack protector turned on benefit from this hardening.

    Why doesn’t my gcc compiler have it on by default whereas in other systems ( macOS x86_64 clang ) I’ve noticed it is on ?

    Canonical has decided to enable this option by default as to make hardening against stack-smashing an “opt out” instead of an ”opt in” as it is on macOS. This improves overall security.

    What are the scenarios where it makes sense using it versus the ones we should absolutely avoid it ?

    Compiling with stack protector turned on is generally useful and especially so if your code is ran with untrusted input or input coming from network or external storage media. However, there is a minor performance cost. If this is is significant, you may want to turn off the stack protector. Be aware that your application may then be easier to exploit with stack smashing attacks if it has such a defect.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search