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