When fortify is used with msan it will cause msan false positives.
% clang test.c -fsanitize=memory -O3 && ./a.out
% clang test.c -fsanitize=memory -D_FORTIFY_SOURCE=2 -O3 && ./a.out
Uninitialized bytes in __interceptor_strlen at offset 0 inside [0x7ffe259e4d20, 6)
==26297==WARNING: MemorySanitizer: use-of-uninitialized-value
#0 0x4869cc in main
With asan, this will not cause false positives, but may case false negatives.
char *T = "hello";
volatile int sink;
int main(int argc, char **argv)
int n = argc == 1 ? 4 : atoi(argv);
char *text = (char*)malloc(n);
sprintf(text, "%s", T);
sink = text;
% clang asan-test.c -fsanitize=address -O3 && ./a.out 2>&1 | grep ERROR
==27843==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000fbf4 at pc 0x0000004a7cb0 bp 0x7ffe22795bc0 sp 0x7ffe22795370
% clang asan-test.c -fsanitize=address -O3 -D_FORTIFY_SOURCE=2 && ./a.out 2>&1 | grep ERROR
same with tsan.
This is happening because fortify replaces libc functions (e.g. sprintf)
with its own variants (__sprintf_chk) and the sanitizers don't know about these variants.
supporting fortify in *san makes little sense because fortify does not add anything to the sanitizers and it will only increase the complexity.
So, the better way is to warn the user that the sanitizers and fortify are incompatible.
Florian suggested that the simplest way to warn is to modify the glibc headers
to check if fortify and one of the sanitizers is enabled.
Note that gcc and clang use different ways to tell that a sanitizer is on
(macros in gcc, __has_feature in clang)
Will you consider implementing this?
The most natural fix seems to be inside the glibc headers,
but if you are not planing to do it any time soon we'll have some
kind of workaround in clang or *san run-times.
Created attachment 9480 [details]
Something like this? I wonder how can we test this patch. Can we rely on GCC is recent enough to support -fsanitize=address?
(In reply to Maxim Ostapenko from comment #2)
> Created attachment 9480 [details]
> Untested patch.
> Something like this? I wonder how can we test this patch. Can we rely on GCC
> is recent enough to support -fsanitize=address?
Or perhaps we can define __SANITIZE_ADDRESS__ manually and check the warning?
Looks great (untested).
IMHO we can rely on recent-enough gcc, but the actual glibc folks would know better.
These days, _FORTIFY_SOURCE covers additional aspects (including enhanced compile-time type safety), not just buffer-length checking. I'm not sure what the current expectations regarding the sanitizers are. Is it the norm to compile twice, for production (with -D_FORTIFY_SOURCE=2), and for special testing with the required sanitizer?
I'm asking this because if there is just a single compile (say with Address Sanitizer), then I think we need to make the enhanced type safety (and other goodies) available to sanitizer users as well.
(In reply to Florian Weimer from comment #5)
> These days, _FORTIFY_SOURCE covers additional aspects (including enhanced
> compile-time type safety), not just buffer-length checking. I'm not sure
> what the current expectations regarding the sanitizers are. Is it the norm
> to compile twice, for production (with -D_FORTIFY_SOURCE=2), and for special
> testing with the required sanitizer?
> I'm asking this because if there is just a single compile (say with Address
> Sanitizer), then I think we need to make the enhanced type safety (and other
> goodies) available to sanitizer users as well.
Typically, asan/msan/tsan are used as testing tools, not for production build.
And anyway, there are 3 of them, so you can't have a single build anyway.
asan is sometimes used for production (e.g. on a small subset of servers)
to find the last remaining bugs.
Very rarely asan is used as a hardened production build,
but the security value of this is disputable (at least, with the current implementation).
Can you give examples (or point to docs) of the "additional aspects" of fortify?
If they fit well into asan's architecture we will certainly want to either
have them duplicated in asan or make asan work with those parts of fortify.
The traditional parts of fortify (where it replaces foo with foo_chk)
are *san-hostile at the moment.
(In reply to Kostya Serebryany from comment #6)
> Can you give examples (or point to docs) of the "additional aspects" of
An example is the argument type checking for open/openat, in io/bits/fcntl2.h. I expect more things like this in the future. Some of them do not inherently conflict with the ASan interceptors, but many others will (like variable argument list length checking for printf and similar functions).