#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;
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;
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
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;
}
}
// 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;
}
}
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;
}
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;
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;
}
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;
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;
}
}
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;
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;
}
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;
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;
}
}
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;
}
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;
}
}
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) {
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;