summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Salyzyn <salyzyn@google.com>2015-12-04 10:59:45 -0800
committerMark Salyzyn <salyzyn@google.com>2015-12-08 16:46:29 -0800
commit083b037c0740ca00f72429e4457bfdd4b4d4dfa7 (patch)
tree6748f9f8bcaebd495df77604dfeba68e0b65b5be
parentcb3e6ef15459388fc8fee2b4a3157ff0eac0714a (diff)
downloadcore-083b037c0740ca00f72429e4457bfdd4b4d4dfa7.tar.gz
core-083b037c0740ca00f72429e4457bfdd4b4d4dfa7.tar.bz2
core-083b037c0740ca00f72429e4457bfdd4b4d4dfa7.zip
logd: liblog: logcat: Add LOG_ID_SECURITY
- Largish commit, buffer and access controls done together - Add LOG_ID_SECURITY binary content log - Add "default" meta buffer - allow LOG_ID_SECURITY only from AID_SYSTEM and AID_ROOT UID & GID - Use __android_log_security() to gate logging - Add __android_log_security_bwrite() native access to security logging. - Add liblog.__security_buffer end-to-end gTest Bug: 26029733 Change-Id: Ibcf5b4660c17c1aa6902c0d93f8ffd29c93d9a93
-rw-r--r--include/log/log.h3
-rw-r--r--include/log/logd.h2
-rw-r--r--liblog/log_read.c1
-rw-r--r--liblog/logd_write.c61
-rw-r--r--liblog/tests/liblog_test.cpp94
-rw-r--r--logcat/logcat.cpp96
-rw-r--r--logd/CommandListener.cpp1
-rw-r--r--logd/FlushCommand.cpp1
-rw-r--r--logd/LogBuffer.cpp38
-rw-r--r--logd/LogBufferElement.cpp9
-rw-r--r--logd/LogCommand.cpp13
-rw-r--r--logd/LogCommand.h2
-rw-r--r--logd/LogListener.cpp7
-rw-r--r--logd/LogStatistics.cpp17
-rw-r--r--logd/LogStatistics.h3
-rw-r--r--logd/LogUtils.h7
16 files changed, 303 insertions, 52 deletions
diff --git a/include/log/log.h b/include/log/log.h
index 619bf230c..3d9240dbb 100644
--- a/include/log/log.h
+++ b/include/log/log.h
@@ -604,7 +604,8 @@ typedef enum log_id {
LOG_ID_EVENTS = 2,
LOG_ID_SYSTEM = 3,
LOG_ID_CRASH = 4,
- LOG_ID_KERNEL = 5,
+ LOG_ID_SECURITY = 5,
+ LOG_ID_KERNEL = 6, /* place last, third-parties can not use it */
#endif
LOG_ID_MAX
diff --git a/include/log/logd.h b/include/log/logd.h
index 0fe515f2a..b7aedaff6 100644
--- a/include/log/logd.h
+++ b/include/log/logd.h
@@ -44,6 +44,8 @@ int __android_log_btwrite(int32_t tag, char type, const void *payload,
size_t len);
int __android_log_bswrite(int32_t tag, const char *payload);
+int __android_log_security_bwrite(int32_t tag, const void *payload, size_t len);
+
#ifdef __cplusplus
}
#endif
diff --git a/liblog/log_read.c b/liblog/log_read.c
index fb8675779..179f61115 100644
--- a/liblog/log_read.c
+++ b/liblog/log_read.c
@@ -208,6 +208,7 @@ static const char *LOG_NAME[LOG_ID_MAX] = {
[LOG_ID_EVENTS] = "events",
[LOG_ID_SYSTEM] = "system",
[LOG_ID_CRASH] = "crash",
+ [LOG_ID_SECURITY] = "security",
[LOG_ID_KERNEL] = "kernel",
};
diff --git a/liblog/logd_write.c b/liblog/logd_write.c
index 11c6d9cc8..c2b0ec2ea 100644
--- a/liblog/logd_write.c
+++ b/liblog/logd_write.c
@@ -84,7 +84,7 @@ static void unlock()
#endif /* !defined(_WIN32) */
#if FAKE_LOG_DEVICE
-static int log_fds[(int)LOG_ID_MAX] = { -1, -1, -1, -1, -1 };
+static int log_fds[(int)LOG_ID_MAX] = { -1, -1, -1, -1, -1, -1 };
#else
static int logd_fd = -1;
static int pstore_fd = -1;
@@ -181,6 +181,7 @@ static int __write_to_log_daemon(log_id_t log_id, struct iovec *vec, size_t nr)
static uid_t last_uid = AID_ROOT; /* logd *always* starts up as AID_ROOT */
static pid_t last_pid = (pid_t) -1;
static atomic_int_fast32_t dropped;
+ static atomic_int_fast32_t dropped_security;
if (!nr) {
return -EINVAL;
@@ -192,6 +193,23 @@ static int __write_to_log_daemon(log_id_t log_id, struct iovec *vec, size_t nr)
if (last_pid == (pid_t) -1) {
last_pid = getpid();
}
+ if (log_id == LOG_ID_SECURITY) {
+ if ((last_uid != AID_SYSTEM) && (last_uid != AID_ROOT)) {
+ uid_t uid = geteuid();
+ if ((uid != AID_SYSTEM) && (uid != AID_ROOT)) {
+ gid_t gid = getgid();
+ if ((gid != AID_SYSTEM) && (gid != AID_ROOT)) {
+ gid = getegid();
+ if ((gid != AID_SYSTEM) && (gid != AID_ROOT)) {
+ return -EPERM;
+ }
+ }
+ }
+ }
+ if (!__android_log_security()) {
+ return -EPERM;
+ }
+ }
/*
* struct {
* // what we provide to pstore
@@ -229,7 +247,26 @@ static int __write_to_log_daemon(log_id_t log_id, struct iovec *vec, size_t nr)
newVec[1].iov_len = sizeof(header);
if (logd_fd > 0) {
- int32_t snapshot = atomic_exchange_explicit(&dropped, 0, memory_order_relaxed);
+ int32_t snapshot = atomic_exchange_explicit(&dropped_security, 0,
+ memory_order_relaxed);
+ if (snapshot) {
+ android_log_event_int_t buffer;
+
+ header.id = LOG_ID_SECURITY;
+ buffer.header.tag = htole32(LIBLOG_LOG_TAG);
+ buffer.payload.type = EVENT_TYPE_INT;
+ buffer.payload.data = htole32(snapshot);
+
+ newVec[2].iov_base = &buffer;
+ newVec[2].iov_len = sizeof(buffer);
+
+ ret = TEMP_FAILURE_RETRY(writev(logd_fd, newVec + 1, 2));
+ if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) {
+ atomic_fetch_add_explicit(&dropped_security, snapshot,
+ memory_order_relaxed);
+ }
+ }
+ snapshot = atomic_exchange_explicit(&dropped, 0, memory_order_relaxed);
if (snapshot) {
android_log_event_int_t buffer;
@@ -243,7 +280,8 @@ static int __write_to_log_daemon(log_id_t log_id, struct iovec *vec, size_t nr)
ret = TEMP_FAILURE_RETRY(writev(logd_fd, newVec + 1, 2));
if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) {
- atomic_fetch_add_explicit(&dropped, snapshot, memory_order_relaxed);
+ atomic_fetch_add_explicit(&dropped, snapshot,
+ memory_order_relaxed);
}
}
}
@@ -315,6 +353,10 @@ static int __write_to_log_daemon(log_id_t log_id, struct iovec *vec, size_t nr)
ret -= sizeof(header);
} else if (ret == -EAGAIN) {
atomic_fetch_add_explicit(&dropped, 1, memory_order_relaxed);
+ if (log_id == LOG_ID_SECURITY) {
+ atomic_fetch_add_explicit(&dropped_security, 1,
+ memory_order_relaxed);
+ }
}
#endif
@@ -328,6 +370,7 @@ static const char *LOG_NAME[LOG_ID_MAX] = {
[LOG_ID_EVENTS] = "events",
[LOG_ID_SYSTEM] = "system",
[LOG_ID_CRASH] = "crash",
+ [LOG_ID_SECURITY] = "security",
[LOG_ID_KERNEL] = "kernel",
};
@@ -483,6 +526,18 @@ int __android_log_bwrite(int32_t tag, const void *payload, size_t len)
return write_to_log(LOG_ID_EVENTS, vec, 2);
}
+int __android_log_security_bwrite(int32_t tag, const void *payload, size_t len)
+{
+ struct iovec vec[2];
+
+ vec[0].iov_base = &tag;
+ vec[0].iov_len = sizeof(tag);
+ vec[1].iov_base = (void*)payload;
+ vec[1].iov_len = len;
+
+ return write_to_log(LOG_ID_SECURITY, vec, 2);
+}
+
/*
* Like __android_log_bwrite, but takes the type as well. Doesn't work
* for the general case where we're generating lists of stuff, but very
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index 597d8f694..1046d25d4 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -25,6 +25,7 @@
#include <log/logger.h>
#include <log/log_read.h>
#include <log/logprint.h>
+#include <private/android_logger.h>
// enhanced version of LOG_FAILURE_RETRY to add support for EAGAIN and
// non-syscall libs. Since we are only using this in the emergency of
@@ -201,6 +202,96 @@ TEST(liblog, __security) {
property_set(persist_key, persist);
}
+TEST(liblog, __security_buffer) {
+ struct logger_list *logger_list;
+ android_event_long_t buffer;
+
+ static const char persist_key[] = "persist.logd.security";
+ char persist[PROP_VALUE_MAX];
+ bool set_persist = false;
+ bool allow_security = false;
+
+ if (__android_log_security()) {
+ allow_security = true;
+ } else {
+ property_get(persist_key, persist, "");
+ if (strcasecmp(persist, "true")) {
+ property_set(persist_key, "TRUE");
+ if (__android_log_security()) {
+ allow_security = true;
+ set_persist = true;
+ } else {
+ property_set(persist_key, persist);
+ }
+ }
+ }
+
+ if (!allow_security) {
+ fprintf(stderr, "WARNING: "
+ "security buffer disabled, bypassing end-to-end test\n");
+
+ log_time ts(CLOCK_MONOTONIC);
+
+ buffer.type = EVENT_TYPE_LONG;
+ buffer.data = *(static_cast<uint64_t *>((void *)&ts));
+
+ // expect failure!
+ ASSERT_GE(0, __android_log_security_bwrite(0, &buffer, sizeof(buffer)));
+
+ return;
+ }
+
+ pid_t pid = getpid();
+
+ ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
+ LOG_ID_SECURITY, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK,
+ 1000, pid)));
+
+ log_time ts(CLOCK_MONOTONIC);
+
+ buffer.type = EVENT_TYPE_LONG;
+ buffer.data = *(static_cast<uint64_t *>((void *)&ts));
+
+ ASSERT_LT(0, __android_log_security_bwrite(0, &buffer, sizeof(buffer)));
+ usleep(1000000);
+
+ int count = 0;
+
+ for (;;) {
+ log_msg log_msg;
+ if (android_logger_list_read(logger_list, &log_msg) <= 0) {
+ break;
+ }
+
+ ASSERT_EQ(log_msg.entry.pid, pid);
+
+ if ((log_msg.entry.len != (4 + 1 + 8))
+ || (log_msg.id() != LOG_ID_SECURITY)) {
+ continue;
+ }
+
+ char *eventData = log_msg.msg();
+
+ if (eventData[4] != EVENT_TYPE_LONG) {
+ continue;
+ }
+
+ log_time tx(eventData + 4 + 1);
+ if (ts == tx) {
+ ++count;
+ }
+ }
+
+ if (set_persist) {
+ property_set(persist_key, persist);
+ }
+
+ android_logger_list_close(logger_list);
+
+ EXPECT_EQ(1, count);
+
+}
+
static unsigned signaled;
log_time signal_time;
@@ -650,7 +741,8 @@ TEST(liblog, android_logger_get_) {
EXPECT_EQ(id, android_logger_get_id(logger));
EXPECT_LT(0, android_logger_get_log_size(logger));
/* crash buffer is allowed to be empty, that is actually healthy! */
- if (android_logger_get_log_readable_size(logger) || strcmp("crash", name)) {
+ if (android_logger_get_log_readable_size(logger) ||
+ (strcmp("crash", name) && strcmp("security", name))) {
EXPECT_LT(0, android_logger_get_log_readable_size(logger));
}
EXPECT_LT(0, android_logger_get_log_version(logger));
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index 059916e78..8ceeba5fc 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -283,10 +283,12 @@ static void show_help(const char *cmd)
" --buffer_size=<size>\n"
" -L dump logs from prior to last reboot\n"
" --last\n"
+ // Leave security (Device Owner only installations) and
+ // kernel (userdebug and eng) buffers undocumented.
" -b <buffer> Request alternate ring buffer, 'main', 'system', 'radio',\n"
- " --buffer=<buffer> 'events', 'crash' or 'all'. Multiple -b parameters are\n"
- " allowed and results are interleaved. The default is\n"
- " -b main -b system -b crash.\n"
+ " --buffer=<buffer> 'events', 'crash', 'default' or 'all'. Multiple -b\n"
+ " parameters are allowed and results are interleaved. The\n"
+ " default is -b main -b system -b crash.\n"
" -B output the log in binary.\n"
" --binary\n"
" -S output statistics.\n"
@@ -696,16 +698,56 @@ int main(int argc, char **argv)
break;
case 'b': {
- if (strcmp(optarg, "all") == 0) {
- while (devices) {
- dev = devices;
- devices = dev->next;
- delete dev;
+ if (strcmp(optarg, "default") == 0) {
+ for (int i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) {
+ switch (i) {
+ case LOG_ID_SECURITY:
+ case LOG_ID_EVENTS:
+ continue;
+ case LOG_ID_MAIN:
+ case LOG_ID_SYSTEM:
+ case LOG_ID_CRASH:
+ break;
+ default:
+ continue;
+ }
+
+ const char *name = android_log_id_to_name((log_id_t)i);
+ log_id_t log_id = android_name_to_log_id(name);
+
+ if (log_id != (log_id_t)i) {
+ continue;
+ }
+
+ bool found = false;
+ for (dev = devices; dev; dev = dev->next) {
+ if (!strcmp(optarg, dev->device)) {
+ found = true;
+ break;
+ }
+ if (!dev->next) {
+ break;
+ }
+ }
+ if (found) {
+ break;
+ }
+
+ log_device_t* d = new log_device_t(name, false);
+
+ if (dev) {
+ dev->next = d;
+ dev = d;
+ } else {
+ devices = dev = d;
+ }
+ g_devCount++;
}
+ break;
+ }
- devices = dev = NULL;
- g_devCount = 0;
- for(int i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) {
+ if (strcmp(optarg, "all") == 0) {
+ for (int i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) {
const char *name = android_log_id_to_name((log_id_t)i);
log_id_t log_id = android_name_to_log_id(name);
@@ -713,7 +755,22 @@ int main(int argc, char **argv)
continue;
}
- bool binary = strcmp(name, "events") == 0;
+ bool found = false;
+ for (dev = devices; dev; dev = dev->next) {
+ if (!strcmp(optarg, dev->device)) {
+ found = true;
+ break;
+ }
+ if (!dev->next) {
+ break;
+ }
+ }
+ if (found) {
+ break;
+ }
+
+ bool binary = !strcmp(name, "events") ||
+ !strcmp(name, "security");
log_device_t* d = new log_device_t(name, binary);
if (dev) {
@@ -727,14 +784,21 @@ int main(int argc, char **argv)
break;
}
- bool binary = strcmp(optarg, "events") == 0;
+ bool binary = !(strcmp(optarg, "events") &&
+ strcmp(optarg, "security"));
if (devices) {
dev = devices;
while (dev->next) {
+ if (!strcmp(optarg, dev->device)) {
+ dev = NULL;
+ break;
+ }
dev = dev->next;
}
- dev->next = new log_device_t(optarg, binary);
+ if (dev) {
+ dev->next = new log_device_t(optarg, binary);
+ }
} else {
devices = new log_device_t(optarg, binary);
}
@@ -1004,7 +1068,7 @@ int main(int argc, char **argv)
size_t len = 8192;
char *buf;
- for(int retry = 32;
+ for (int retry = 32;
(retry >= 0) && ((buf = new char [len]));
delete [] buf, buf = NULL, --retry) {
if (getPruneList) {
@@ -1094,7 +1158,7 @@ int main(int argc, char **argv)
logcat_panic(false, "logcat read failure");
}
- for(d = devices; d; d = d->next) {
+ for (d = devices; d; d = d->next) {
if (android_name_to_log_id(d->device) == log_msg.id()) {
break;
}
diff --git a/logd/CommandListener.cpp b/logd/CommandListener.cpp
index c45111aa5..e10335916 100644
--- a/logd/CommandListener.cpp
+++ b/logd/CommandListener.cpp
@@ -34,6 +34,7 @@
#include "CommandListener.h"
#include "LogCommand.h"
+#include "LogUtils.h"
CommandListener::CommandListener(LogBuffer *buf, LogReader * /*reader*/,
LogListener * /*swl*/) :
diff --git a/logd/FlushCommand.cpp b/logd/FlushCommand.cpp
index bf650cdaa..cb3d1c278 100644
--- a/logd/FlushCommand.cpp
+++ b/logd/FlushCommand.cpp
@@ -21,6 +21,7 @@
#include "LogCommand.h"
#include "LogReader.h"
#include "LogTimes.h"
+#include "LogUtils.h"
FlushCommand::FlushCommand(LogReader &reader,
bool nonBlock,
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index 6770bb7f2..3ce6b61e0 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -199,22 +199,24 @@ int LogBuffer::log(log_id_t log_id, log_time realtime,
LogBufferElement *elem = new LogBufferElement(log_id, realtime,
uid, pid, tid, msg, len);
- int prio = ANDROID_LOG_INFO;
- const char *tag = NULL;
- if (log_id == LOG_ID_EVENTS) {
- tag = android::tagToName(elem->getTag());
- } else {
- prio = *msg;
- tag = msg + 1;
- }
- if (!__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE)) {
- // Log traffic received to total
- pthread_mutex_lock(&mLogElementsLock);
- stats.add(elem);
- stats.subtract(elem);
- pthread_mutex_unlock(&mLogElementsLock);
- delete elem;
- return -EACCES;
+ if (log_id != LOG_ID_SECURITY) {
+ int prio = ANDROID_LOG_INFO;
+ const char *tag = NULL;
+ if (log_id == LOG_ID_EVENTS) {
+ tag = android::tagToName(elem->getTag());
+ } else {
+ prio = *msg;
+ tag = msg + 1;
+ }
+ if (!__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE)) {
+ // Log traffic received to total
+ pthread_mutex_lock(&mLogElementsLock);
+ stats.add(elem);
+ stats.subtract(elem);
+ pthread_mutex_unlock(&mLogElementsLock);
+ delete elem;
+ return -EACCES;
+ }
}
pthread_mutex_lock(&mLogElementsLock);
@@ -484,7 +486,7 @@ bool LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) {
}
// prune by worst offender by uid
- bool hasBlacklist = mPrune.naughty();
+ bool hasBlacklist = (id != LOG_ID_SECURITY) && mPrune.naughty();
while (!clearAll && (pruneRows > 0)) {
// recalculate the worst offender on every batched pass
uid_t worst = (uid_t) -1;
@@ -654,7 +656,7 @@ bool LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) {
}
bool whitelist = false;
- bool hasWhitelist = mPrune.nice() && !clearAll;
+ bool hasWhitelist = (id != LOG_ID_SECURITY) && mPrune.nice() && !clearAll;
it = mLogElements.begin();
while((pruneRows > 0) && (it != mLogElements.end())) {
LogBufferElement *e = *it;
diff --git a/logd/LogBufferElement.cpp b/logd/LogBufferElement.cpp
index c4c302b0a..f92a085cb 100644
--- a/logd/LogBufferElement.cpp
+++ b/logd/LogBufferElement.cpp
@@ -51,7 +51,8 @@ LogBufferElement::~LogBufferElement() {
}
uint32_t LogBufferElement::getTag() const {
- if ((mLogId != LOG_ID_EVENTS) || !mMsg || (mMsgLen < sizeof(uint32_t))) {
+ if (((mLogId != LOG_ID_EVENTS) && (mLogId != LOG_ID_SECURITY)) ||
+ !mMsg || (mMsgLen < sizeof(uint32_t))) {
return 0;
}
return le32toh(reinterpret_cast<android_event_header_t *>(mMsg)->tag);
@@ -158,7 +159,9 @@ size_t LogBufferElement::populateDroppedMessage(char *&buffer,
mDropped, (mDropped > 1) ? "s" : "");
size_t hdrLen;
- if (mLogId == LOG_ID_EVENTS) {
+ // LOG_ID_SECURITY not strictly needed since spam filter not activated,
+ // but required for accuracy.
+ if ((mLogId == LOG_ID_EVENTS) || (mLogId == LOG_ID_SECURITY)) {
hdrLen = sizeof(android_log_event_string_t);
} else {
hdrLen = 1 + sizeof(tag);
@@ -172,7 +175,7 @@ size_t LogBufferElement::populateDroppedMessage(char *&buffer,
}
size_t retval = hdrLen + len;
- if (mLogId == LOG_ID_EVENTS) {
+ if ((mLogId == LOG_ID_EVENTS) || (mLogId == LOG_ID_SECURITY)) {
android_log_event_string_t *event =
reinterpret_cast<android_log_event_string_t *>(buffer);
diff --git a/logd/LogCommand.cpp b/logd/LogCommand.cpp
index 6d0e92e4e..3b1757656 100644
--- a/logd/LogCommand.cpp
+++ b/logd/LogCommand.cpp
@@ -22,6 +22,7 @@
#include <private/android_filesystem_config.h>
#include "LogCommand.h"
+#include "LogUtils.h"
LogCommand::LogCommand(const char *cmd) : FrameworkCommand(cmd) {
}
@@ -56,20 +57,18 @@ static bool groupIsLog(char *buf) {
return false;
}
-bool clientHasLogCredentials(SocketClient * cli) {
- uid_t uid = cli->getUid();
- if (uid == AID_ROOT) {
+bool clientHasLogCredentials(uid_t uid, gid_t gid, pid_t pid) {
+ if ((uid == AID_ROOT) || (uid == AID_SYSTEM) || (uid == AID_LOG)) {
return true;
}
- gid_t gid = cli->getGid();
if ((gid == AID_ROOT) || (gid == AID_SYSTEM) || (gid == AID_LOG)) {
return true;
}
// FYI We will typically be here for 'adb logcat'
char filename[256];
- snprintf(filename, sizeof(filename), "/proc/%u/status", cli->getPid());
+ snprintf(filename, sizeof(filename), "/proc/%u/status", pid);
bool ret;
bool foundLog = false;
@@ -145,3 +144,7 @@ bool clientHasLogCredentials(SocketClient * cli) {
return ret;
}
+
+bool clientHasLogCredentials(SocketClient *cli) {
+ return clientHasLogCredentials(cli->getUid(), cli->getGid(), cli->getPid());
+}
diff --git a/logd/LogCommand.h b/logd/LogCommand.h
index e3b96a2b7..c944478f8 100644
--- a/logd/LogCommand.h
+++ b/logd/LogCommand.h
@@ -26,6 +26,4 @@ public:
virtual ~LogCommand() {}
};
-bool clientHasLogCredentials(SocketClient * cli);
-
#endif
diff --git a/logd/LogListener.cpp b/logd/LogListener.cpp
index b29f5ab92..9bbf9e84b 100644
--- a/logd/LogListener.cpp
+++ b/logd/LogListener.cpp
@@ -27,6 +27,7 @@
#include <private/android_logger.h>
#include "LogListener.h"
+#include "LogUtils.h"
LogListener::LogListener(LogBuffer *buf, LogReader *reader) :
SocketListener(getLogSocket(), false),
@@ -92,6 +93,12 @@ bool LogListener::onDataAvailable(SocketClient *cli) {
return false;
}
+ if ((header->id == LOG_ID_SECURITY) &&
+ (!__android_log_security() ||
+ !clientHasLogCredentials(cred->uid, cred->gid, cred->pid))) {
+ return false;
+ }
+
char *msg = ((char *)buffer) + sizeof(android_log_header_t);
n -= sizeof(android_log_header_t);
diff --git a/logd/LogStatistics.cpp b/logd/LogStatistics.cpp
index 416edd8a1..bf0e30b09 100644
--- a/logd/LogStatistics.cpp
+++ b/logd/LogStatistics.cpp
@@ -85,7 +85,11 @@ void LogStatistics::add(LogBufferElement *element) {
uint32_t tag = element->getTag();
if (tag) {
- tagTable.add(tag, element);
+ if (log_id == LOG_ID_SECURITY) {
+ securityTagTable.add(tag, element);
+ } else {
+ tagTable.add(tag, element);
+ }
}
}
@@ -113,7 +117,11 @@ void LogStatistics::subtract(LogBufferElement *element) {
uint32_t tag = element->getTag();
if (tag) {
- tagTable.subtract(tag, element);
+ if (log_id == LOG_ID_SECURITY) {
+ securityTagTable.subtract(tag, element);
+ } else {
+ tagTable.subtract(tag, element);
+ }
}
}
@@ -468,6 +476,11 @@ std::string LogStatistics::format(uid_t uid, unsigned int logMask) const {
output += tagTable.format(*this, uid, name, LOG_ID_EVENTS);
}
+ if (enable && (logMask & (1 << LOG_ID_SECURITY))) {
+ name = "Chattiest security log buffer TAGs:";
+ output += securityTagTable.format(*this, uid, name, LOG_ID_SECURITY);
+ }
+
return output;
}
diff --git a/logd/LogStatistics.h b/logd/LogStatistics.h
index 28810d9d5..8558b0671 100644
--- a/logd/LogStatistics.h
+++ b/logd/LogStatistics.h
@@ -397,6 +397,9 @@ class LogStatistics {
typedef LogHashtable<uint32_t, TagEntry> tagTable_t;
tagTable_t tagTable;
+ // security tag list
+ tagTable_t securityTagTable;
+
public:
LogStatistics();
diff --git a/logd/LogUtils.h b/logd/LogUtils.h
index 533eb1c5f..b591f2892 100644
--- a/logd/LogUtils.h
+++ b/logd/LogUtils.h
@@ -20,6 +20,7 @@
#include <sys/types.h>
#include <log/log.h>
+#include <sysutils/SocketClient.h>
// Hijack this header as a common include file used by most all sources
// to report some utilities defined here and there.
@@ -38,8 +39,12 @@ const char *tagToName(uint32_t tag);
}
+// Furnished in LogCommand.cpp
+bool clientHasLogCredentials(uid_t uid, gid_t gid, pid_t pid);
+bool clientHasLogCredentials(SocketClient *cli);
+
static inline bool worstUidEnabledForLogid(log_id_t id) {
- return (id != LOG_ID_CRASH) && (id != LOG_ID_KERNEL) && (id != LOG_ID_EVENTS);
+ return (id == LOG_ID_MAIN) || (id == LOG_ID_SYSTEM) || (id == LOG_ID_RADIO);
}
template <int (*cmp)(const char *l, const char *r, const size_t s)>