Loading include/log/log.h +2 −1 Original line number Diff line number Diff line Loading @@ -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 Loading include/log/logd.h +2 −0 Original line number Diff line number Diff line Loading @@ -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 Loading liblog/log_read.c +1 −0 Original line number Diff line number Diff line Loading @@ -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", }; Loading liblog/logd_write.c +58 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading @@ -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 Loading Loading @@ -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; Loading @@ -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); } } } Loading Loading @@ -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 Loading @@ -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", }; Loading Loading @@ -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 Loading liblog/tests/liblog_test.cpp +93 −1 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -651,7 +742,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)); Loading Loading
include/log/log.h +2 −1 Original line number Diff line number Diff line Loading @@ -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 Loading
include/log/logd.h +2 −0 Original line number Diff line number Diff line Loading @@ -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 Loading
liblog/log_read.c +1 −0 Original line number Diff line number Diff line Loading @@ -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", }; Loading
liblog/logd_write.c +58 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading @@ -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 Loading Loading @@ -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; Loading @@ -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); } } } Loading Loading @@ -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 Loading @@ -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", }; Loading Loading @@ -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 Loading
liblog/tests/liblog_test.cpp +93 −1 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -651,7 +742,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)); Loading