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
This commit is contained in:
parent
cb3e6ef154
commit
083b037c07
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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,20 @@ 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;
|
||||
}
|
||||
|
||||
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);
|
||||
log_id_t log_id = android_name_to_log_id(name);
|
||||
|
||||
|
@ -713,7 +719,58 @@ 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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
|
||||
#include "CommandListener.h"
|
||||
#include "LogCommand.h"
|
||||
#include "LogUtils.h"
|
||||
|
||||
CommandListener::CommandListener(LogBuffer *buf, LogReader * /*reader*/,
|
||||
LogListener * /*swl*/) :
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "LogCommand.h"
|
||||
#include "LogReader.h"
|
||||
#include "LogTimes.h"
|
||||
#include "LogUtils.h"
|
||||
|
||||
FlushCommand::FlushCommand(LogReader &reader,
|
||||
bool nonBlock,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -26,6 +26,4 @@ public:
|
|||
virtual ~LogCommand() {}
|
||||
};
|
||||
|
||||
bool clientHasLogCredentials(SocketClient * cli);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -397,6 +397,9 @@ class LogStatistics {
|
|||
typedef LogHashtable<uint32_t, TagEntry> tagTable_t;
|
||||
tagTable_t tagTable;
|
||||
|
||||
// security tag list
|
||||
tagTable_t securityTagTable;
|
||||
|
||||
public:
|
||||
LogStatistics();
|
||||
|
||||
|
|
|
@ -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)>
|
||||
|
|
Loading…
Reference in New Issue