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
diff --git a/liblog/logd_write.c b/liblog/logd_write.c
index 11c6d9c..c2b0ec2 100644
--- a/liblog/logd_write.c
+++ b/liblog/logd_write.c
@@ -84,7 +84,7 @@
#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 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 @@
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 @@
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 @@
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 @@
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 @@
[LOG_ID_EVENTS] = "events",
[LOG_ID_SYSTEM] = "system",
[LOG_ID_CRASH] = "crash",
+ [LOG_ID_SECURITY] = "security",
[LOG_ID_KERNEL] = "kernel",
};
@@ -483,6 +526,18 @@
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