Merge "logd: liblog: logcat: Add LOG_ID_SECURITY"

This commit is contained in:
Mark Salyzyn 2015-12-11 17:33:33 +00:00 committed by Gerrit Code Review
commit 86052a5d4f
16 changed files with 304 additions and 53 deletions

View file

@ -604,7 +604,8 @@ typedef enum log_id {
LOG_ID_EVENTS = 2, LOG_ID_EVENTS = 2,
LOG_ID_SYSTEM = 3, LOG_ID_SYSTEM = 3,
LOG_ID_CRASH = 4, 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 #endif
LOG_ID_MAX LOG_ID_MAX

View file

@ -44,6 +44,8 @@ int __android_log_btwrite(int32_t tag, char type, const void *payload,
size_t len); size_t len);
int __android_log_bswrite(int32_t tag, const char *payload); 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 #ifdef __cplusplus
} }
#endif #endif

View file

@ -208,6 +208,7 @@ static const char *LOG_NAME[LOG_ID_MAX] = {
[LOG_ID_EVENTS] = "events", [LOG_ID_EVENTS] = "events",
[LOG_ID_SYSTEM] = "system", [LOG_ID_SYSTEM] = "system",
[LOG_ID_CRASH] = "crash", [LOG_ID_CRASH] = "crash",
[LOG_ID_SECURITY] = "security",
[LOG_ID_KERNEL] = "kernel", [LOG_ID_KERNEL] = "kernel",
}; };

View file

@ -84,7 +84,7 @@ static void unlock()
#endif /* !defined(_WIN32) */ #endif /* !defined(_WIN32) */
#if FAKE_LOG_DEVICE #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 #else
static int logd_fd = -1; static int logd_fd = -1;
static int pstore_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 uid_t last_uid = AID_ROOT; /* logd *always* starts up as AID_ROOT */
static pid_t last_pid = (pid_t) -1; static pid_t last_pid = (pid_t) -1;
static atomic_int_fast32_t dropped; static atomic_int_fast32_t dropped;
static atomic_int_fast32_t dropped_security;
if (!nr) { if (!nr) {
return -EINVAL; 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) { if (last_pid == (pid_t) -1) {
last_pid = getpid(); 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 { * struct {
* // what we provide to pstore * // 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); newVec[1].iov_len = sizeof(header);
if (logd_fd > 0) { 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) { if (snapshot) {
android_log_event_int_t buffer; 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)); ret = TEMP_FAILURE_RETRY(writev(logd_fd, newVec + 1, 2));
if (ret != (ssize_t)(sizeof(header) + sizeof(buffer))) { 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); ret -= sizeof(header);
} else if (ret == -EAGAIN) { } else if (ret == -EAGAIN) {
atomic_fetch_add_explicit(&dropped, 1, memory_order_relaxed); 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 #endif
@ -328,6 +370,7 @@ static const char *LOG_NAME[LOG_ID_MAX] = {
[LOG_ID_EVENTS] = "events", [LOG_ID_EVENTS] = "events",
[LOG_ID_SYSTEM] = "system", [LOG_ID_SYSTEM] = "system",
[LOG_ID_CRASH] = "crash", [LOG_ID_CRASH] = "crash",
[LOG_ID_SECURITY] = "security",
[LOG_ID_KERNEL] = "kernel", [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); 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 * 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 * for the general case where we're generating lists of stuff, but very

View file

@ -25,6 +25,7 @@
#include <log/logger.h> #include <log/logger.h>
#include <log/log_read.h> #include <log/log_read.h>
#include <log/logprint.h> #include <log/logprint.h>
#include <private/android_logger.h>
// enhanced version of LOG_FAILURE_RETRY to add support for EAGAIN and // 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 // 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); 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; static unsigned signaled;
log_time signal_time; log_time signal_time;
@ -651,7 +742,8 @@ TEST(liblog, android_logger_get_) {
EXPECT_EQ(id, android_logger_get_id(logger)); EXPECT_EQ(id, android_logger_get_id(logger));
EXPECT_LT(0, android_logger_get_log_size(logger)); EXPECT_LT(0, android_logger_get_log_size(logger));
/* crash buffer is allowed to be empty, that is actually healthy! */ /* 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_readable_size(logger));
} }
EXPECT_LT(0, android_logger_get_log_version(logger)); EXPECT_LT(0, android_logger_get_log_version(logger));

View file

@ -283,10 +283,12 @@ static void show_help(const char *cmd)
" --buffer_size=<size>\n" " --buffer_size=<size>\n"
" -L dump logs from prior to last reboot\n" " -L dump logs from prior to last reboot\n"
" --last\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" " -b <buffer> Request alternate ring buffer, 'main', 'system', 'radio',\n"
" --buffer=<buffer> 'events', 'crash' or 'all'. Multiple -b parameters are\n" " --buffer=<buffer> 'events', 'crash', 'default' or 'all'. Multiple -b\n"
" allowed and results are interleaved. The default is\n" " parameters are allowed and results are interleaved. The\n"
" -b main -b system -b crash.\n" " default is -b main -b system -b crash.\n"
" -B output the log in binary.\n" " -B output the log in binary.\n"
" --binary\n" " --binary\n"
" -S output statistics.\n" " -S output statistics.\n"
@ -696,16 +698,20 @@ int main(int argc, char **argv)
break; break;
case 'b': { case 'b': {
if (strcmp(optarg, "all") == 0) { if (strcmp(optarg, "default") == 0) {
while (devices) { for (int i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) {
dev = devices; switch (i) {
devices = dev->next; case LOG_ID_SECURITY:
delete dev; case LOG_ID_EVENTS:
} continue;
case LOG_ID_MAIN:
case LOG_ID_SYSTEM:
case LOG_ID_CRASH:
break;
default:
continue;
}
devices = dev = NULL;
g_devCount = 0;
for(int i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) {
const char *name = android_log_id_to_name((log_id_t)i); const char *name = android_log_id_to_name((log_id_t)i);
log_id_t log_id = android_name_to_log_id(name); log_id_t log_id = android_name_to_log_id(name);
@ -713,7 +719,58 @@ int main(int argc, char **argv)
continue; 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;
}
log_device_t* d = new log_device_t(name, false);
if (dev) {
dev->next = d;
dev = d;
} else {
devices = dev = d;
}
g_devCount++;
}
break;
}
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);
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;
}
bool binary = !strcmp(name, "events") ||
!strcmp(name, "security");
log_device_t* d = new log_device_t(name, binary); log_device_t* d = new log_device_t(name, binary);
if (dev) { if (dev) {
@ -727,14 +784,21 @@ int main(int argc, char **argv)
break; break;
} }
bool binary = strcmp(optarg, "events") == 0; bool binary = !(strcmp(optarg, "events") &&
strcmp(optarg, "security"));
if (devices) { if (devices) {
dev = devices; dev = devices;
while (dev->next) { while (dev->next) {
if (!strcmp(optarg, dev->device)) {
dev = NULL;
break;
}
dev = dev->next; dev = dev->next;
} }
dev->next = new log_device_t(optarg, binary); if (dev) {
dev->next = new log_device_t(optarg, binary);
}
} else { } else {
devices = new log_device_t(optarg, binary); devices = new log_device_t(optarg, binary);
} }
@ -1004,7 +1068,7 @@ int main(int argc, char **argv)
size_t len = 8192; size_t len = 8192;
char *buf; char *buf;
for(int retry = 32; for (int retry = 32;
(retry >= 0) && ((buf = new char [len])); (retry >= 0) && ((buf = new char [len]));
delete [] buf, buf = NULL, --retry) { delete [] buf, buf = NULL, --retry) {
if (getPruneList) { if (getPruneList) {
@ -1094,7 +1158,7 @@ int main(int argc, char **argv)
logcat_panic(false, "logcat read failure"); 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()) { if (android_name_to_log_id(d->device) == log_msg.id()) {
break; break;
} }

View file

@ -34,6 +34,7 @@
#include "CommandListener.h" #include "CommandListener.h"
#include "LogCommand.h" #include "LogCommand.h"
#include "LogUtils.h"
CommandListener::CommandListener(LogBuffer *buf, LogReader * /*reader*/, CommandListener::CommandListener(LogBuffer *buf, LogReader * /*reader*/,
LogListener * /*swl*/) : LogListener * /*swl*/) :

View file

@ -21,6 +21,7 @@
#include "LogCommand.h" #include "LogCommand.h"
#include "LogReader.h" #include "LogReader.h"
#include "LogTimes.h" #include "LogTimes.h"
#include "LogUtils.h"
FlushCommand::FlushCommand(LogReader &reader, FlushCommand::FlushCommand(LogReader &reader,
bool nonBlock, bool nonBlock,

View file

@ -199,22 +199,24 @@ int LogBuffer::log(log_id_t log_id, log_time realtime,
LogBufferElement *elem = new LogBufferElement(log_id, realtime, LogBufferElement *elem = new LogBufferElement(log_id, realtime,
uid, pid, tid, msg, len); uid, pid, tid, msg, len);
int prio = ANDROID_LOG_INFO; if (log_id != LOG_ID_SECURITY) {
const char *tag = NULL; int prio = ANDROID_LOG_INFO;
if (log_id == LOG_ID_EVENTS) { const char *tag = NULL;
tag = android::tagToName(elem->getTag()); if (log_id == LOG_ID_EVENTS) {
} else { tag = android::tagToName(elem->getTag());
prio = *msg; } else {
tag = msg + 1; prio = *msg;
} tag = msg + 1;
if (!__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE)) { }
// Log traffic received to total if (!__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE)) {
pthread_mutex_lock(&mLogElementsLock); // Log traffic received to total
stats.add(elem); pthread_mutex_lock(&mLogElementsLock);
stats.subtract(elem); stats.add(elem);
pthread_mutex_unlock(&mLogElementsLock); stats.subtract(elem);
delete elem; pthread_mutex_unlock(&mLogElementsLock);
return -EACCES; delete elem;
return -EACCES;
}
} }
pthread_mutex_lock(&mLogElementsLock); 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 // prune by worst offender by uid
bool hasBlacklist = mPrune.naughty(); bool hasBlacklist = (id != LOG_ID_SECURITY) && mPrune.naughty();
while (!clearAll && (pruneRows > 0)) { while (!clearAll && (pruneRows > 0)) {
// recalculate the worst offender on every batched pass // recalculate the worst offender on every batched pass
uid_t worst = (uid_t) -1; 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 whitelist = false;
bool hasWhitelist = mPrune.nice() && !clearAll; bool hasWhitelist = (id != LOG_ID_SECURITY) && mPrune.nice() && !clearAll;
it = mLogElements.begin(); it = mLogElements.begin();
while((pruneRows > 0) && (it != mLogElements.end())) { while((pruneRows > 0) && (it != mLogElements.end())) {
LogBufferElement *e = *it; LogBufferElement *e = *it;

View file

@ -51,7 +51,8 @@ LogBufferElement::~LogBufferElement() {
} }
uint32_t LogBufferElement::getTag() const { 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 0;
} }
return le32toh(reinterpret_cast<android_event_header_t *>(mMsg)->tag); return le32toh(reinterpret_cast<android_event_header_t *>(mMsg)->tag);
@ -158,7 +159,9 @@ size_t LogBufferElement::populateDroppedMessage(char *&buffer,
mDropped, (mDropped > 1) ? "s" : ""); mDropped, (mDropped > 1) ? "s" : "");
size_t hdrLen; 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); hdrLen = sizeof(android_log_event_string_t);
} else { } else {
hdrLen = 1 + sizeof(tag); hdrLen = 1 + sizeof(tag);
@ -172,7 +175,7 @@ size_t LogBufferElement::populateDroppedMessage(char *&buffer,
} }
size_t retval = hdrLen + len; 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 = android_log_event_string_t *event =
reinterpret_cast<android_log_event_string_t *>(buffer); reinterpret_cast<android_log_event_string_t *>(buffer);

View file

@ -22,6 +22,7 @@
#include <private/android_filesystem_config.h> #include <private/android_filesystem_config.h>
#include "LogCommand.h" #include "LogCommand.h"
#include "LogUtils.h"
LogCommand::LogCommand(const char *cmd) : FrameworkCommand(cmd) { LogCommand::LogCommand(const char *cmd) : FrameworkCommand(cmd) {
} }
@ -56,20 +57,18 @@ static bool groupIsLog(char *buf) {
return false; return false;
} }
bool clientHasLogCredentials(SocketClient * cli) { bool clientHasLogCredentials(uid_t uid, gid_t gid, pid_t pid) {
uid_t uid = cli->getUid(); if ((uid == AID_ROOT) || (uid == AID_SYSTEM) || (uid == AID_LOG)) {
if (uid == AID_ROOT) {
return true; return true;
} }
gid_t gid = cli->getGid();
if ((gid == AID_ROOT) || (gid == AID_SYSTEM) || (gid == AID_LOG)) { if ((gid == AID_ROOT) || (gid == AID_SYSTEM) || (gid == AID_LOG)) {
return true; return true;
} }
// FYI We will typically be here for 'adb logcat' // FYI We will typically be here for 'adb logcat'
char filename[256]; char filename[256];
snprintf(filename, sizeof(filename), "/proc/%u/status", cli->getPid()); snprintf(filename, sizeof(filename), "/proc/%u/status", pid);
bool ret; bool ret;
bool foundLog = false; bool foundLog = false;
@ -145,3 +144,7 @@ bool clientHasLogCredentials(SocketClient * cli) {
return ret; return ret;
} }
bool clientHasLogCredentials(SocketClient *cli) {
return clientHasLogCredentials(cli->getUid(), cli->getGid(), cli->getPid());
}

View file

@ -26,6 +26,4 @@ public:
virtual ~LogCommand() {} virtual ~LogCommand() {}
}; };
bool clientHasLogCredentials(SocketClient * cli);
#endif #endif

View file

@ -27,6 +27,7 @@
#include <private/android_logger.h> #include <private/android_logger.h>
#include "LogListener.h" #include "LogListener.h"
#include "LogUtils.h"
LogListener::LogListener(LogBuffer *buf, LogReader *reader) : LogListener::LogListener(LogBuffer *buf, LogReader *reader) :
SocketListener(getLogSocket(), false), SocketListener(getLogSocket(), false),
@ -92,6 +93,12 @@ bool LogListener::onDataAvailable(SocketClient *cli) {
return false; 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); char *msg = ((char *)buffer) + sizeof(android_log_header_t);
n -= sizeof(android_log_header_t); n -= sizeof(android_log_header_t);

View file

@ -85,7 +85,11 @@ void LogStatistics::add(LogBufferElement *element) {
uint32_t tag = element->getTag(); uint32_t tag = element->getTag();
if (tag) { 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(); uint32_t tag = element->getTag();
if (tag) { 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); 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; return output;
} }

View file

@ -397,6 +397,9 @@ class LogStatistics {
typedef LogHashtable<uint32_t, TagEntry> tagTable_t; typedef LogHashtable<uint32_t, TagEntry> tagTable_t;
tagTable_t tagTable; tagTable_t tagTable;
// security tag list
tagTable_t securityTagTable;
public: public:
LogStatistics(); LogStatistics();

View file

@ -20,6 +20,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <log/log.h> #include <log/log.h>
#include <sysutils/SocketClient.h>
// Hijack this header as a common include file used by most all sources // Hijack this header as a common include file used by most all sources
// to report some utilities defined here and there. // 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) { 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)> template <int (*cmp)(const char *l, const char *r, const size_t s)>