Merge "Remove sshd."
diff --git a/include/log/log.h b/include/log/log.h
index 5b76c1a..ace12d6 100644
--- a/include/log/log.h
+++ b/include/log/log.h
@@ -491,7 +491,7 @@
 #endif
 #ifndef LOG_EVENT_STRING
 #define LOG_EVENT_STRING(_tag, _value)                                      \
-    ((void) 0)  /* not implemented -- must combine len with string */
+        (void) __android_log_bswrite(_tag, _value);
 #endif
 /* TODO: something for LIST */
 
diff --git a/include/log/logd.h b/include/log/logd.h
index 379c373..2e6f220 100644
--- a/include/log/logd.h
+++ b/include/log/logd.h
@@ -41,6 +41,7 @@
 int __android_log_bwrite(int32_t tag, const void *payload, size_t len);
 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);
 
 #ifdef __cplusplus
 }
diff --git a/init/devices.c b/init/devices.c
index ea9a4b2..e27c311 100644
--- a/init/devices.c
+++ b/init/devices.c
@@ -134,11 +134,10 @@
     char buf[512];
     struct listnode *node;
     struct perms_ *dp;
-    char *secontext;
 
-        /* upaths omit the "/sys" that paths in this list
-         * contain, so we add 4 when comparing...
-         */
+    /* upaths omit the "/sys" that paths in this list
+     * contain, so we add 4 when comparing...
+     */
     list_for_each(node, &sys_perms) {
         dp = &(node_to_item(node, struct perm_node, plist))->dp;
         if (dp->prefix) {
@@ -153,24 +152,44 @@
         }
 
         if ((strlen(upath) + strlen(dp->attr) + 6) > sizeof(buf))
-            return;
+            break;
 
         sprintf(buf,"/sys%s/%s", upath, dp->attr);
         INFO("fixup %s %d %d 0%o\n", buf, dp->uid, dp->gid, dp->perm);
         chown(buf, dp->uid, dp->gid);
         chmod(buf, dp->perm);
-        if (sehandle) {
-            secontext = NULL;
-            selabel_lookup(sehandle, &secontext, buf, 0);
-            if (secontext) {
-                setfilecon(buf, secontext);
-                freecon(secontext);
-           }
-        }
+    }
+
+    // Now fixup SELinux file labels
+    int len = snprintf(buf, sizeof(buf), "/sys%s", upath);
+    if ((len < 0) || ((size_t) len >= sizeof(buf))) {
+        // Overflow
+        return;
+    }
+    if (access(buf, F_OK) == 0) {
+        INFO("restorecon_recursive: %s\n", buf);
+        restorecon_recursive(buf);
     }
 }
 
-static mode_t get_device_perm(const char *path, unsigned *uid, unsigned *gid)
+static bool perm_path_matches(const char *path, struct perms_ *dp)
+{
+    if (dp->prefix) {
+        if (strncmp(path, dp->name, strlen(dp->name)) == 0)
+            return true;
+    } else if (dp->wildcard) {
+        if (fnmatch(dp->name, path, FNM_PATHNAME) == 0)
+            return true;
+    } else {
+        if (strcmp(path, dp->name) == 0)
+            return true;
+    }
+
+    return false;
+}
+
+static mode_t get_device_perm(const char *path, const char **links,
+                unsigned *uid, unsigned *gid)
 {
     mode_t perm;
     struct listnode *node;
@@ -181,22 +200,30 @@
      * override ueventd.rc
      */
     list_for_each_reverse(node, &dev_perms) {
+        bool match = false;
+
         perm_node = node_to_item(node, struct perm_node, plist);
         dp = &perm_node->dp;
 
-        if (dp->prefix) {
-            if (strncmp(path, dp->name, strlen(dp->name)))
-                continue;
-        } else if (dp->wildcard) {
-            if (fnmatch(dp->name, path, FNM_PATHNAME) != 0)
-                continue;
+        if (perm_path_matches(path, dp)) {
+            match = true;
         } else {
-            if (strcmp(path, dp->name))
-                continue;
+            if (links) {
+                int i;
+                for (i = 0; links[i]; i++) {
+                    if (perm_path_matches(links[i], dp)) {
+                        match = true;
+                        break;
+                    }
+                }
+            }
         }
-        *uid = dp->uid;
-        *gid = dp->gid;
-        return dp->perm;
+
+        if (match) {
+            *uid = dp->uid;
+            *gid = dp->gid;
+            return dp->perm;
+        }
     }
     /* Default if nothing found. */
     *uid = 0;
@@ -215,7 +242,7 @@
     dev_t dev;
     char *secontext = NULL;
 
-    mode = get_device_perm(path, &uid, &gid) | (block ? S_IFBLK : S_IFCHR);
+    mode = get_device_perm(path, links, &uid, &gid) | (block ? S_IFBLK : S_IFCHR);
 
     if (sehandle) {
         selabel_lookup_best_match(sehandle, &secontext, path, links, mode);
diff --git a/liblog/logd_write.c b/liblog/logd_write.c
index f10eb8e..3171c78 100644
--- a/liblog/logd_write.c
+++ b/liblog/logd_write.c
@@ -107,7 +107,7 @@
         close(i);
     }
 
-    i = socket(PF_UNIX, SOCK_DGRAM, 0);
+    i = socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0);
     if (i < 0) {
         ret = -errno;
         write_to_log = __write_to_log_null;
@@ -473,3 +473,25 @@
 
     return write_to_log(LOG_ID_EVENTS, vec, 3);
 }
+
+/*
+ * Like __android_log_bwrite, but used for writing strings to the
+ * event log.
+ */
+int __android_log_bswrite(int32_t tag, const char *payload)
+{
+    struct iovec vec[4];
+    char type = EVENT_TYPE_STRING;
+    uint32_t len = strlen(payload);
+
+    vec[0].iov_base = &tag;
+    vec[0].iov_len = sizeof(tag);
+    vec[1].iov_base = &type;
+    vec[1].iov_len = sizeof(type);
+    vec[2].iov_base = &len;
+    vec[2].iov_len = sizeof(len);
+    vec[3].iov_base = (void*)payload;
+    vec[3].iov_len = len;
+
+    return write_to_log(LOG_ID_EVENTS, vec, 4);
+}
diff --git a/liblog/logd_write_kern.c b/liblog/logd_write_kern.c
index 1d10748..1ed5ecf 100644
--- a/liblog/logd_write_kern.c
+++ b/liblog/logd_write_kern.c
@@ -317,3 +317,25 @@
 
     return write_to_log(LOG_ID_EVENTS, vec, 3);
 }
+
+/*
+ * Like __android_log_bwrite, but used for writing strings to the
+ * event log.
+ */
+int __android_log_bswrite(int32_t tag, const char *payload)
+{
+    struct iovec vec[4];
+    char type = EVENT_TYPE_STRING;
+    uint32_t len = strlen(payload);
+
+    vec[0].iov_base = &tag;
+    vec[0].iov_len = sizeof(tag);
+    vec[1].iov_base = &type;
+    vec[1].iov_len = sizeof(type);
+    vec[2].iov_base = &len;
+    vec[2].iov_len = sizeof(len);
+    vec[3].iov_base = (void*)payload;
+    vec[3].iov_len = len;
+
+    return write_to_log(LOG_ID_EVENTS, vec, 4);
+}
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index 16fe7ee..7c6af42 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -336,7 +336,7 @@
     for (;;) {
         int ret;
 
-        ret = getopt(argc, argv, "cdt:T:gG:sQf:r::n:v:b:BSpP:");
+        ret = getopt(argc, argv, "cdt:T:gG:sQf:r:n:v:b:BSpP:");
 
         if (ret < 0) {
             break;