Merge "Mark some tests as requiring root."
diff --git a/init/selinux.cpp b/init/selinux.cpp
index fd42256..6842820 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -51,6 +51,8 @@
 
 #include <android/api-level.h>
 #include <fcntl.h>
+#include <linux/audit.h>
+#include <linux/netlink.h>
 #include <stdlib.h>
 #include <sys/wait.h>
 #include <unistd.h>
@@ -446,6 +448,35 @@
     }
 }
 
+constexpr size_t kKlogMessageSize = 1024;
+
+void SelinuxAvcLog(char* buf, size_t buf_len) {
+    CHECK_GT(buf_len, 0u);
+
+    size_t str_len = strnlen(buf, buf_len);
+    // trim newline at end of string
+    if (buf[str_len - 1] == '\n') {
+        buf[str_len - 1] = '\0';
+    }
+
+    struct NetlinkMessage {
+        nlmsghdr hdr;
+        char buf[kKlogMessageSize];
+    } request = {};
+
+    request.hdr.nlmsg_flags = NLM_F_REQUEST;
+    request.hdr.nlmsg_type = AUDIT_USER_AVC;
+    request.hdr.nlmsg_len = sizeof(request);
+    strlcpy(request.buf, buf, sizeof(request.buf));
+
+    auto fd = unique_fd{socket(PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_AUDIT)};
+    if (!fd.ok()) {
+        return;
+    }
+
+    TEMP_FAILURE_RETRY(send(fd, &request, sizeof(request), 0));
+}
+
 }  // namespace
 
 // The files and directories that were created before initial sepolicy load or
@@ -478,12 +509,19 @@
     } else if (type == SELINUX_INFO) {
         severity = android::base::INFO;
     }
-    char buf[1024];
+    char buf[kKlogMessageSize];
     va_list ap;
     va_start(ap, fmt);
-    vsnprintf(buf, sizeof(buf), fmt, ap);
+    int length_written = vsnprintf(buf, sizeof(buf), fmt, ap);
     va_end(ap);
-    android::base::KernelLogger(android::base::MAIN, severity, "selinux", nullptr, 0, buf);
+    if (length_written <= 0) {
+        return 0;
+    }
+    if (type == SELINUX_AVC) {
+        SelinuxAvcLog(buf, sizeof(buf));
+    } else {
+        android::base::KernelLogger(android::base::MAIN, severity, "selinux", nullptr, 0, buf);
+    }
     return 0;
 }
 
diff --git a/libunwindstack/tools/unwind_reg_info.cpp b/libunwindstack/tools/unwind_reg_info.cpp
index d0562d9..0cbcac5 100644
--- a/libunwindstack/tools/unwind_reg_info.cpp
+++ b/libunwindstack/tools/unwind_reg_info.cpp
@@ -165,8 +165,8 @@
   }
 }
 
-int GetInfo(const char* file, uint64_t pc) {
-  Elf elf(Memory::CreateFileMemory(file, pc).release());
+int GetInfo(const char* file, uint64_t offset, uint64_t pc) {
+  Elf elf(Memory::CreateFileMemory(file, offset).release());
   if (!elf.Init() || !elf.valid()) {
     printf("%s is not a valid elf file.\n", file);
     return 1;
@@ -243,12 +243,14 @@
 }  // namespace unwindstack
 
 int main(int argc, char** argv) {
-  if (argc != 3) {
-    printf("Usage: unwind_reg_info ELF_FILE PC\n");
+  if (argc != 3 && argc != 4) {
+    printf("Usage: unwind_reg_info ELF_FILE PC [OFFSET]\n");
     printf("  ELF_FILE\n");
     printf("    The path to an elf file.\n");
     printf("  PC\n");
     printf("    The pc for which the register information should be obtained.\n");
+    printf("  OFFSET\n");
+    printf("    Use the offset into the ELF file as the beginning of the elf.\n");
     return 1;
   }
 
@@ -270,5 +272,15 @@
     return 1;
   }
 
-  return unwindstack::GetInfo(argv[1], pc);
+  uint64_t offset = 0;
+  if (argc == 4) {
+    char* end;
+    offset = strtoull(argv[3], &end, 16);
+    if (*end != '\0') {
+      printf("Malformed OFFSET value: %s\n", argv[3]);
+      return 1;
+    }
+  }
+
+  return unwindstack::GetInfo(argv[1], offset, pc);
 }