glibc on Linux calls __longjmp_chk instead of longjmp (or _longjmp) when
_FORTIFY_SOURCE is defined. Ensure that an ASAN-instrumented program intercepts
this function when a system library calls it, otherwise the stack might remain
poisoned and result in CHECK failures and false positives.
Details
Diff Detail
- Repository
- rL LLVM
Event Timeline
lib/asan/asan_interceptors.cc | ||
---|---|---|
442 ↗ | (On Diff #96328) | Why not REAL(__longjmp_chk) ? |
lib/asan/asan_interceptors.h | ||
61 ↗ | (On Diff #96328) | && !SANITIZER_ANDROID |
test/asan/TestCases/Linux/longjmp_chk.c | ||
8 ↗ | (On Diff #96328) | Why do you split the test in two translation units? |
lib/asan/asan_interceptors.cc | ||
---|---|---|
442 ↗ | (On Diff #96328) | I was concerned that this would result in linking issues since __longjmp_chk is not a standard symbol (it is specific to glib). Furthermore, if an external application somehow tries to use the __longjmp_chk symbol when available (while we don't have glibc as C library), then it would call into a nullptr. It is possible that this concern is invalid though, what do you think? |
test/asan/TestCases/Linux/longjmp_chk.c | ||
8 ↗ | (On Diff #96328) | The essence is that one application is built with ASAN and another library is built without ASAN, but with _FORTIFY_SOURCE. Only this combination is causing issues, if both are built with ASAN or if both are built without FS, then there is no problem. |
lib/asan/asan_interceptors.cc | ||
---|---|---|
442 ↗ | (On Diff #96328) | I think it is still better to call __longjmp_chk to avoid weakening _FORTIFY_SOURCE. We already have quite a few dependencies like this, for example see the obstack interceptor in sanitizer_common - it is glibc-specific and can not be realistically implemented without REAL(obstack). |
test/asan/TestCases/Linux/longjmp_chk.c | ||
8 ↗ | (On Diff #96328) | Why is there no problem when both are built with fortify? I see that asan disables fortify on darwin, but probably not on linux. |
lib/asan/asan_interceptors.cc | ||
---|---|---|
442 ↗ | (On Diff #96328) | Ok, using __longjmp_chk seems to work, and if the symbol does not exist in the libc it still seems to build (I tried adding an interceptor for a non-existing __longjmp_chk2). Will fix this in the next revision. |
test/asan/TestCases/Linux/longjmp_chk.c | ||
8 ↗ | (On Diff #96328) | There can still be a problem even if both are built with fortify. Most important is that the non-ASAN code does a __longjmp_chk through the stack frame of the ASAN code. That's why two builds are needed, one with ASAN and one without. |
test/asan/TestCases/Linux/longjmp_chk.c | ||
---|---|---|
8 ↗ | (On Diff #96328) | Oh I get it, ASan instrumentation adds __asan_handle_no_return() before any call to longjmp, that's why the test needs to call longjmp from an uninstrumented code. |
Changes:
- Clarified why "msg" is passed in "callback"
- Clarified why the "external library" is built without ASAN
- Added !SANITIZER_ANDROID as suggested
Can I commit it now?