these should not be used system wide (see package.env). good for small programs that don’t serve as dependencies for alot of other important packages. specifying flags will force them and can cause problems with compilation or cause the program to stop unexpectedly.

  _FORTIFY_SOURCE (since glibc 2.3.4)
          Defining this macro causes some lightweight checks to be performed to detect some buffer overflow errors when
          employing various string and memory manipulation functions
          (for example, memcpy(3), memset(3), stpcpy(3), strcpy(3),
          strncpy(3), strcat(3), strncat(3), sprintf(3),
          snprintf(3), vsprintf(3), vsnprintf(3), gets(3), and wide
          character variants thereof).  For some functions, argument
          consistency is checked; for example, a check is made that
          open(2) has been supplied with a mode argument when the
          specified flags include O_CREAT.  Not all problems are
          detected, just some common cases.

          If _FORTIFY_SOURCE is set to 1, with compiler optimization
          level 1 (gcc -O1) and above, checks that shouldn't change
          the behavior of conforming programs are performed.  With
          _FORTIFY_SOURCE set to 2, some more checking is added, but
          some conforming programs might fail.

          Some of the checks can be performed at compile time (via
          macros logic implemented in header files), and result in
          compiler warnings; other checks take place at run time,
          and result in a run-time error if the check fails

-fcf-protection=[full|branch|return|none|check]

Enable code instrumentation of control-flow transfers to increase program security by checking that target addresses of control-flow transfer instructions (such as indirect function call, function return, indirect jump) are valid. This prevents diverting the flow of control to an unexpected target. This is intended to protect against such threats as Return-oriented Programming (ROP), and similarly call/jmp-oriented programming (COP/JOP).

The value branch tells the compiler to implement checking of validity of control-flow transfer at the point of indirect branch instructions, i.e. call/jmp instructions. The value return implements checking of validity at the point of returning from a function. The value full is an alias for specifying both branch and return. The value none turns off instrumentation.

The value check is used for the final link with link-time optimization (LTO). An error is issued if LTO object files are compiled with different -fcf-protection values. The value check is ignored at the compile time.

The macro __CET__ is defined when -fcf-protection is used. The first bit of __CET__ is set to 1 for the value branch and the second bit of __CET__ is set to 1 for the return.

You can also use the nocf_check attribute to identify which functions and calls should be skipped from instrumentation (see Function Attributes).

Currently the x86 GNU/Linux target provides an implementation based on Intel Control-flow Enforcement Technology (CET).

-mstack-protector-guard=guard -mstack-protector-guard-reg=reg -mstack-protector-guard-offset=offset

Generate stack protection code using canary at guard. Supported locations are ‘global’ for global canary or ‘tls’ for per-thread canary in the TLS block (the default). This option has effect only when -fstack-protector or -fstack-protector-all is specified.
With the latter choice the options -mstack-protector-guard-reg=reg and -mstack-protector-guard-offset=offset furthermore specify which segment register (%fs or %gs) to use as base register for reading the canary, and from what offset from that base register. The default for those is as specified in the relevant ABI.

-fstack-protector

Emit extra code to check for buffer overflows, such as stack smashing attacks. This is done by adding a guard variable to functions with vulnerable objects. This includes functions that call alloca, and functions with buffers larger than or equal to 8 bytes. The guards are initialized when a function is entered and then checked when the function exits. If a guard check fails, an error message is printed and the program exits. Only variables that are actually allocated on the stack are considered, optimized away variables or variables allocated in registers don’t count.

-fstack-protector-all

Like -fstack-protector except that all functions are protected.

-fstack-protector-strong

Like -fstack-protector but includes additional functions to be protected — those that have local array definitions, or have references to local frame addresses. Only variables that are actually allocated on the stack are considered, optimized away variables or variables allocated in registers don’t count.

-fstack-protector-explicit

Like -fstack-protector but only protects those functions which have the stack_protect attribute.

-fstack-check

Generate code to verify that you do not go beyond the boundary of the stack. You should specify this flag if you are running in an environment with multiple threads, but you only rarely need to specify it in a single-threaded environment since stack overflow is automatically detected on nearly all systems if there is only one stack.

Note that this switch does not actually cause checking to be done; the operating system or the language runtime must do that. The switch causes generation of code to ensure that they see the stack being extended.

You can additionally specify a string parameter: ‘no’ means no checking, ‘generic’ means force the use of old-style checking, ‘specific’ means use the best checking method and is equivalent to bare -fstack-check.

Old-style checking is a generic mechanism that requires no specific target support in the compiler but comes with the following drawbacks:

    Modified allocation strategy for large objects: they are always allocated dynamically if their size exceeds a fixed threshold. Note this may change the semantics of some code.
    Fixed limit on the size of the static frame of functions: when it is topped by a particular function, stack checking is not reliable and a warning is issued by the compiler.
    Inefficiency: because of both the modified allocation strategy and the generic implementation, code performance is hampered.

Note that old-style stack checking is also the fallback method for ‘specific’ if no target support has been added in the compiler.

‘-fstack-check=’ is designed for Ada’s needs to detect infinite recursion and stack overflows. ‘specific’ is an excellent choice when compiling Ada code. It is not generally sufficient to protect against stack-clash attacks. To protect against those you want ‘-fstack-clash-protection’.

-fstack-clash-protection

Generate code to prevent stack clash style attacks. When this option is enabled, the compiler will only allocate one page of stack space at a time and each page is accessed immediately after allocation. Thus, it prevents allocations from jumping over any stack guard page provided by the operating system.

Most targets do not fully support stack clash protection. However, on those targets -fstack-clash-protection will protect dynamic stack allocations. -fstack-clash-protection may also provide limited protection for static stack allocations if the target supports -fstack-check=specific.

-fstack-limit-register=reg -fstack-limit-symbol=sym -fno-stack-limit

Generate code to ensure that the stack does not grow beyond a certain value, either the value of a register or the address of a symbol. If a larger stack is required, a signal is raised at run time. For most targets, the signal is raised before the stack overruns the boundary, so it is possible to catch the signal without taking special precautions.

For instance, if the stack starts at absolute address ‘0x80000000’ and grows downwards, you can use the flags -fstack-limit-symbol=__stack_limit and -Wl,--defsym,__stack_limit=0x7ffe0000 to enforce a stack limit of 128KB. Note that this may only work with the GNU linker.

You can locally override stack limit checking by using the no_stack_limit function attribute (see Function Attributes).

-fsplit-stack

Generate code to automatically split the stack before it overflows. The resulting program has a discontiguous stack which can only overflow if the program is unable to allocate any more memory. This is most useful when running threaded programs, as it is no longer necessary to calculate a good stack size to use for each thread. This is currently only implemented for the x86 targets running GNU/Linux.

When code compiled with -fsplit-stack calls code compiled without -fsplit-stack, there may not be much stack space available for the latter code to run. If compiling all code, including library code, with -fsplit-stack is not an option, then the linker can fix up these calls so that the code compiled without -fsplit-stack always has a large stack. Support for this is implemented in the gold linker in GNU binutils release 2.21 and later.
  • dm9pZCAq
    link
    fedilink
    arrow-up
    2
    ·
    3 years ago

    LDFLAGS

    ld -z now, gcc -Wl,-z,now

    When generating an executable or shared library, mark it to tell the dynamic linker to resolve all symbols when the program is started, or when the shared library is loaded by dlopen, instead of deferring function call resolution to the point when the function is first called.

    ld -z relro, gcc -Wl,-z,relro

    Create an ELF “PT_GNU_RELRO” segment header in the object. This specifies a memory segment that should be made read-only after relocation, if supported. Specifying common-page-size smaller tha the system page size will render this protection ineffective.


    also some additional useful info can be found here https://wiki.debian.org/Hardening