This is an archive of the discontinued LLVM Phabricator instance.

[ASAN] Add interceptor for __longjmp_chk
ClosedPublic

Authored by Lekensteyn on Apr 23 2017, 3:44 PM.

Details

Summary

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.

Fixes https://github.com/google/sanitizers/issues/721

Diff Detail

Repository
rL LLVM

Event Timeline

Lekensteyn created this revision.Apr 23 2017, 3:44 PM
eugenis added inline comments.Apr 26 2017, 1:41 PM
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?
If it is to prevent "msg" from being optimized out, a call to __asan_address_is_poisoned would have the same effect.

Lekensteyn added inline comments.Apr 26 2017, 1:50 PM
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.

eugenis added inline comments.Apr 26 2017, 2:00 PM
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.

Lekensteyn added inline comments.Apr 26 2017, 2:40 PM
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.

eugenis added inline comments.Apr 26 2017, 3:12 PM
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.

Lekensteyn updated this revision to Diff 97305.May 1 2017, 10:10 AM
Lekensteyn marked 9 inline comments as done.

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?

eugenis accepted this revision.May 1 2017, 10:52 AM

LGTM

This revision is now accepted and ready to land.May 1 2017, 10:52 AM
This revision was automatically updated to reflect the committed changes.