diff options
author | Kostya Kortchinsky <kostyak@google.com> | 2017-11-20 16:39:49 +0000 |
---|---|---|
committer | Kostya Kortchinsky <kostyak@google.com> | 2017-11-20 16:39:49 +0000 |
commit | 7a9c646ba3f2dbf09bc4c0ec073a0530e1fc01a3 (patch) | |
tree | b624fdae4d00c5317ad52fcb25f6346db46ccf28 | |
parent | cd5a55a06385bd71911e4fe87c32433b60493df0 (diff) |
[sanitizer] New attempt at using runtime checks for Android logging
Summary:
This is a second attempt after D40100 induced racey crashes with ASan
(due to `__android_log_write` and the `strncpy` interceptor on API >= 21).
This new version checks the runtime API level to be <= `ANDROID_KITKAT` for
the use of `__android_log_write`, otherwise we use `syslog`, which should
conform with the previous behavior.
Unfortunately despite numerous efforts I couldn't reproduce the original
crashes in my environments so I couldn't test that the fix was actually
preventing crashes.
Reviewers: eugenis
Reviewed By: eugenis
Subscribers: llvm-commits, srhines, kubamracek
Differential Revision: https://reviews.llvm.org/D40149
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@318659 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/sanitizer_common/sanitizer_linux_libcdep.cc | 67 |
1 files changed, 40 insertions, 27 deletions
diff --git a/lib/sanitizer_common/sanitizer_linux_libcdep.cc b/lib/sanitizer_common/sanitizer_linux_libcdep.cc index b298fe4c5..6fc1396ab 100644 --- a/lib/sanitizer_common/sanitizer_linux_libcdep.cc +++ b/lib/sanitizer_common/sanitizer_linux_libcdep.cc @@ -48,10 +48,6 @@ #include <android/api-level.h> #endif -#if SANITIZER_ANDROID && __ANDROID_API__ < 21 -#include <android/log.h> -#endif - #if !SANITIZER_ANDROID #include <elf.h> #include <unistd.h> @@ -536,12 +532,9 @@ uptr GetRSS() { return rss * GetPageSizeCached(); } -// 64-bit Android targets don't provide the deprecated __android_log_write. -// Starting with the L release, syslog() works and is preferable to -// __android_log_write. #if SANITIZER_LINUX -#if SANITIZER_ANDROID +# if SANITIZER_ANDROID static atomic_uint8_t android_log_initialized; void AndroidLogInit() { @@ -552,35 +545,55 @@ void AndroidLogInit() { static bool ShouldLogAfterPrintf() { return atomic_load(&android_log_initialized, memory_order_acquire); } -#else -void AndroidLogInit() {} -static bool ShouldLogAfterPrintf() { return true; } -#endif // SANITIZER_ANDROID +extern "C" SANITIZER_WEAK_ATTRIBUTE +int async_safe_write_log(int pri, const char* tag, const char* msg); +extern "C" SANITIZER_WEAK_ATTRIBUTE +int __android_log_write(int prio, const char* tag, const char* msg); + +// ANDROID_LOG_INFO is 4, but can't be resolved at runtime. +#define SANITIZER_ANDROID_LOG_INFO 4 +// async_safe_write_log is a new public version of __libc_write_log that is +// used behind syslog. It is preferable to syslog as it will not do any dynamic +// memory allocation or formatting. +// If the function is not available, syslog is preferred for L+ (it was broken +// pre-L) as __android_log_write triggers a racey behavior with the strncpy +// interceptor. Fallback to __android_log_write pre-L. void WriteOneLineToSyslog(const char *s) { -#if SANITIZER_ANDROID &&__ANDROID_API__ < 21 - __android_log_write(ANDROID_LOG_INFO, NULL, s); -#else - syslog(LOG_INFO, "%s", s); -#endif + if (&async_safe_write_log) { + async_safe_write_log(SANITIZER_ANDROID_LOG_INFO, GetProcessName(), s); + } else if (AndroidGetApiLevel() > ANDROID_KITKAT) { + syslog(LOG_INFO, "%s", s); + } else { + CHECK(&__android_log_write); + __android_log_write(SANITIZER_ANDROID_LOG_INFO, nullptr, s); + } } -void LogMessageOnPrintf(const char *str) { - if (common_flags()->log_to_syslog && ShouldLogAfterPrintf()) - WriteToSyslog(str); -} +extern "C" SANITIZER_WEAK_ATTRIBUTE +void android_set_abort_message(const char *); -#if SANITIZER_ANDROID -extern "C" __attribute__((weak)) void android_set_abort_message(const char *); void SetAbortMessage(const char *str) { - if (&android_set_abort_message) android_set_abort_message(str); + if (&android_set_abort_message) + android_set_abort_message(str); } -#else +# else +void AndroidLogInit() {} + +static bool ShouldLogAfterPrintf() { return true; } + +void WriteOneLineToSyslog(const char *s) { syslog(LOG_INFO, "%s", s); } + void SetAbortMessage(const char *str) {} -#endif +# endif // SANITIZER_ANDROID + +void LogMessageOnPrintf(const char *str) { + if (common_flags()->log_to_syslog && ShouldLogAfterPrintf()) + WriteToSyslog(str); +} -#endif // SANITIZER_LINUX +#endif // SANITIZER_LINUX } // namespace __sanitizer |