gcc-local —
local modifications to gcc
OpenBSD uses derivatives of
gcc(1) versions 3.3.6 or 4.2.1,
depending on machine architecture. In all cases, the software comes with
specific modifications for
OpenBSD:
- gcc does not search under
/usr/local for include files nor for
libraries: as a system compiler, it only searches the system paths by
default.
- On all architectures where the stack is non-executable,
trampoline code marks the smallest possible area around the trampoline
stub executable using
mprotect(2).
- Trampoline code generation is disabled by default. Code
requiring trampolines will not compile without
-ftrampolines. The warning flag
-Wtrampolines can be used to locate
trampoline instances if trampoline generation is re-enabled.
- The -O2 option does not
include -fstrict-aliasing, as this option
causes issues on some legacy code.
-fstrict-aliasing is very unsafe with code
that plays tricks with casts, bypassing the already weak type system of
C.
- The -O2 option does not
include -fstrict-overflow, as this option
causes issues on some legacy code.
-fstrict-overflow can cause surprising
optimizations to occur, possibly deleting security critical overflow
checks.
- The -O2 option does not
include the -ftree-vrp optimization as it is
known to be broken in gcc 4.2.1.
- gcc recognizes the extra
format attribute syslog, to better match the definition of
syslog(3), and silence
erroneous warnings when used with
-pedantic.
- gcc recognizes the attribute
__nonnull__, which can be used to mark
arguments that can't be
NULL
. The
printf format attribute does not imply
__nonnull__ for the format. This allows for
correct format checking on the
err(3) function family.
- gcc recognizes the extra
attribute __sentinel__, which can be used to
mark varargs function that need a
NULL
pointer to mark argument termination, like
execl(3). This exposes latent
bugs for 64-bit architectures, where a terminating 0 will expand to a
32-bit int, and not a full-fledged 64-bits pointer.
- On alpha, -mieee is enabled
by default to enable full compliance with the IEEE floating point
standard, although the “inexact” flag is not maintained.
Additionally, rounding mode is dynamic.
- gcc comes with the
“ProPolice” stack protection extension, which is enabled by
default. This extension reorders local variable declarations and adds
stack consistency checks at runtime, in order to detect stack overflows,
and will attempt to report the problem in the system logs by calling
syslog(3) with a
LOG_CRIT
priority message:
“stack overflow in function XXX”, and abort the faulting
process. It can be turned off using the
-fno-stack-protector command line option.
Note that the stack protector relies on some support code in libc.
Stand-alone programs not linked against libc must either provide their own
support bits or use the -fno-stack-protector
option.
There is a -fstack-protector-all option that
turns stack protection code on for all functions and disables any
heuristic that flags some functions as safe. This extended checking has a
moderate runtime cost though. There is a
-fstack-protector-strong option, similar to
-fstack-protector, which includes additional
functions to be protected — those that have local array definitions
or have references to local frame addresses.
- On amd64, -msave-args can be
passed to the compiler to have functions save their register arguments on
the stack, while maintaining compatibility with the System 5 AMD64 ABI.
This enables tools and debuggers that understand this semantic to
trivially generate stack traces that include function arguments.
- On the alpha, amd64, arm, hppa, i386, mips64, powerpc, sh
and sparc64 architectures, gcc generates
position-independent executables (PIEs) by default, allowing the system to
load the resulting binary at a random location. This behavior can be
turned off by passing -fno-pie to the
compiler and -nopie to the linker.
- gcc recognizes a new flag
which is enabled by default, -Wbounded, to
perform basic checks on functions which accept buffers and sizes. An extra
attribute, __bounded__, has been added to
mark functions that can be checked this way.
- gcc recognizes a new format
attribute, kprintf, to deal with the extra format arguments
‘
%b
’,
‘%r
’, and
‘%z
’ used in the
OpenBSD kernel.
- gcc does not store its
version string in objects. This behavior can be restored with
-fident.
- The option -fstack-shuffle
will randomize the order of stack variables at compile time with
gcc 4.2.1, which can be helpful to find bugs.
This option is silently ignored by gcc
3.3.6.
- gcc will not move variables
initialized with the value zero from the data section to the bss section.
The default behaviour of gcc 3.3.6 and
gcc 4.2.1 on other systems is to perform this
action, which can be restored for OpenBSD with
-fzero-initialized-in-bss.
- gcc does not warn for cast
expressions used as lvalues outside of
-pedantic.
- gcc 4.2.1 does not warn for
passing pointer arguments or assignment with different signedness outside
of -pedantic. This can be re-enabled with the
-Wpointer-sign flag.
- gcc recognizes the
preprocessor flag -CC that lets comments in
macros pass through to the output (except in
-traditional mode).
- The warning option
-Wsystem-headers, which makes
gcc report warnings in systems headers, is
enabled by default.
- gcc supports two extra
warning options:
- -Wframe-larger-than=N
(and its non-portable alias
-Wstack-larger-than-N)
will report functions using more than
N bytes of stack space for their
local variables. Stack space used for other purposes (such as register
window saving, callee-saved registers, or outbound arguments storage)
is not taken into account for this check.
- -Wvariable-decl
will report automatic variable declarations whose size cannot be
determined at compile-time.
- gcc 4.2.1 and
gcc 3.3.6 have backported support for the GCC
binary integer constants extension, which was first introduced in
gcc 4.3.
- The behavior of -Wshadow in
gcc 4.2.1 has been altered to behave
similarly to gcc 4.8 and not warn about
variables or parameters that shadow a global function unless the variable
or parameter is of type pointer-to-function.
The
__bounded__ attribute is used to type-check
functions whose parameters pass fixed-length buffers and their sizes. The
syntax for normal buffers is:
__attribute__((
__bounded__(
__buffer__,
buffer,
length)))
where
buffer contains the parameter number
(starting from 1) of the pointer to the buffer, and
length contains the parameter number of the
buffer length argument.
gcc will emit a warning if the length argument is a
constant larger than the actual size of the buffer. If the buffer is not a
statically declared array of fixed length, no warnings will be generated.
Refer to
memcpy(3) for an
example of a function with this check.
For checking strings, just use
__string__ instead
of
__buffer__:
__attribute__((
__bounded__(
__string__,
buffer,
length)))
In addition to the checks described above, this also tests if the
length argument was wrongly derived from a
sizeof(
void *)
operation.
strlcpy(3) is a good
example of a string function with this check.
If a function needs string checking like
__string__
but operates on element counts rather than buffer sizes, use
__wcstring__:
__attribute__((
__bounded__(
__wcstring__,
buffer,
count)))
An example of a string function with this check is
wcslcpy(3).
Some functions specify the length as two arguments: the number of elements and
the size of each element. In this case, use the
__size__ attribute:
__attribute__((
__bounded__(
__size__,
buffer,
nmemb,
size)))
where
buffer contains the parameter number of
the pointer to the buffer,
nmemb contains the
parameter number of the number of members, and
size has the parameter number of the size of
each element. The type checks performed by
__size__ are the same as the
__buffer__ attribute. See
fread(3) for an example of this
type of function.
If a function accepts a buffer parameter and specifies that it has to be of a
minimum length, the __minbytes__ attribute can be used:
__attribute__((
__bounded__(
__minbytes__,
buffer,
minsize)))
where
buffer contains the parameter number of
the pointer to the buffer, and
minsize
specifies the minimum number of bytes that the buffer should be.
ctime_r(3) is an example of
this type of function.
If
-Wbounded is specified with
-Wformat, additional checks are performed on
sscanf(3) format strings. The
‘
%s
’ fields are checked for incorrect
bound lengths by checking the size of the buffer associated with the format
argument.
gcc(1)
The
-Wbounded flag only works with statically
allocated fixed-size buffers. Since it is applied at compile-time, dynamically
allocated memory buffers and non-constant arguments are ignored.