[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

llvm-svn: 318659
This commit is contained in:
Kostya Kortchinsky 2017-11-20 16:39:49 +00:00
parent 58acafc424
commit a695e418f3
1 changed files with 40 additions and 27 deletions

View File

@ -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
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 (&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);
}
}
extern "C" SANITIZER_WEAK_ATTRIBUTE
void android_set_abort_message(const char *);
void SetAbortMessage(const char *str) {
if (&android_set_abort_message)
android_set_abort_message(str);
}
# else
void AndroidLogInit() {}
static bool ShouldLogAfterPrintf() { return true; }
#endif // SANITIZER_ANDROID
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
}
void WriteOneLineToSyslog(const char *s) { syslog(LOG_INFO, "%s", s); }
void SetAbortMessage(const char *str) {}
# endif // SANITIZER_ANDROID
void LogMessageOnPrintf(const char *str) {
if (common_flags()->log_to_syslog && ShouldLogAfterPrintf())
WriteToSyslog(str);
}
#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);
}
#else
void SetAbortMessage(const char *str) {}
#endif
#endif // SANITIZER_LINUX
#endif // SANITIZER_LINUX
} // namespace __sanitizer