summaryrefslogtreecommitdiffstats
path: root/liblog
diff options
context:
space:
mode:
authorMark Salyzyn <salyzyn@google.com>2015-03-13 06:50:32 -0700
committerMark Salyzyn <salyzyn@google.com>2015-12-30 10:03:37 -0800
commita0140047525b3c12e9e64903fb7b85fea0d5a0f9 (patch)
tree33d70870f0748941a1bddb9b6fd118fcfb7f0df2 /liblog
parentb5e821316da31d2f4d06c3dea74ed57098b69033 (diff)
downloadsystem_core-a0140047525b3c12e9e64903fb7b85fea0d5a0f9.tar.gz
system_core-a0140047525b3c12e9e64903fb7b85fea0d5a0f9.tar.bz2
system_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.c91
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;