Merge "liblog: add __android_log_close()"
diff --git a/adb/socket_test.cpp b/adb/socket_test.cpp
index d2ce2d8..2bb01a3 100644
--- a/adb/socket_test.cpp
+++ b/adb/socket_test.cpp
@@ -254,10 +254,7 @@
     ASSERT_TRUE(adb_thread_create(reinterpret_cast<void (*)(void*)>(ClientThreadFunc), nullptr,
                                   &client_thread));
 
-    struct sockaddr addr;
-    socklen_t alen;
-    alen = sizeof(addr);
-    int accept_fd = adb_socket_accept(listen_fd, &addr, &alen);
+    int accept_fd = adb_socket_accept(listen_fd, nullptr, nullptr);
     ASSERT_GE(accept_fd, 0);
     CloseRdHupSocketArg arg;
     arg.socket_fd = accept_fd;
diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp
index c578d65..5550bc0 100644
--- a/debuggerd/debuggerd.cpp
+++ b/debuggerd/debuggerd.cpp
@@ -821,12 +821,8 @@
   ALOGI("debuggerd: starting\n");
 
   for (;;) {
-    sockaddr_storage ss;
-    sockaddr* addrp = reinterpret_cast<sockaddr*>(&ss);
-    socklen_t alen = sizeof(ss);
-
     ALOGV("waiting for connection\n");
-    int fd = accept4(s, addrp, &alen, SOCK_CLOEXEC | SOCK_NONBLOCK);
+    int fd = accept4(s, nullptr, nullptr, SOCK_CLOEXEC | SOCK_NONBLOCK);
     if (fd == -1) {
       ALOGE("accept failed: %s\n", strerror(errno));
       continue;
diff --git a/debuggerd/tombstone.cpp b/debuggerd/tombstone.cpp
index a56f34d..3ddd2b0 100644
--- a/debuggerd/tombstone.cpp
+++ b/debuggerd/tombstone.cpp
@@ -544,6 +544,10 @@
     if (!hdr_size) {
       hdr_size = sizeof(log_entry.entry_v1);
     }
+    if ((hdr_size < sizeof(log_entry.entry_v1)) ||
+        (hdr_size > sizeof(log_entry.entry))) {
+      continue;
+    }
     char* msg = reinterpret_cast<char*>(log_entry.buf) + hdr_size;
 
     char timeBuf[32];
diff --git a/include/cutils/ashmem.h b/include/cutils/ashmem.h
index acedf73..d80caa6 100644
--- a/include/cutils/ashmem.h
+++ b/include/cutils/ashmem.h
@@ -20,6 +20,7 @@
 extern "C" {
 #endif
 
+int ashmem_valid(int fd);
 int ashmem_create_region(const char *name, size_t size);
 int ashmem_set_prot_region(int fd, int prot);
 int ashmem_pin_region(int fd, size_t offset, size_t len);
diff --git a/include/log/logger.h b/include/log/logger.h
index 60d47a2..256fdd1 100644
--- a/include/log/logger.h
+++ b/include/log/logger.h
@@ -143,7 +143,14 @@
     }
     char *msg()
     {
-        return entry.hdr_size ? (char *) buf + entry.hdr_size : entry_v1.msg;
+        unsigned short hdr_size = entry.hdr_size;
+        if (!hdr_size) {
+            hdr_size = sizeof(entry_v1);
+        }
+        if ((hdr_size < sizeof(entry_v1)) || (hdr_size > sizeof(entry))) {
+            return NULL;
+        }
+        return (char *) buf + hdr_size;
     }
     unsigned int len()
     {
diff --git a/init/property_service.cpp b/init/property_service.cpp
index e2e1b16..9e13733 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -227,32 +227,29 @@
 static void handle_property_set_fd()
 {
     prop_msg msg;
-    int s;
     int r;
-    struct ucred cr;
-    struct sockaddr_un addr;
-    socklen_t addr_size = sizeof(addr);
-    socklen_t cr_size = sizeof(cr);
     char * source_ctx = NULL;
-    struct pollfd ufds[1];
-    const int timeout_ms = 2 * 1000;  /* Default 2 sec timeout for caller to send property. */
-    int nr;
 
-    if ((s = accept(property_set_fd, (struct sockaddr *) &addr, &addr_size)) < 0) {
+    int s = accept(property_set_fd, nullptr, nullptr);
+    if (s == -1) {
         return;
     }
 
     /* Check socket options here */
+    struct ucred cr;
+    socklen_t cr_size = sizeof(cr);
     if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &cr, &cr_size) < 0) {
         close(s);
         PLOG(ERROR) << "Unable to receive socket options";
         return;
     }
 
+    static constexpr int timeout_ms = 2 * 1000;  /* Default 2 sec timeout for caller to send property. */
+    struct pollfd ufds[1];
     ufds[0].fd = s;
     ufds[0].events = POLLIN;
     ufds[0].revents = 0;
-    nr = TEMP_FAILURE_RETRY(poll(ufds, 1, timeout_ms));
+    int nr = TEMP_FAILURE_RETRY(poll(ufds, 1, timeout_ms));
     if (nr == 0) {
         LOG(ERROR) << "sys_prop: timeout waiting for uid " << cr.uid << " to send property message.";
         close(s);
diff --git a/libcutils/ashmem-dev.c b/libcutils/ashmem-dev.c
index 4a07d66..09fa09a 100644
--- a/libcutils/ashmem-dev.c
+++ b/libcutils/ashmem-dev.c
@@ -85,7 +85,7 @@
 }
 
 /* Make sure file descriptor references ashmem, negative number means false */
-static int __ashmem_is_ashmem(int fd)
+static int __ashmem_is_ashmem(int fd, int fatal)
 {
     dev_t rdev;
     struct stat st;
@@ -117,22 +117,29 @@
         }
     }
 
-    if (rdev) {
-        LOG_ALWAYS_FATAL("illegal fd=%d mode=0%o rdev=%d:%d expected 0%o %d:%d",
-          fd, st.st_mode, major(st.st_rdev), minor(st.st_rdev),
-          S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IRGRP,
-          major(rdev), minor(rdev));
-    } else {
-        LOG_ALWAYS_FATAL("illegal fd=%d mode=0%o rdev=%d:%d expected 0%o",
-          fd, st.st_mode, major(st.st_rdev), minor(st.st_rdev),
-          S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IRGRP);
+    if (fatal) {
+        if (rdev) {
+            LOG_ALWAYS_FATAL("illegal fd=%d mode=0%o rdev=%d:%d expected 0%o %d:%d",
+              fd, st.st_mode, major(st.st_rdev), minor(st.st_rdev),
+              S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IRGRP,
+              major(rdev), minor(rdev));
+        } else {
+            LOG_ALWAYS_FATAL("illegal fd=%d mode=0%o rdev=%d:%d expected 0%o",
+              fd, st.st_mode, major(st.st_rdev), minor(st.st_rdev),
+              S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IRGRP);
+        }
+        /* NOTREACHED */
     }
-    /* NOTREACHED */
 
     errno = ENOTTY;
     return -1;
 }
 
+int ashmem_valid(int fd)
+{
+    return __ashmem_is_ashmem(fd, 0) >= 0;
+}
+
 /*
  * ashmem_create_region - creates a new ashmem region and returns the file
  * descriptor, or <0 on error
@@ -175,7 +182,7 @@
 
 int ashmem_set_prot_region(int fd, int prot)
 {
-    int ret = __ashmem_is_ashmem(fd);
+    int ret = __ashmem_is_ashmem(fd, 1);
     if (ret < 0) {
         return ret;
     }
@@ -187,7 +194,7 @@
 {
     struct ashmem_pin pin = { offset, len };
 
-    int ret = __ashmem_is_ashmem(fd);
+    int ret = __ashmem_is_ashmem(fd, 1);
     if (ret < 0) {
         return ret;
     }
@@ -199,7 +206,7 @@
 {
     struct ashmem_pin pin = { offset, len };
 
-    int ret = __ashmem_is_ashmem(fd);
+    int ret = __ashmem_is_ashmem(fd, 1);
     if (ret < 0) {
         return ret;
     }
@@ -209,7 +216,7 @@
 
 int ashmem_get_size_region(int fd)
 {
-    int ret = __ashmem_is_ashmem(fd);
+    int ret = __ashmem_is_ashmem(fd, 1);
     if (ret < 0) {
         return ret;
     }
diff --git a/liblog/logger_read.c b/liblog/logger_read.c
index 00157b7..0d55453 100644
--- a/liblog/logger_read.c
+++ b/liblog/logger_read.c
@@ -367,6 +367,10 @@
     if (log_msg->entry_v2.hdr_size == 0) {
         log_msg->entry_v2.hdr_size = sizeof(struct logger_entry);
     }
+    if ((log_msg->entry_v2.hdr_size < sizeof(log_msg->entry_v1)) ||
+            (log_msg->entry_v2.hdr_size > sizeof(log_msg->entry))) {
+        return -EINVAL;
+    }
 
     /* len validation */
     if (ret <= log_msg->entry_v2.hdr_size) {
diff --git a/liblog/logprint.c b/liblog/logprint.c
index 59bd479..e21a9c4 100644
--- a/liblog/logprint.c
+++ b/liblog/logprint.c
@@ -496,6 +496,11 @@
     char *msg = buf->msg;
     struct logger_entry_v2 *buf2 = (struct logger_entry_v2 *)buf;
     if (buf2->hdr_size) {
+        if ((buf2->hdr_size < sizeof(((struct log_msg *)NULL)->entry_v1)) ||
+                (buf2->hdr_size > sizeof(((struct log_msg *)NULL)->entry))) {
+            fprintf(stderr, "+++ LOG: entry illegal hdr_size\n");
+            return -1;
+        }
         msg = ((char *)buf2) + buf2->hdr_size;
         if (buf2->hdr_size >= sizeof(struct logger_entry_v4)) {
             entry->uid = ((struct logger_entry_v4 *)buf)->uid;
@@ -775,6 +780,11 @@
     eventData = (const unsigned char*) buf->msg;
     struct logger_entry_v2 *buf2 = (struct logger_entry_v2 *)buf;
     if (buf2->hdr_size) {
+        if ((buf2->hdr_size < sizeof(((struct log_msg *)NULL)->entry_v1)) ||
+                (buf2->hdr_size > sizeof(((struct log_msg *)NULL)->entry))) {
+            fprintf(stderr, "+++ LOG: entry illegal hdr_size\n");
+            return -1;
+        }
         eventData = ((unsigned char *)buf2) + buf2->hdr_size;
         if ((buf2->hdr_size >= sizeof(struct logger_entry_v3)) &&
                 (((struct logger_entry_v3 *)buf)->lid == LOG_ID_SECURITY)) {
diff --git a/liblog/pmsg_reader.c b/liblog/pmsg_reader.c
index a4eec65..679c159 100644
--- a/liblog/pmsg_reader.c
+++ b/liblog/pmsg_reader.c
@@ -343,6 +343,10 @@
         char *msg = (char *)&transp.logMsg + hdr_size;
         char *split = NULL;
 
+        if ((hdr_size < sizeof(transp.logMsg.entry_v1)) ||
+                (hdr_size > sizeof(transp.logMsg.entry))) {
+            continue;
+        }
         /* Check for invalid sequence number */
         if ((transp.logMsg.entry.nsec % ANDROID_LOG_PMSG_FILE_SEQUENCE) ||
                 ((transp.logMsg.entry.nsec / ANDROID_LOG_PMSG_FILE_SEQUENCE) >=
diff --git a/liblog/tests/liblog_benchmark.cpp b/liblog/tests/liblog_benchmark.cpp
index 1b66a56..f4e3089 100644
--- a/liblog/tests/liblog_benchmark.cpp
+++ b/liblog/tests/liblog_benchmark.cpp
@@ -542,7 +542,7 @@
 
             char* eventData = log_msg.msg();
 
-            if (eventData[4] != EVENT_TYPE_LONG) {
+            if (!eventData || (eventData[4] != EVENT_TYPE_LONG)) {
                 continue;
             }
             log_time tx(eventData + 4 + 1);
@@ -622,7 +622,7 @@
 
             char* eventData = log_msg.msg();
 
-            if (eventData[4] != EVENT_TYPE_LONG) {
+            if (!eventData || (eventData[4] != EVENT_TYPE_LONG)) {
                 continue;
             }
             log_time tx(eventData + 4 + 1);
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index cb92016..b3b44e3 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -159,7 +159,7 @@
 
         char *eventData = log_msg.msg();
 
-        if (eventData[4] != EVENT_TYPE_LONG) {
+        if (!eventData || (eventData[4] != EVENT_TYPE_LONG)) {
             continue;
         }
 
@@ -235,7 +235,7 @@
 
         char *eventData = log_msg.msg();
 
-        if (eventData[4] != EVENT_TYPE_STRING) {
+        if (!eventData || (eventData[4] != EVENT_TYPE_STRING)) {
             continue;
         }
 
@@ -514,7 +514,7 @@
 
         char *eventData = log_msg.msg();
 
-        if (eventData[4] != EVENT_TYPE_LONG) {
+        if (!eventData || (eventData[4] != EVENT_TYPE_LONG)) {
             continue;
         }
 
@@ -645,7 +645,7 @@
 
         char *eventData = log_msg.msg();
 
-        if (eventData[4] != EVENT_TYPE_LONG) {
+        if (!eventData || (eventData[4] != EVENT_TYPE_LONG)) {
             continue;
         }
 
@@ -796,7 +796,7 @@
 
         char *eventData = log_msg.msg();
 
-        if (eventData[4] != EVENT_TYPE_LONG) {
+        if (!eventData || (eventData[4] != EVENT_TYPE_LONG)) {
             continue;
         }
 
@@ -998,9 +998,9 @@
             continue;
         }
 
-        char *data = log_msg.msg() + 1;
+        char *data = log_msg.msg();
 
-        if (strcmp(data, tag)) {
+        if (!data || strcmp(++data, tag)) {
             continue;
         }
 
@@ -1115,9 +1115,9 @@
             continue;
         }
 
-        char *data = log_msg.msg() + 1;
+        char *data = log_msg.msg();
 
-        if (strcmp(data, tag)) {
+        if (!data || strcmp(++data, tag)) {
             continue;
         }
 
@@ -1614,6 +1614,9 @@
         }
 
         char *eventData = log_msg.msg();
+        if (!eventData) {
+            continue;
+        }
 
         // Tag
         int tag = get4LE(eventData);
@@ -1695,6 +1698,10 @@
         }
 
         char *eventData = log_msg.msg();
+        if (!eventData) {
+            continue;
+        }
+
         char *original = eventData;
 
         // Tag
@@ -1782,6 +1789,9 @@
         }
 
         char *eventData = log_msg.msg();
+        if (!eventData) {
+            continue;
+        }
 
         // Tag
         int tag = get4LE(eventData);
@@ -1825,6 +1835,9 @@
         }
 
         char *eventData = log_msg.msg();
+        if (!eventData) {
+            continue;
+        }
 
         // Tag
         int tag = get4LE(eventData);
@@ -1912,6 +1925,9 @@
         }
 
         char *eventData = log_msg.msg();
+        if (!eventData) {
+            continue;
+        }
 
         // Tag
         int tag = get4LE(eventData);
@@ -1969,6 +1985,9 @@
         }
 
         char *eventData = log_msg.msg();
+        if (!eventData) {
+            continue;
+        }
 
         // Tag
         int tag = get4LE(eventData);
@@ -2457,16 +2476,19 @@
         android_log_format_free(logformat);
 
         // test buffer reading API
-        snprintf(msgBuf, sizeof(msgBuf), "I/[%d]", get4LE(eventData));
-        print_barrier();
-        fprintf(stderr, "%-10s(%5u): ", msgBuf, pid);
-        memset(msgBuf, 0, sizeof(msgBuf));
-        int buffer_to_string = android_log_buffer_to_string(
-            eventData + sizeof(uint32_t),
-            log_msg.entry.len - sizeof(uint32_t),
-            msgBuf, sizeof(msgBuf));
-        fprintf(stderr, "%s\n", msgBuf);
-        print_barrier();
+        int buffer_to_string = -1;
+        if (eventData) {
+            snprintf(msgBuf, sizeof(msgBuf), "I/[%d]", get4LE(eventData));
+            print_barrier();
+            fprintf(stderr, "%-10s(%5u): ", msgBuf, pid);
+            memset(msgBuf, 0, sizeof(msgBuf));
+            buffer_to_string = android_log_buffer_to_string(
+                eventData + sizeof(uint32_t),
+                log_msg.entry.len - sizeof(uint32_t),
+                msgBuf, sizeof(msgBuf));
+            fprintf(stderr, "%s\n", msgBuf);
+            print_barrier();
+        }
         EXPECT_EQ(0, buffer_to_string);
         EXPECT_EQ(strlen(expected_string), strlen(msgBuf));
         EXPECT_EQ(0, strcmp(expected_string, msgBuf));
diff --git a/libsysutils/src/SocketListener.cpp b/libsysutils/src/SocketListener.cpp
index 4d602a6..608abae 100644
--- a/libsysutils/src/SocketListener.cpp
+++ b/libsysutils/src/SocketListener.cpp
@@ -199,16 +199,7 @@
             continue;
         }
         if (mListen && FD_ISSET(mSock, &read_fds)) {
-            sockaddr_storage ss;
-            sockaddr* addrp = reinterpret_cast<sockaddr*>(&ss);
-            socklen_t alen;
-            int c;
-
-            do {
-                alen = sizeof(ss);
-                c = accept4(mSock, addrp, &alen, SOCK_CLOEXEC);
-                SLOGV("%s got %d from accept", mSocketName, c);
-            } while (c < 0 && errno == EINTR);
+            int c = TEMP_FAILURE_RETRY(accept4(mSock, nullptr, nullptr, SOCK_CLOEXEC));
             if (c < 0) {
                 SLOGE("accept failed (%s)", strerror(errno));
                 sleep(1);
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c
index 37fbdb8..733b784 100644
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -410,9 +410,6 @@
 }
 
 static void ctrl_connect_handler(uint32_t events __unused) {
-    struct sockaddr_storage ss;
-    struct sockaddr *addrp = (struct sockaddr *)&ss;
-    socklen_t alen;
     struct epoll_event epev;
 
     if (ctrl_dfd >= 0) {
@@ -420,8 +417,7 @@
         ctrl_dfd_reopened = 1;
     }
 
-    alen = sizeof(ss);
-    ctrl_dfd = accept(ctrl_lfd, addrp, &alen);
+    ctrl_dfd = accept(ctrl_lfd, NULL, NULL);
 
     if (ctrl_dfd < 0) {
         ALOGE("lmkd control socket accept failed; errno=%d", errno);
diff --git a/logd/tests/logd_test.cpp b/logd/tests/logd_test.cpp
index 2014374..301ede9 100644
--- a/logd/tests/logd_test.cpp
+++ b/logd/tests/logd_test.cpp
@@ -213,9 +213,15 @@
         version = 1;
         break;
 
-    case sizeof(msg->entry_v2):
+    case sizeof(msg->entry_v2): /* PLUS case sizeof(msg->entry_v3): */
         if (version == 0) {
-            version = 2;
+            version = (msg->entry_v3.lid < LOG_ID_MAX) ? 3 : 2;
+        }
+        break;
+
+    case sizeof(msg->entry_v4):
+        if (version == 0) {
+            version = 4;
         }
         break;
     }
@@ -269,6 +275,11 @@
     unsigned int len = msg->entry.len;
     fprintf(stderr, "msg[%u]={", len);
     unsigned char *cp = reinterpret_cast<unsigned char *>(msg->msg());
+    if (!cp) {
+        static const unsigned char garbage[] = "<INVALID>";
+        cp = const_cast<unsigned char *>(garbage);
+        len = strlen(reinterpret_cast<const char *>(garbage));
+    }
     while(len) {
         unsigned char *p = cp;
         while (*p && (((' ' <= *p) && (*p < 0x7F)) || (*p == '\n'))) {