diff options
author | Mark Salyzyn <salyzyn@google.com> | 2015-03-13 06:50:32 -0700 |
---|---|---|
committer | Mark Salyzyn <salyzyn@google.com> | 2015-12-30 10:03:37 -0800 |
commit | a0140047525b3c12e9e64903fb7b85fea0d5a0f9 (patch) | |
tree | 33d70870f0748941a1bddb9b6fd118fcfb7f0df2 /liblog | |
parent | b5e821316da31d2f4d06c3dea74ed57098b69033 (diff) | |
download | core-a0140047525b3c12e9e64903fb7b85fea0d5a0f9.tar.gz core-a0140047525b3c12e9e64903fb7b85fea0d5a0f9.tar.bz2 core-a0140047525b3c12e9e64903fb7b85fea0d5a0f9.zip |
liblog: add __android_log_is_loggable checking to writer
Add __android_log_is_loggable() checking for all buffers except
LOG_ID_SECURITY. Return -EPERM if blocked. Since we are sniffing
the log tag, check validity and return -EINVAL.
NB: Try not to call __android_log_is_loggable() in native code within
a signal handler. Both here, and in the system properties, there
are locking paths that are not guaranteed to play well in that
environment. This has also been the case for the log writer path
even before this change. All attempts have been made to use trylock,
and to use a more expensive code path when contention occurs rather
than lead to deadlock.
Bug: 19544788
Bug: 26178938
Change-Id: I98738c662f6328189a6703251eb8721a05e956f9
Diffstat (limited to 'liblog')
-rw-r--r-- | liblog/logd_write.c | 91 |
1 files changed, 90 insertions, 1 deletions
diff --git a/liblog/logd_write.c b/liblog/logd_write.c index c2b0ec2ea..5406c50e1 100644 --- a/liblog/logd_write.c +++ b/liblog/logd_write.c @@ -39,6 +39,7 @@ #include <android/set_abort_message.h> #endif +#include <log/event_tag_map.h> #include <log/logd.h> #include <log/logger.h> #include <log/log_read.h> @@ -71,6 +72,11 @@ static void lock() pthread_mutex_lock(&log_init_lock); } +static int trylock() +{ + return pthread_mutex_trylock(&log_init_lock); +} + static void unlock() { pthread_mutex_unlock(&log_init_lock); @@ -79,6 +85,7 @@ static void unlock() #else /* !defined(_WIN32) */ #define lock() ((void)0) +#define trylock() (0) /* success */ #define unlock() ((void)0) #endif /* !defined(_WIN32) */ @@ -194,6 +201,9 @@ static int __write_to_log_daemon(log_id_t log_id, struct iovec *vec, size_t nr) last_pid = getpid(); } if (log_id == LOG_ID_SECURITY) { + if (vec[0].iov_len < 4) { + return -EINVAL; + } if ((last_uid != AID_SYSTEM) && (last_uid != AID_ROOT)) { uid_t uid = geteuid(); if ((uid != AID_SYSTEM) && (uid != AID_ROOT)) { @@ -207,9 +217,86 @@ static int __write_to_log_daemon(log_id_t log_id, struct iovec *vec, size_t nr) } } if (!__android_log_security()) { + atomic_store(&dropped_security, 0); + return -EPERM; + } + } else if (log_id == LOG_ID_EVENTS) { + static atomic_uintptr_t map; + int ret; + const char *tag; + EventTagMap *m, *f; + + if (vec[0].iov_len < 4) { + return -EINVAL; + } + + tag = NULL; + f = NULL; + m = (EventTagMap *)atomic_load(&map); + + if (!m) { + ret = trylock(); + m = (EventTagMap *)atomic_load(&map); /* trylock flush cache */ + if (!m) { + m = android_openEventTagMap(EVENT_TAG_MAP_FILE); + if (ret) { /* trylock failed, use local copy, mark for close */ + f = m; + } else { + if (!m) { /* One chance to open map file */ + m = (EventTagMap *)(uintptr_t)-1LL; + } + atomic_store(&map, (uintptr_t)m); + } + } + if (!ret) { /* trylock succeeded, unlock */ + unlock(); + } + } + if (m && (m != (EventTagMap *)(uintptr_t)-1LL)) { + tag = android_lookupEventTag( + m, + htole32(((uint32_t *)vec[0].iov_base)[0])); + } + ret = __android_log_is_loggable(ANDROID_LOG_INFO, + tag, + ANDROID_LOG_VERBOSE); + if (f) { /* local copy marked for close */ + android_closeEventTagMap(f); + } + if (!ret) { + return -EPERM; + } + } else { + /* Validate the incoming tag, tag content can not split across iovec */ + char prio = ANDROID_LOG_VERBOSE; + const char *tag = vec[0].iov_base; + size_t len = vec[0].iov_len; + if (!tag) { + len = 0; + } + if (len > 0) { + prio = *tag; + if (len > 1) { + --len; + ++tag; + } else { + len = vec[1].iov_len; + tag = ((const char *)vec[1].iov_base); + if (!tag) { + len = 0; + } + } + } + /* tag must be nul terminated */ + if (strnlen(tag, len) >= len) { + tag = NULL; + } + + if (!__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE)) { return -EPERM; } } + /* * struct { * // what we provide to pstore @@ -267,7 +354,9 @@ static int __write_to_log_daemon(log_id_t log_id, struct iovec *vec, size_t nr) } } snapshot = atomic_exchange_explicit(&dropped, 0, memory_order_relaxed); - if (snapshot) { + if (snapshot && __android_log_is_loggable(ANDROID_LOG_INFO, + "liblog", + ANDROID_LOG_VERBOSE)) { android_log_event_int_t buffer; header.id = LOG_ID_EVENTS; |