bionic: prevent root processes from calling __system_property_add

If a root process other than init calls __system_property_add, which
it should never do, it will break the design assumption that there is
only one mutator.

Pass O_EXCL to open() in map_prop_region_rw to ensure that only one
process ever has the property pages open for write.

(cherry picked from commit fb9b7b436f3ef94385f1b0c55ab81f246f0d96b8)

Change-Id: I6df3afedbfb5d07891b095aa24b78278381a5aaf
diff --git a/libc/bionic/system_properties.c b/libc/bionic/system_properties.c
index d4054d2..f9671c6 100644
--- a/libc/bionic/system_properties.c
+++ b/libc/bionic/system_properties.c
@@ -128,11 +128,13 @@
 {
     prop_area *pa;
     int fd;
+    int ret;
 
     /* dev is a tmpfs that we can use to carve a shared workspace
      * out of, so let's do that...
      */
-    fd = open(property_filename, O_RDWR | O_CREAT | O_NOFOLLOW, 0644);
+    fd = open(property_filename, O_RDWR | O_CREAT | O_NOFOLLOW | O_CLOEXEC |
+            O_EXCL, 0444);
     if (fd < 0) {
         if (errno == EACCES) {
             /* for consistency with the case where the process has already
@@ -143,6 +145,10 @@
         return -1;
     }
 
+    ret = fcntl(fd, F_SETFD, FD_CLOEXEC);
+    if (ret < 0)
+        goto out;
+
     if (ftruncate(fd, PA_SIZE) < 0)
         goto out;
 
@@ -186,8 +192,16 @@
 {
     bool fromFile = true;
     int result = -1;
+    int fd;
+    int ret;
 
-    int fd = open(property_filename, O_RDONLY | O_NOFOLLOW);
+    fd = open(property_filename, O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
+    if (fd >= 0) {
+        /* For old kernels that don't support O_CLOEXEC */
+        ret = fcntl(fd, F_SETFD, FD_CLOEXEC);
+        if (ret < 0)
+            goto cleanup;
+    }
 
     if ((fd < 0) && (errno == ENOENT)) {
         /*