Compiler defenses

QNX SDP8.0QNX OS System Security GuideAPIConfiguration

Recommended compiler options

The following compiler options enable security features and are included by default when you compile using q++ or qcc:

Option Description
-fpic (default), -fPIC Creates objects for two types of shared libraries (*S.a and *.so).
-fPIE (default), -fpie Creates objects for position independent executables and non-shared static libraries (*.a).
-fstack-protector-strong Inserts a stack canary onto the stack frame for vulnerable functions, to protect against stack buffer overflow.

By default, qcc implicitly uses the -fstack-protector-strong option. However, it is not implicitly used when you directly invoke either ntoaarch64-gcc or ntox86_64-gcc, or specify some specific compiler or linker options. For more information, go to Stack protection in Security features for developers.

The following compiler option is not included by default:

Option Description
-mbranch-protection Enables branch protection features for 64-bit ARM (AArch64) systems with CPUs that support it. QNX SDP 8.0 currently supports one of those branch protection features: Pointer Authentication. Pointer authentication can provide protection against, for example, ROP exploits. QNX recommends that you set this option to pac-ret+leaf. For more information, refer to the GCC 12.2.0 compiler documentation. (https://gcc.gnu.org/onlinedocs/gcc-12.2.0/gcc/AArch64-Options.html#index-mbranch-protection)

Specify -U at startup to check for and set Pointer Authentication support. For more information, refer to startup-* options in the Utilities Reference.

The following additional options configure the compiler to output warnings when vulnerable code is detected. Depending on the condition detected, the offending code might be prone to crashing, produce errors or unexpected behavior, or create an opportunity for attack:

Option Description
-Wall Enable additional warnings about questionable code construction. Includes -Wformat, which checks calls to printf()- and scanf()-style functions to make sure the arguments match the format strings.
-Wcast-align Warn if the way a pointer is cast causes the required alignment of the target to increased.
-Wcast-qual Warn whenever the way a pointer is cast removes a type qualifier from the target type.
-Wconversion Warn for implicit conversions that may alter a value.
-Wduplicated-branches Warn when an if-else has identical branches.
-Wduplicated-cond Warn about duplicated conditions in an if-else-if chain.
-Werror Treat warnings as errors, failing the build. May not be appropriate in all environments.
-Wextra Enable additional warnings not enabled by -Wall.
-Wfloat-equal Warn if floating-point values are used in equality comparisons.
-Wformat=2 Check calls to printf()- and scanf()-style functions to make sure the arguments match the format strings (-Wformat), plus additional format checks (-Wformat-nonliteral, -Wformat-security, -Wformat-y2k).
-Winit-self Warn about uninitialized variables that are initialized with themselves (requires -Wuninitialized, which is included in -Wall).
-Wlogical-op Warn about suspicious uses of logical operators in expressions.
-Wmissing-declarations Warn if a global function is defined without a previous declaration.
-Wmissing-prototypes Warn if there are missing prototypes.
-Wnull-dereference Warn if the compiler detects paths that trigger errors or undefined behavior because a null pointer is dereferenced.
-Wpointer-arith Warn about anything that depends on the size of a function type or of void.
-Wshadow Warn whenever a local variable or type declaration shadows another variable, parameter, type, or class member (in C++), or whenever a built-in function is shadowed.
-Wsuggest-attribute=format Warn about function pointers that might be candidates for format attributes. When the format attribute is set, the -Wformat=2 flags look for problems with invocations of the function.
-Wswitch-default Warn whenever a switch statement does not have a default case.
-Wswitch-enum Warn whenever a switch statement has an index of enumerated type and lacks a case for one or more of the named codes of that enumeration.
-Wtrampolines Warn when trampolines are generated for pointers to nested functions. (A trampoline is a small piece of data or code that is created at runtime on the stack when the address of a nested function is taken, and is used to call the nested function indirectly.)
-Wunreachable-code Warn if the compiler detects code that will never be executed.
-Wvla-larger-than=4096 Warns if the size of a variable length array (VLA) is larger than 4096 bytes (one page of memory). VLA allocations of 4096 bytes or smaller cannot bypass the guard page at the top of the stack. This option requires an optimization level of 1 or higher.
-Wwrite-strings Issue a diagnostic message if const char * is converted to (non-const) char *.

For detailed information on the warning options, refer to the GNU compiler documentation at: https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html

Recommended preprocessor options

QNX recommends the following CPPFLAGS preprocessor option:

Option Description
-D_FORTIFY_SOURCE=2 Enables fortified system functions with more stringent parameter validation (refer to Fortified System Functions.)

Recommended linker options

QNX recommends the following linker (LDFLAGS) options:

Option Description
-pie Compile an executable as position-independent executable (PIE). Enabled by default with QNX OS compile utilities.
-Wl,-z,relro -Wl,-z,now Enable Full RELRO (Relocation Read-Only). Refer to RELRO in Security features for developers.) Enabled by default with QNX OS compile utilities.
-Wl,-z,defs Prevents undefined symbols in object files.

Recommended compiler verification options

You can increase the probability of finding bugs in your code by compiling it with sanitizers enabled. These compiler options are not meant to be enabled in production binaries. Each option targets a different aspect of the code. To fully utilize the power of these options, make sure that your instrumented code is exercised as it would be in production.

QNX OS supports the Address Sanitizer (ASan) and Undefined Behavior Sanitizer (UBSan). For details, refer to ASan and UBSan.

To use these sanitizer options, include libstdc++.so in your IFS.

Options Description
-fsanitize=address -lasan Enables ASan. Memory access instructions are instrumented to detect out-of-bounds and use-after-free bugs.
-fsanitize=undefined -lubsan Enables UBSan. Various computations are instrumented to detect undefined behavior at runtime.

For more information, refer to the GNU compiler documentation at: https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html

ASan and UBSan

The compiler builds the ASan and UBSan features into the executables. An environment variable optionally controls these features.

ASan

Address Sanitizer (ASan) is a memory error detector for C/C++.

When you enable the ASan feature, the compiler adds code to the program to implement address sanitization. You can then build the binary with the -fsanitize=address option (refer to Recommended compiler verification options). The program relies on the libasan.so library, which links automatically, for the target-dependent functionality.

Note:
The target runtime part of the GCC sanitizer suite (libasan) is a compiler feature. It sanitizes the code at build and run time.

The ASAN_OPTIONS environment variable passes most of the runtime flags to the Address Sanitizer. For more information on runtime and other flags, refer to the AddressSanitizer project documentation at: https://github.com/google/sanitizers/wiki/AddressSanitizerFlags.

UBSan

Undefined Behavior Sanitizer (UBSan) is a fast, undefined-behavior detector.

UBSan modifies the program at compile time to catch undefined behavior during the execution of a program. For details about current checks, refer to the Clang Compiler documentation for UBSan at: https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html#ubsan-checks.

To suppress the UBSan error reports for specific files, functions, or libraries, without recompiling the code, pass its path in a UBSAN_OPTIONS environment variable.

When you use the qcc option to compile and link the program with the -fsanitize=undefined flag, the executable links with the proper UBSan runtime library (libubsan.so).

Page updated: