Reconcile with jb-mr1-release - do not merge

Change-Id: I7ec0e7696f2f2004f75d5b83f86ea6d890e0cd3d
diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c
index 538b5be..2bcc9c4 100644
--- a/fs_mgr/fs_mgr.c
+++ b/fs_mgr/fs_mgr.c
@@ -173,7 +173,7 @@
  * then return an empty buffer.  This effectively ignores lines that are too long.
  * On EOF, return null.
  */
-static char *getline(char *buf, int size, FILE *file)
+static char *fs_getline(char *buf, int size, FILE *file)
 {
     int cnt = 0;
     int eof = 0;
@@ -247,7 +247,7 @@
     }
 
     entries = 0;
-    while (getline(line, sizeof(line), fstab_file)) {
+    while (fs_getline(line, sizeof(line), fstab_file)) {
         /* if the last character is a newline, shorten the string by 1 byte */
         len = strlen(line);
         if (line[len - 1] == '\n') {
@@ -274,7 +274,7 @@
     fseek(fstab_file, 0, SEEK_SET);
 
     cnt = 0;
-    while (getline(line, sizeof(line), fstab_file)) {
+    while (fs_getline(line, sizeof(line), fstab_file)) {
         /* if the last character is a newline, shorten the string by 1 byte */
         len = strlen(line);
         if (line[len - 1] == '\n') {
diff --git a/init/property_service.c b/init/property_service.c
index f58e07d..01a4d17 100755
--- a/init/property_service.c
+++ b/init/property_service.c
@@ -125,7 +125,7 @@
         /* dev is a tmpfs that we can use to carve a shared workspace
          * out of, so let's do that...
          */
-    fd = open("/dev/__properties__", O_RDWR | O_CREAT, 0600);
+    fd = open("/dev/__properties__", O_RDWR | O_CREAT | O_NOFOLLOW, 0600);
     if (fd < 0)
         return -1;
 
@@ -138,7 +138,7 @@
 
     close(fd);
 
-    fd = open("/dev/__properties__", O_RDONLY);
+    fd = open("/dev/__properties__", O_RDONLY | O_NOFOLLOW);
     if (fd < 0)
         return -1;
 
@@ -320,13 +320,12 @@
 
 static void write_persistent_property(const char *name, const char *value)
 {
-    const char *tempPath = PERSISTENT_PROPERTY_DIR "/.temp";
+    char tempPath[PATH_MAX];
     char path[PATH_MAX];
-    int fd, length;
+    int fd;
 
-    snprintf(path, sizeof(path), "%s/%s", PERSISTENT_PROPERTY_DIR, name);
-
-    fd = open(tempPath, O_WRONLY|O_CREAT|O_TRUNC, 0600);
+    snprintf(tempPath, sizeof(tempPath), "%s/.temp.XXXXXX", PERSISTENT_PROPERTY_DIR);
+    fd = mkstemp(tempPath);
     if (fd < 0) {
         ERROR("Unable to write persistent property to temp file %s errno: %d\n", tempPath, errno);
         return;
@@ -334,6 +333,7 @@
     write(fd, value, strlen(value));
     close(fd);
 
+    snprintf(path, sizeof(path), "%s/%s", PERSISTENT_PROPERTY_DIR, name);
     if (rename(tempPath, path)) {
         unlink(tempPath);
         ERROR("Unable to rename persistent property file %s to %s\n", tempPath, path);
@@ -345,8 +345,8 @@
     prop_area *pa;
     prop_info *pi;
 
-    int namelen = strlen(name);
-    int valuelen = strlen(value);
+    size_t namelen = strlen(name);
+    size_t valuelen = strlen(value);
 
     if(namelen >= PROP_NAME_MAX) return -1;
     if(valuelen >= PROP_VALUE_MAX) return -1;
@@ -425,13 +425,13 @@
     /* Check socket options here */
     if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &cr, &cr_size) < 0) {
         close(s);
-        ERROR("Unable to recieve socket options\n");
+        ERROR("Unable to receive socket options\n");
         return;
     }
 
     r = TEMP_FAILURE_RETRY(recv(s, &msg, sizeof(msg), 0));
     if(r != sizeof(prop_msg)) {
-        ERROR("sys_prop: mis-match msg size recieved: %d expected: %d errno: %d\n",
+        ERROR("sys_prop: mis-match msg size received: %d expected: %d errno: %d\n",
               r, sizeof(prop_msg), errno);
         close(s);
         return;
@@ -530,10 +530,11 @@
 static void load_persistent_properties()
 {
     DIR* dir = opendir(PERSISTENT_PROPERTY_DIR);
+    int dir_fd = dirfd(dir);
     struct dirent*  entry;
-    char path[PATH_MAX];
     char value[PROP_VALUE_MAX];
     int fd, length;
+    struct stat sb;
 
     if (dir) {
         while ((entry = readdir(dir)) != NULL) {
@@ -544,20 +545,39 @@
                 continue;
 #endif
             /* open the file and read the property value */
-            snprintf(path, sizeof(path), "%s/%s", PERSISTENT_PROPERTY_DIR, entry->d_name);
-            fd = open(path, O_RDONLY);
-            if (fd >= 0) {
-                length = read(fd, value, sizeof(value) - 1);
-                if (length >= 0) {
-                    value[length] = 0;
-                    property_set(entry->d_name, value);
-                } else {
-                    ERROR("Unable to read persistent property file %s errno: %d\n", path, errno);
-                }
-                close(fd);
-            } else {
-                ERROR("Unable to open persistent property file %s errno: %d\n", path, errno);
+            fd = openat(dir_fd, entry->d_name, O_RDONLY | O_NOFOLLOW);
+            if (fd < 0) {
+                ERROR("Unable to open persistent property file \"%s\" errno: %d\n",
+                      entry->d_name, errno);
+                continue;
             }
+            if (fstat(fd, &sb) < 0) {
+                ERROR("fstat on property file \"%s\" failed errno: %d\n", entry->d_name, errno);
+                close(fd);
+                continue;
+            }
+
+            // File must not be accessible to others, be owned by root/root, and
+            // not be a hard link to any other file.
+            if (((sb.st_mode & (S_IRWXG | S_IRWXO)) != 0)
+                    || (sb.st_uid != 0)
+                    || (sb.st_gid != 0)
+                    || (sb.st_nlink != 1)) {
+                ERROR("skipping insecure property file %s (uid=%lu gid=%lu nlink=%d mode=%o)\n",
+                      entry->d_name, sb.st_uid, sb.st_gid, sb.st_nlink, sb.st_mode);
+                close(fd);
+                continue;
+            }
+
+            length = read(fd, value, sizeof(value) - 1);
+            if (length >= 0) {
+                value[length] = 0;
+                property_set(entry->d_name, value);
+            } else {
+                ERROR("Unable to read persistent property file %s errno: %d\n",
+                      entry->d_name, errno);
+            }
+            close(fd);
         }
         closedir(dir);
     } else {
diff --git a/toolbox/ls.c b/toolbox/ls.c
index a4db99c..b7ba1b7 100644
--- a/toolbox/ls.c
+++ b/toolbox/ls.c
@@ -276,12 +276,12 @@
     switch(s.st_mode & S_IFMT) {
     case S_IFLNK: {
         char linkto[256];
-        int len;
+        ssize_t len;
 
         len = readlink(path, linkto, sizeof(linkto));
         if(len < 0) return -1;
 
-        if(len > sizeof(linkto)-1) {
+        if((size_t)len > sizeof(linkto)-1) {
             linkto[sizeof(linkto)-4] = '.';
             linkto[sizeof(linkto)-3] = '.';
             linkto[sizeof(linkto)-2] = '.';
@@ -307,7 +307,7 @@
 
 static int listfile(const char *dirname, const char *filename, int flags)
 {
-    if ((flags & LIST_LONG | LIST_SIZE | LIST_CLASSIFY | LIST_MACLABEL) == 0) {
+    if ((flags & (LIST_LONG | LIST_SIZE | LIST_CLASSIFY | LIST_MACLABEL)) == 0) {
         printf("%s\n", filename);
         return 0;
     }