OSDN Git Service

libc: clean up ARM64 copyright notices
[android-x86/bionic.git] / libc / bionic / system_properties.cpp
index ec1d18f..a958699 100644 (file)
 #include <sys/_system_properties.h>
 #include <sys/system_properties.h>
 
+#include <async_safe/log.h>
+
+#include "private/ErrnoRestorer.h"
 #include "private/bionic_futex.h"
 #include "private/bionic_lock.h"
 #include "private/bionic_macros.h"
 #include "private/bionic_sdk_version.h"
-#include "private/libc_logging.h"
 
 static constexpr int PROP_FILENAME_MAX = 1024;
 
@@ -199,17 +201,7 @@ struct prop_info {
   DISALLOW_IMPLICIT_CONSTRUCTORS(prop_info);
 };
 
-struct find_nth_cookie {
-  uint32_t count;
-  const uint32_t n;
-  const prop_info* pi;
-
-  explicit find_nth_cookie(uint32_t n) : count(0), n(n), pi(nullptr) {
-  }
-};
-
 // This is public because it was exposed in the NDK. As of 2017-01, ~60 apps reference this symbol.
-// It's also used in a libnativehelper test.
 prop_area* __system_property_area__ = nullptr;
 
 static char property_filename[PROP_FILENAME_MAX] = PROP_FILENAME;
@@ -236,8 +228,8 @@ static prop_area* map_prop_area_rw(const char* filename, const char* context,
 
   if (context) {
     if (fsetxattr(fd, XATTR_NAME_SELINUX, context, strlen(context) + 1, 0) != 0) {
-      __libc_format_log(ANDROID_LOG_ERROR, "libc",
-                        "fsetxattr failed to set context (%s) for \"%s\"", context, filename);
+      async_safe_format_log(ANDROID_LOG_ERROR, "libc",
+                            "fsetxattr failed to set context (%s) for \"%s\"", context, filename);
       /*
        * fsetxattr() will fail during system properties tests due to selinux policy.
        * We do not want to create a custom policy for the tester, so we will continue in
@@ -501,9 +493,9 @@ class PropertyServiceConnection {
     socklen_t alen = namelen + offsetof(sockaddr_un, sun_path) + 1;
 
     if (TEMP_FAILURE_RETRY(connect(socket_, reinterpret_cast<sockaddr*>(&addr), alen)) == -1) {
+      last_error_ = errno;
       close(socket_);
       socket_ = -1;
-      last_error_ = errno;
     }
   }
 
@@ -649,9 +641,9 @@ static int send_prop_msg(const prop_msg* msg) {
       // ms so callers who do read-after-write can reliably see
       // what they've written.  Most of the time.
       // TODO: fix the system properties design.
-      __libc_format_log(ANDROID_LOG_WARN, "libc",
-                        "Property service has timed out while trying to set \"%s\" to \"%s\"",
-                        msg->name, msg->value);
+      async_safe_format_log(ANDROID_LOG_WARN, "libc",
+                            "Property service has timed out while trying to set \"%s\" to \"%s\"",
+                            msg->name, msg->value);
       result = 0;
     }
   }
@@ -659,14 +651,6 @@ static int send_prop_msg(const prop_msg* msg) {
   return result;
 }
 
-static void find_nth_fn(const prop_info* pi, void* ptr) {
-  find_nth_cookie* cookie = reinterpret_cast<find_nth_cookie*>(ptr);
-
-  if (cookie->n == cookie->count) cookie->pi = pi;
-
-  cookie->count++;
-}
-
 bool prop_area::foreach_property(prop_bt* const trie,
                                  void (*propfn)(const prop_info* pi, void* cookie), void* cookie) {
   if (!trie) return false;
@@ -823,7 +807,8 @@ bool context_node::open(bool access_rw, bool* fsetxattr_failed) {
   }
 
   char filename[PROP_FILENAME_MAX];
-  int len = __libc_format_buffer(filename, sizeof(filename), "%s/%s", property_filename, context_);
+  int len = async_safe_format_buffer(filename, sizeof(filename), "%s/%s", property_filename,
+                                     context_);
   if (len < 0 || len > PROP_FILENAME_MAX) {
     lock_.unlock();
     return false;
@@ -858,7 +843,8 @@ void context_node::reset_access() {
 
 bool context_node::check_access() {
   char filename[PROP_FILENAME_MAX];
-  int len = __libc_format_buffer(filename, sizeof(filename), "%s/%s", property_filename, context_);
+  int len = async_safe_format_buffer(filename, sizeof(filename), "%s/%s", property_filename,
+                                     context_);
   if (len < 0 || len > PROP_FILENAME_MAX) {
     return false;
   }
@@ -881,7 +867,8 @@ void context_node::unmap() {
 static bool map_system_property_area(bool access_rw, bool* fsetxattr_failed) {
   char filename[PROP_FILENAME_MAX];
   int len =
-      __libc_format_buffer(filename, sizeof(filename), "%s/properties_serial", property_filename);
+      async_safe_format_buffer(filename, sizeof(filename), "%s/properties_serial",
+                               property_filename);
   if (len < 0 || len > PROP_FILENAME_MAX) {
     __system_property_area__ = nullptr;
     return false;
@@ -1059,15 +1046,23 @@ static bool initialize_properties() {
     return true;
   }
 
-  // TODO: Change path to /system/property_contexts after b/27805372
-  if (!initialize_properties_from_file("/plat_property_contexts")) {
-    return false;
+  // Use property_contexts from /system & /vendor, fall back to those from /
+  if (access("/system/etc/selinux/plat_property_contexts", R_OK) != -1) {
+    if (!initialize_properties_from_file("/system/etc/selinux/plat_property_contexts")) {
+      return false;
+    }
+    if (!initialize_properties_from_file("/vendor/etc/selinux/nonplat_property_contexts")) {
+      return false;
+    }
+  } else {
+    if (!initialize_properties_from_file("/plat_property_contexts")) {
+      return false;
+    }
+    if (!initialize_properties_from_file("/nonplat_property_contexts")) {
+      return false;
+    }
   }
 
-  // TODO: Change path to /vendor/property_contexts after b/27805372
-  // device-specific property context is optional, so load if it exists.
-  initialize_properties_from_file("/nonplat_property_contexts");
-
   return true;
 }
 
@@ -1089,6 +1084,9 @@ static void free_and_unmap_contexts() {
 }
 
 int __system_properties_init() {
+  // This is called from __libc_init_common, and should leave errno at 0 (http://b/37248982).
+  ErrnoRestorer errno_restorer;
+
   if (initialized) {
     list_foreach(contexts, [](context_node* l) { l->reset_access(); });
     return 0;
@@ -1158,7 +1156,7 @@ const prop_info* __system_property_find(const char* name) {
 
   prop_area* pa = get_prop_area_for_name(name);
   if (!pa) {
-    __libc_format_log(ANDROID_LOG_ERROR, "libc", "Access denied finding property \"%s\"", name);
+    async_safe_format_log(ANDROID_LOG_ERROR, "libc", "Access denied finding property \"%s\"", name);
     return nullptr;
   }
 
@@ -1190,11 +1188,11 @@ int __system_property_read(const prop_info* pi, char* name, char* value) {
       if (name != nullptr) {
         size_t namelen = strlcpy(name, pi->name, PROP_NAME_MAX);
         if (namelen >= PROP_NAME_MAX) {
-          __libc_format_log(ANDROID_LOG_ERROR, "libc",
-                            "The property name length for \"%s\" is >= %d;"
-                            " please use __system_property_read_callback"
-                            " to read this property. (the name is truncated to \"%s\")",
-                            pi->name, PROP_NAME_MAX - 1, name);
+          async_safe_format_log(ANDROID_LOG_ERROR, "libc",
+                                "The property name length for \"%s\" is >= %d;"
+                                " please use __system_property_read_callback"
+                                " to read this property. (the name is truncated to \"%s\")",
+                                pi->name, PROP_NAME_MAX - 1, name);
         }
       }
       return len;
@@ -1245,17 +1243,17 @@ static void detect_protocol_version() {
   char value[PROP_VALUE_MAX];
   if (__system_property_get(kServiceVersionPropertyName, value) == 0) {
     g_propservice_protocol_version = kProtocolVersion1;
-    __libc_format_log(ANDROID_LOG_WARN, "libc",
-                      "Using old property service protocol (\"%s\" is not set)",
-                      kServiceVersionPropertyName);
+    async_safe_format_log(ANDROID_LOG_WARN, "libc",
+                          "Using old property service protocol (\"%s\" is not set)",
+                          kServiceVersionPropertyName);
   } else {
     uint32_t version = static_cast<uint32_t>(atoll(value));
     if (version >= kProtocolVersion2) {
       g_propservice_protocol_version = kProtocolVersion2;
     } else {
-      __libc_format_log(ANDROID_LOG_WARN, "libc",
-                        "Using old property service protocol (\"%s\"=\"%s\")",
-                        kServiceVersionPropertyName, value);
+      async_safe_format_log(ANDROID_LOG_WARN, "libc",
+                            "Using old property service protocol (\"%s\"=\"%s\")",
+                            kServiceVersionPropertyName, value);
       g_propservice_protocol_version = kProtocolVersion1;
     }
   }
@@ -1286,49 +1284,49 @@ int __system_property_set(const char* key, const char* value) {
     PropertyServiceConnection connection;
     if (!connection.IsValid()) {
       errno = connection.GetLastError();
-      __libc_format_log(ANDROID_LOG_WARN,
-                        "libc",
-                        "Unable to set property \"%s\" to \"%s\": connection failed; errno=%d (%s)",
-                        key,
-                        value,
-                        errno,
-                        strerror(errno));
+      async_safe_format_log(ANDROID_LOG_WARN,
+                            "libc",
+                            "Unable to set property \"%s\" to \"%s\": connection failed; errno=%d (%s)",
+                            key,
+                            value,
+                            errno,
+                            strerror(errno));
       return -1;
     }
 
     SocketWriter writer(&connection);
     if (!writer.WriteUint32(PROP_MSG_SETPROP2).WriteString(key).WriteString(value).Send()) {
       errno = connection.GetLastError();
-      __libc_format_log(ANDROID_LOG_WARN,
-                        "libc",
-                        "Unable to set property \"%s\" to \"%s\": write failed; errno=%d (%s)",
-                        key,
-                        value,
-                        errno,
-                        strerror(errno));
+      async_safe_format_log(ANDROID_LOG_WARN,
+                            "libc",
+                            "Unable to set property \"%s\" to \"%s\": write failed; errno=%d (%s)",
+                            key,
+                            value,
+                            errno,
+                            strerror(errno));
       return -1;
     }
 
     int result = -1;
     if (!connection.RecvInt32(&result)) {
       errno = connection.GetLastError();
-      __libc_format_log(ANDROID_LOG_WARN,
-                        "libc",
-                        "Unable to set property \"%s\" to \"%s\": recv failed; errno=%d (%s)",
-                        key,
-                        value,
-                        errno,
-                        strerror(errno));
+      async_safe_format_log(ANDROID_LOG_WARN,
+                            "libc",
+                            "Unable to set property \"%s\" to \"%s\": recv failed; errno=%d (%s)",
+                            key,
+                            value,
+                            errno,
+                            strerror(errno));
       return -1;
     }
 
     if (result != PROP_SUCCESS) {
-      __libc_format_log(ANDROID_LOG_WARN,
-                        "libc",
-                        "Unable to set property \"%s\" to \"%s\": error code: 0x%x",
-                        key,
-                        value,
-                        result);
+      async_safe_format_log(ANDROID_LOG_WARN,
+                            "libc",
+                            "Unable to set property \"%s\" to \"%s\": error code: 0x%x",
+                            key,
+                            value,
+                            result);
       return -1;
     }
 
@@ -1383,7 +1381,7 @@ int __system_property_add(const char* name, unsigned int namelen, const char* va
   prop_area* pa = get_prop_area_for_name(name);
 
   if (!pa) {
-    __libc_format_log(ANDROID_LOG_ERROR, "libc", "Access denied adding property \"%s\"", name);
+    async_safe_format_log(ANDROID_LOG_ERROR, "libc", "Access denied adding property \"%s\"", name);
     return -1;
   }
 
@@ -1445,20 +1443,19 @@ bool __system_property_wait(const prop_info* pi,
 }
 
 const prop_info* __system_property_find_nth(unsigned n) {
-  if (bionic_get_application_target_sdk_version() >= __ANDROID_API_O__) {
-    __libc_fatal(
-        "__system_property_find_nth is not supported since Android O,"
-        " please use __system_property_foreach instead.");
-  }
-
-  find_nth_cookie cookie(n);
-
-  const int err = __system_property_foreach(find_nth_fn, &cookie);
-  if (err < 0) {
-    return nullptr;
-  }
-
-  return cookie.pi;
+  struct find_nth {
+    const uint32_t sought;
+    uint32_t current;
+    const prop_info* result;
+
+    explicit find_nth(uint32_t n) : sought(n), current(0), result(nullptr) {}
+    static void fn(const prop_info* pi, void* ptr) {
+      find_nth* self = reinterpret_cast<find_nth*>(ptr);
+      if (self->current++ == self->sought) self->result = pi;
+    }
+  } state(n);
+  __system_property_foreach(find_nth::fn, &state);
+  return state.result;
 }
 
 int __system_property_foreach(void (*propfn)(const prop_info* pi, void* cookie), void* cookie) {
@@ -1468,7 +1465,7 @@ int __system_property_foreach(void (*propfn)(const prop_info* pi, void* cookie),
 
   list_foreach(contexts, [propfn, cookie](context_node* l) {
     if (l->check_access_and_open()) {
-      l->pa()->foreach (propfn, cookie);
+      l->pa()->foreach(propfn, cookie);
     }
   });
   return 0;