diff --git a/jni/Android.mk b/jni/Android.mk index cd6a2160b..30d522e7f 100644 --- a/jni/Android.mk +++ b/jni/Android.mk @@ -34,7 +34,6 @@ LOCAL_SRC_FILES := \ magiskpolicy/sepolicy.c \ magiskpolicy/api.c \ resetprop/resetprop.cpp \ - resetprop/libc_logging.cpp \ resetprop/system_properties.cpp \ su/su.c \ su/activity.c \ diff --git a/jni/daemon/bootstages.c b/jni/daemon/bootstages.c index 6f3cc7721..a9f67808e 100644 --- a/jni/daemon/bootstages.c +++ b/jni/daemon/bootstages.c @@ -693,6 +693,9 @@ void post_fs_data(int client) { bind_mount(HOSTSFILE, "/system/etc/hosts"); } + // Initialize resetprop for the daemon + init_resetprop(); + // Start magiskhide if enabled char *hide_prop = getprop(MAGISKHIDE_PROP); if (hide_prop) { diff --git a/jni/resetprop/_system_properties.h b/jni/resetprop/_system_properties.h index 73baf8729..20dbf928c 100644 --- a/jni/resetprop/_system_properties.h +++ b/jni/resetprop/_system_properties.h @@ -62,38 +62,38 @@ __BEGIN_DECLS ** Map the property area from the specified filename. This ** method is for testing only. */ -int __system_property_set_filename(const char *filename); +int __system_property_set_filename2(const char *filename); /* ** Initialize the area to be used to store properties. Can ** only be done by a single process that has write access to ** the property area. */ -int __system_property_area_init(); +int __system_property_area_init2(); /* Read the global serial number of the system properties ** -** Called to predict if a series of cached __system_property_find -** objects will have seen __system_property_serial values change. +** Called to predict if a series of cached __system_property_find2 +** objects will have seen __system_property_serial2 values change. ** But also aids the converse, as changes in the global serial can -** also be used to predict if a failed __system_property_find +** also be used to predict if a failed __system_property_find2 ** could in-turn now find a new object; thus preventing the -** cycles of effort to poll __system_property_find. +** cycles of effort to poll __system_property_find2. ** ** Typically called at beginning of a cache cycle to signal if _any_ possible ** changes have occurred since last. If there is, one may check each individual -** __system_property_serial to confirm dirty, or __system_property_find -** to check if the property now exists. If a call to __system_property_add -** or __system_property_update has completed between two calls to -** __system_property_area_serial then the second call will return a larger +** __system_property_serial2 to confirm dirty, or __system_property_find2 +** to check if the property now exists. If a call to __system_property_add2 +** or __system_property_update2 has completed between two calls to +** __system_property_area_serial2 then the second call will return a larger ** value than the first call. Beware of race conditions as changes to the ** properties are not atomic, the main value of this call is to determine -** whether the expensive __system_property_find is worth retrying to see if +** whether the expensive __system_property_find2 is worth retrying to see if ** a property now exists. ** ** Returns the serial number on success, -1 on error. */ -uint32_t __system_property_area_serial(); +uint32_t __system_property_area_serial2(); /* Add a new system property. Can only be done by a single ** process that has write access to the property area, and @@ -103,7 +103,7 @@ uint32_t __system_property_area_serial(); ** ** Returns 0 on success, -1 if the property area is full. */ -int __system_property_add(const char *name, unsigned int namelen, const char *value, unsigned int valuelen); +int __system_property_add2(const char *name, unsigned int namelen, const char *value, unsigned int valuelen); /* Delete a new system property. Added in resetprop ** @@ -112,21 +112,21 @@ int __system_property_add(const char *name, unsigned int namelen, const char *va int __system_property_del(const char *name); /* Update the value of a system property returned by -** __system_property_find. Can only be done by a single process +** __system_property_find2. Can only be done by a single process ** that has write access to the property area, and that process ** must handle sequencing to ensure that only one property is ** updated at a time. ** ** Returns 0 on success, -1 if the parameters are incorrect. */ -int __system_property_update(prop_info *pi, const char *value, unsigned int len); +int __system_property_update2(prop_info *pi, const char *value, unsigned int len); /* Read the serial number of a system property returned by -** __system_property_find. +** __system_property_find2. ** ** Returns the serial number on success, -1 on error. */ -uint32_t __system_property_serial(const prop_info* pi); +uint32_t __system_property_serial2(const prop_info* pi); /* Initialize the system properties area in read only mode. * Should be done by all processes that need to read system @@ -134,10 +134,10 @@ uint32_t __system_property_serial(const prop_info* pi); * * Returns 0 on success, -1 otherwise. */ -int __system_properties_init(); +int __system_properties_init2(); -/* Deprecated: use __system_property_wait instead. */ -uint32_t __system_property_wait_any(uint32_t old_serial); +/* Deprecated: use __system_property_wait2 instead. */ +uint32_t __system_property_wait_any2(uint32_t old_serial); __END_DECLS diff --git a/jni/resetprop/libc_logging.cpp b/jni/resetprop/libc_logging.cpp deleted file mode 100644 index 72098fad7..000000000 --- a/jni/resetprop/libc_logging.cpp +++ /dev/null @@ -1,659 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "libc_logging.h" // Relative path so we can #include this .cpp file for testing. - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ -#include "_system_properties.h" - -static pthread_mutex_t g_abort_msg_lock = PTHREAD_MUTEX_INITIALIZER; - -__LIBC_HIDDEN__ abort_msg_t** __abort_message_ptr; // Accessible to __libc_init_common. - -// Must be kept in sync with frameworks/base/core/java/android/util/EventLog.java. -enum AndroidEventLogType { - EVENT_TYPE_INT = 0, - EVENT_TYPE_LONG = 1, - EVENT_TYPE_STRING = 2, - EVENT_TYPE_LIST = 3, - EVENT_TYPE_FLOAT = 4, -}; - -struct BufferOutputStream { - public: - BufferOutputStream(char* buffer, size_t size) : total(0) { - buffer_ = buffer; - end_ = buffer + size - 1; - pos_ = buffer_; - pos_[0] = '\0'; - } - - ~BufferOutputStream() { - } - - void Send(const char* data, int len) { - if (len < 0) { - len = strlen(data); - } - - total += len; - - while (len > 0) { - int avail = end_ - pos_; - if (avail == 0) { - return; - } - if (avail > len) { - avail = len; - } - memcpy(pos_, data, avail); - pos_ += avail; - pos_[0] = '\0'; - len -= avail; - } - } - - size_t total; - - private: - char* buffer_; - char* pos_; - char* end_; -}; - -struct FdOutputStream { - public: - FdOutputStream(int fd) : total(0), fd_(fd) { - } - - void Send(const char* data, int len) { - if (len < 0) { - len = strlen(data); - } - - total += len; - - while (len > 0) { - int rc = TEMP_FAILURE_RETRY(write(fd_, data, len)); - if (rc == -1) { - return; - } - data += rc; - len -= rc; - } - } - - size_t total; - - private: - int fd_; -}; - -/*** formatted output implementation - ***/ - -/* Parse a decimal string from 'format + *ppos', - * return the value, and writes the new position past - * the decimal string in '*ppos' on exit. - * - * NOTE: Does *not* handle a sign prefix. - */ -static unsigned parse_decimal(const char *format, int *ppos) { - const char* p = format + *ppos; - unsigned result = 0; - - for (;;) { - int ch = *p; - unsigned d = static_cast(ch - '0'); - - if (d >= 10U) { - break; - } - - result = result*10 + d; - p++; - } - *ppos = p - format; - return result; -} - -// Writes number 'value' in base 'base' into buffer 'buf' of size 'buf_size' bytes. -// Assumes that buf_size > 0. -static void format_unsigned(char* buf, size_t buf_size, uint64_t value, int base, bool caps) { - char* p = buf; - char* end = buf + buf_size - 1; - - // Generate digit string in reverse order. - while (value) { - unsigned d = value % base; - value /= base; - if (p != end) { - char ch; - if (d < 10) { - ch = '0' + d; - } else { - ch = (caps ? 'A' : 'a') + (d - 10); - } - *p++ = ch; - } - } - - // Special case for 0. - if (p == buf) { - if (p != end) { - *p++ = '0'; - } - } - *p = '\0'; - - // Reverse digit string in-place. - size_t length = p - buf; - for (size_t i = 0, j = length - 1; i < j; ++i, --j) { - char ch = buf[i]; - buf[i] = buf[j]; - buf[j] = ch; - } -} - -static void format_integer(char* buf, size_t buf_size, uint64_t value, char conversion) { - // Decode the conversion specifier. - int is_signed = (conversion == 'd' || conversion == 'i' || conversion == 'o'); - int base = 10; - if (conversion == 'x' || conversion == 'X') { - base = 16; - } else if (conversion == 'o') { - base = 8; - } - bool caps = (conversion == 'X'); - - if (is_signed && static_cast(value) < 0) { - buf[0] = '-'; - buf += 1; - buf_size -= 1; - value = static_cast(-static_cast(value)); - } - format_unsigned(buf, buf_size, value, base, caps); -} - -template -static void SendRepeat(Out& o, char ch, int count) { - char pad[8]; - memset(pad, ch, sizeof(pad)); - - const int pad_size = static_cast(sizeof(pad)); - while (count > 0) { - int avail = count; - if (avail > pad_size) { - avail = pad_size; - } - o.Send(pad, avail); - count -= avail; - } -} - -/* Perform formatted output to an output target 'o' */ -template -static void out_vformat(Out& o, const char* format, va_list args) { - int nn = 0; - - for (;;) { - int mm; - int padZero = 0; - int padLeft = 0; - char sign = '\0'; - int width = -1; - int prec = -1; - size_t bytelen = sizeof(int); - int slen; - char buffer[32]; /* temporary buffer used to format numbers */ - - char c; - - /* first, find all characters that are not 0 or '%' */ - /* then send them to the output directly */ - mm = nn; - do { - c = format[mm]; - if (c == '\0' || c == '%') - break; - mm++; - } while (1); - - if (mm > nn) { - o.Send(format+nn, mm-nn); - nn = mm; - } - - /* is this it ? then exit */ - if (c == '\0') - break; - - /* nope, we are at a '%' modifier */ - nn++; // skip it - - /* parse flags */ - for (;;) { - c = format[nn++]; - if (c == '\0') { /* single trailing '%' ? */ - c = '%'; - o.Send(&c, 1); - return; - } - else if (c == '0') { - padZero = 1; - continue; - } - else if (c == '-') { - padLeft = 1; - continue; - } - else if (c == ' ' || c == '+') { - sign = c; - continue; - } - break; - } - - /* parse field width */ - if ((c >= '0' && c <= '9')) { - nn --; - width = static_cast(parse_decimal(format, &nn)); - c = format[nn++]; - } - - /* parse precision */ - if (c == '.') { - prec = static_cast(parse_decimal(format, &nn)); - c = format[nn++]; - } - - /* length modifier */ - switch (c) { - case 'h': - bytelen = sizeof(short); - if (format[nn] == 'h') { - bytelen = sizeof(char); - nn += 1; - } - c = format[nn++]; - break; - case 'l': - bytelen = sizeof(long); - if (format[nn] == 'l') { - bytelen = sizeof(long long); - nn += 1; - } - c = format[nn++]; - break; - case 'z': - bytelen = sizeof(size_t); - c = format[nn++]; - break; - case 't': - bytelen = sizeof(ptrdiff_t); - c = format[nn++]; - break; - default: - ; - } - - /* conversion specifier */ - const char* str = buffer; - if (c == 's') { - /* string */ - str = va_arg(args, const char*); - if (str == NULL) { - str = "(null)"; - } - } else if (c == 'c') { - /* character */ - /* NOTE: char is promoted to int when passed through the stack */ - buffer[0] = static_cast(va_arg(args, int)); - buffer[1] = '\0'; - } else if (c == 'p') { - uint64_t value = reinterpret_cast(va_arg(args, void*)); - buffer[0] = '0'; - buffer[1] = 'x'; - format_integer(buffer + 2, sizeof(buffer) - 2, value, 'x'); - } else if (c == 'd' || c == 'i' || c == 'o' || c == 'u' || c == 'x' || c == 'X') { - /* integers - first read value from stack */ - uint64_t value; - int is_signed = (c == 'd' || c == 'i' || c == 'o'); - - /* NOTE: int8_t and int16_t are promoted to int when passed - * through the stack - */ - switch (bytelen) { - case 1: value = static_cast(va_arg(args, int)); break; - case 2: value = static_cast(va_arg(args, int)); break; - case 4: value = va_arg(args, uint32_t); break; - case 8: value = va_arg(args, uint64_t); break; - default: return; /* should not happen */ - } - - /* sign extension, if needed */ - if (is_signed) { - int shift = 64 - 8*bytelen; - value = static_cast((static_cast(value << shift)) >> shift); - } - - /* format the number properly into our buffer */ - format_integer(buffer, sizeof(buffer), value, c); - } else if (c == '%') { - buffer[0] = '%'; - buffer[1] = '\0'; - } else { - __assert(__FILE__, __LINE__, "conversion specifier unsupported"); - } - - /* if we are here, 'str' points to the content that must be - * outputted. handle padding and alignment now */ - - slen = strlen(str); - - if (sign != '\0' || prec != -1) { - __assert(__FILE__, __LINE__, "sign/precision unsupported"); - } - - if (slen < width && !padLeft) { - char padChar = padZero ? '0' : ' '; - SendRepeat(o, padChar, width - slen); - } - - o.Send(str, slen); - - if (slen < width && padLeft) { - char padChar = padZero ? '0' : ' '; - SendRepeat(o, padChar, width - slen); - } - } -} - -int __libc_format_buffer(char* buffer, size_t buffer_size, const char* format, ...) { - BufferOutputStream os(buffer, buffer_size); - va_list args; - va_start(args, format); - out_vformat(os, format, args); - va_end(args); - return os.total; -} - -int __libc_format_fd(int fd, const char* format, ...) { - FdOutputStream os(fd); - va_list args; - va_start(args, format); - out_vformat(os, format, args); - va_end(args); - return os.total; -} - -static int __libc_write_stderr(const char* tag, const char* msg) { - int fd = TEMP_FAILURE_RETRY(open("/dev/stderr", O_CLOEXEC | O_WRONLY | O_APPEND)); - if (fd == -1) { - return -1; - } - - iovec vec[4]; - vec[0].iov_base = const_cast(tag); - vec[0].iov_len = strlen(tag); - vec[1].iov_base = const_cast(": "); - vec[1].iov_len = 2; - vec[2].iov_base = const_cast(msg); - vec[2].iov_len = strlen(msg); - vec[3].iov_base = const_cast("\n"); - vec[3].iov_len = 1; - - int result = TEMP_FAILURE_RETRY(writev(fd, vec, 4)); - close(fd); - return result; -} - -static int __libc_open_log_socket() { - // ToDo: Ideally we want this to fail if the gid of the current - // process is AID_LOGD, but will have to wait until we have - // registered this in private/android_filesystem_config.h. We have - // found that all logd crashes thus far have had no problem stuffing - // the UNIX domain socket and moving on so not critical *today*. - - int log_fd = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0)); - if (log_fd < 0) { - return -1; - } - - if (fcntl(log_fd, F_SETFL, O_NONBLOCK) == -1) { - close(log_fd); - return -1; - } - - union { - struct sockaddr addr; - struct sockaddr_un addrUn; - } u; - memset(&u, 0, sizeof(u)); - u.addrUn.sun_family = AF_UNIX; - strlcpy(u.addrUn.sun_path, "/dev/socket/logdw", sizeof(u.addrUn.sun_path)); - - if (TEMP_FAILURE_RETRY(connect(log_fd, &u.addr, sizeof(u.addrUn))) != 0) { - close(log_fd); - return -1; - } - - return log_fd; -} - -struct cache { - const prop_info* pinfo; - uint32_t serial; - char c; -}; - -static void refresh_cache(struct cache *cache, const char *key) -{ - if (!cache->pinfo) { - cache->pinfo = __system_property_find(key); - if (!cache->pinfo) { - return; - } - } - uint32_t serial = __system_property_serial(cache->pinfo); - if (serial == cache->serial) { - return; - } - cache->serial = serial; - - char buf[PROP_VALUE_MAX]; - __system_property_read(cache->pinfo, 0, buf); - cache->c = buf[0]; -} - -// Timestamp state generally remains constant, since a change is -// rare, we can accept a trylock failure gracefully. -static pthread_mutex_t lock_clockid = PTHREAD_MUTEX_INITIALIZER; - -static clockid_t __android_log_clockid() -{ - static struct cache r_time_cache = { NULL, static_cast(-1), 0 }; - static struct cache p_time_cache = { NULL, static_cast(-1), 0 }; - char c; - - if (pthread_mutex_trylock(&lock_clockid)) { - // We are willing to accept some race in this context - if (!(c = p_time_cache.c)) { - c = r_time_cache.c; - } - } else { - static uint32_t serial; - uint32_t current_serial = __system_property_area_serial(); - if (current_serial != serial) { - refresh_cache(&r_time_cache, "ro.logd.timestamp"); - refresh_cache(&p_time_cache, "persist.logd.timestamp"); - serial = current_serial; - } - if (!(c = p_time_cache.c)) { - c = r_time_cache.c; - } - - pthread_mutex_unlock(&lock_clockid); - } - - return (tolower(c) == 'm') ? CLOCK_MONOTONIC : CLOCK_REALTIME; -} - -struct log_time { // Wire format - uint32_t tv_sec; - uint32_t tv_nsec; -}; - -int __libc_write_log(int priority, const char* tag, const char* msg) { - int main_log_fd = __libc_open_log_socket(); - if (main_log_fd == -1) { - // Try stderr instead. - return __libc_write_stderr(tag, msg); - } - - iovec vec[6]; - char log_id = (priority == ANDROID_LOG_FATAL) ? LOG_ID_CRASH : LOG_ID_MAIN; - vec[0].iov_base = &log_id; - vec[0].iov_len = sizeof(log_id); - uint16_t tid = gettid(); - vec[1].iov_base = &tid; - vec[1].iov_len = sizeof(tid); - timespec ts; - clock_gettime(__android_log_clockid(), &ts); - log_time realtime_ts; - realtime_ts.tv_sec = ts.tv_sec; - realtime_ts.tv_nsec = ts.tv_nsec; - vec[2].iov_base = &realtime_ts; - vec[2].iov_len = sizeof(realtime_ts); - - vec[3].iov_base = &priority; - vec[3].iov_len = 1; - vec[4].iov_base = const_cast(tag); - vec[4].iov_len = strlen(tag) + 1; - vec[5].iov_base = const_cast(msg); - vec[5].iov_len = strlen(msg) + 1; - - int result = TEMP_FAILURE_RETRY(writev(main_log_fd, vec, sizeof(vec) / sizeof(vec[0]))); - close(main_log_fd); - return result; -} - -int __libc_format_log_va_list(int priority, const char* tag, const char* format, va_list args) { - char buffer[1024]; - BufferOutputStream os(buffer, sizeof(buffer)); - out_vformat(os, format, args); - return __libc_write_log(priority, tag, buffer); -} - -int __libc_format_log(int priority, const char* tag, const char* format, ...) { - va_list args; - va_start(args, format); - int result = __libc_format_log_va_list(priority, tag, format, args); - va_end(args); - return result; -} - -static int __libc_android_log_event(int32_t tag, char type, const void* payload, size_t len) { - iovec vec[6]; - char log_id = LOG_ID_EVENTS; - vec[0].iov_base = &log_id; - vec[0].iov_len = sizeof(log_id); - uint16_t tid = gettid(); - vec[1].iov_base = &tid; - vec[1].iov_len = sizeof(tid); - timespec ts; - clock_gettime(__android_log_clockid(), &ts); - log_time realtime_ts; - realtime_ts.tv_sec = ts.tv_sec; - realtime_ts.tv_nsec = ts.tv_nsec; - vec[2].iov_base = &realtime_ts; - vec[2].iov_len = sizeof(realtime_ts); - - vec[3].iov_base = &tag; - vec[3].iov_len = sizeof(tag); - vec[4].iov_base = &type; - vec[4].iov_len = sizeof(type); - vec[5].iov_base = const_cast(payload); - vec[5].iov_len = len; - - int event_log_fd = __libc_open_log_socket(); - - if (event_log_fd == -1) { - return -1; - } - int result = TEMP_FAILURE_RETRY(writev(event_log_fd, vec, sizeof(vec) / sizeof(vec[0]))); - close(event_log_fd); - return result; -} - -void __libc_android_log_event_int(int32_t tag, int value) { - __libc_android_log_event(tag, EVENT_TYPE_INT, &value, sizeof(value)); -} - -void __libc_android_log_event_uid(int32_t tag) { - __libc_android_log_event_int(tag, getuid()); -} - -void __fortify_chk_fail(const char* msg, uint32_t tag) { - if (tag != 0) { - __libc_android_log_event_uid(tag); - } - __libc_fatal("FORTIFY: %s", msg); -} - -void __libc_fatal_no_abort(const char* format, ...) { - va_list args; - va_start(args, format); - __libc_fatal(format, args); - va_end(args); -} - -void __libc_fatal(const char* format, ...) { - va_list args; - va_start(args, format); - __libc_fatal(format, args); - va_end(args); - abort(); -} \ No newline at end of file diff --git a/jni/resetprop/libc_logging.h b/jni/resetprop/libc_logging.h deleted file mode 100644 index 31abc38a5..000000000 --- a/jni/resetprop/libc_logging.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _LIBC_LOGGING_H -#define _LIBC_LOGGING_H - -#include -#include -#include -#include - -__BEGIN_DECLS - -enum { - ANDROID_LOG_UNKNOWN = 0, - ANDROID_LOG_DEFAULT, /* only for SetMinPriority() */ - - ANDROID_LOG_VERBOSE, - ANDROID_LOG_DEBUG, - ANDROID_LOG_INFO, - ANDROID_LOG_WARN, - ANDROID_LOG_ERROR, - ANDROID_LOG_FATAL, - - ANDROID_LOG_SILENT, /* only for SetMinPriority(); must be last */ -}; - -enum { - LOG_ID_MIN = 0, - - LOG_ID_MAIN = 0, - LOG_ID_RADIO = 1, - LOG_ID_EVENTS = 2, - LOG_ID_SYSTEM = 3, - LOG_ID_CRASH = 4, - - LOG_ID_MAX -}; - -struct abort_msg_t { - size_t size; - char msg[0]; -}; - -// -// Formats a message to the log (priority 'fatal'), then aborts. -// - -__LIBC_HIDDEN__ __noreturn void __libc_fatal(const char* format, ...) __printflike(1, 2); - -// -// Formats a message to the log (priority 'fatal'), but doesn't abort. -// Used by the malloc implementation to ensure that debuggerd dumps memory -// around the bad address. -// - -__LIBC_HIDDEN__ void __libc_fatal_no_abort(const char* format, ...) - __printflike(1, 2); - -// -// Formatting routines for the C library's internal debugging. -// Unlike the usual alternatives, these don't allocate, and they don't drag in all of stdio. -// - -__LIBC_HIDDEN__ int __libc_format_buffer(char* buffer, size_t buffer_size, const char* format, ...) - __printflike(3, 4); - -__LIBC_HIDDEN__ int __libc_format_fd(int fd, const char* format, ...) - __printflike(2, 3); - -__LIBC_HIDDEN__ int __libc_format_log(int priority, const char* tag, const char* format, ...) - __printflike(3, 4); - -__LIBC_HIDDEN__ int __libc_format_log_va_list(int priority, const char* tag, const char* format, - va_list ap); - -__LIBC_HIDDEN__ int __libc_write_log(int priority, const char* tag, const char* msg); - -// -// Event logging. -// - -__LIBC_HIDDEN__ void __libc_android_log_event_int(int32_t tag, int value); -__LIBC_HIDDEN__ void __libc_android_log_event_uid(int32_t tag); - -__LIBC_HIDDEN__ __noreturn void __fortify_chk_fail(const char* msg, uint32_t event_tag); - -__END_DECLS - -#endif diff --git a/jni/resetprop/resetprop.cpp b/jni/resetprop/resetprop.cpp index 3d2ff0edc..613e5cbab 100644 --- a/jni/resetprop/resetprop.cpp +++ b/jni/resetprop/resetprop.cpp @@ -11,7 +11,7 @@ * * Functions that need to be patched/added in system_properties.cpp * - * int __system_properties_init() + * int __system_properties_init2() * on android 7, first tear down the everything then let it initialize again: * if (initialized) { * //list_foreach(contexts, [](context_node* l) { l->reset_access(); }); @@ -123,7 +123,7 @@ static int usage(char* arg0) { int init_resetprop() { PRINT_D("resetprop: Initializing...\n"); - if (__system_properties_init()) { + if (__system_properties_init2()) { PRINT_E("resetprop: Initialize error\n"); return -1; } @@ -136,12 +136,12 @@ static void read_prop_info(void* cookie, const char *name, const char *value, ui // Get prop by name, return string (should free manually!) char *getprop(const char *name) { - const prop_info *pi = __system_property_find(name); + const prop_info *pi = __system_property_find2(name); if (pi == NULL) { return NULL; } char value[PROP_VALUE_MAX]; - __system_property_read_callback(pi, read_prop_info, value); + __system_property_read_callback2(pi, read_prop_info, value); PRINT_D("resetprop: getprop [%s]: [%s]\n", name, value); return strdup(value); } @@ -158,16 +158,16 @@ int setprop2(const char *name, const char *value, const int trigger) { free(check); if (trigger) { if (!strncmp(name, "ro.", 3)) deleteprop(name); - ret = __system_property_set(name, value); + ret = __system_property_set2(name, value); } else { - ret = __system_property_update((prop_info*) __system_property_find(name), value, strlen(value)); + ret = __system_property_update2((prop_info*) __system_property_find2(name), value, strlen(value)); } } else { PRINT_D("resetprop: New prop [%s]\n", name); if (trigger) { - ret = __system_property_set(name, value); + ret = __system_property_set2(name, value); } else { - ret = __system_property_add(name, strlen(name), value, strlen(value)); + ret = __system_property_add2(name, strlen(name), value, strlen(value)); } } @@ -276,6 +276,8 @@ int resetprop_main(int argc, char *argv[]) { } } + init_resetprop(); + if (file) { return read_prop_file(filename, trigger); } else if (del) { diff --git a/jni/resetprop/system_properties.cpp b/jni/resetprop/system_properties.cpp index 2c26bc5c7..20c0adf25 100644 --- a/jni/resetprop/system_properties.cpp +++ b/jni/resetprop/system_properties.cpp @@ -54,11 +54,12 @@ #include "_system_properties.h" #include "system_properties.h" +// #include + #include "ErrnoRestorer.h" #include "bionic_futex.h" #include "bionic_lock.h" #include "bionic_macros.h" -#include "libc_logging.h" static constexpr int PROP_FILENAME_MAX = 1024; @@ -90,6 +91,16 @@ static const char* kServiceVersionPropertyName = "ro.property_service.version"; * +-----+ +-----+ +-----+ +===========+ */ +// This is a alternative implementation for async_safe_format_buffer +// A workaround to not include the async_safe header +static int async_safe_format_buffer(char * s, size_t n, const char * format, ...) { + va_list vl; + va_start(vl, format); + int ret = vsnprintf(s, n, format, vl); + va_end(vl); + return ret; +} + // Represents a node in the trie. struct prop_bt { uint32_t namelen; @@ -202,17 +213,9 @@ 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. -prop_area* __system_property_area__ = nullptr; +// Change to static, we don't want to use the global libc reference +static prop_area* __system_property_area__ = nullptr; static char property_filename[PROP_FILENAME_MAX] = PROP_FILENAME; static size_t pa_data_size; @@ -238,8 +241,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 @@ -694,9 +697,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; } } @@ -704,14 +707,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(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; @@ -872,7 +867,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; @@ -907,7 +903,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; } @@ -930,7 +927,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; @@ -1145,7 +1143,7 @@ static void free_and_unmap_contexts() { } } -int __system_properties_init() { +int __system_properties_init2() { // This is called from __libc_init_common, and should leave errno at 0 (http://b/37248982). ErrnoRestorer errno_restorer; @@ -1175,7 +1173,7 @@ int __system_properties_init() { return 0; } -int __system_property_set_filename(const char* filename) { +int __system_property_set_filename2(const char* filename) { size_t len = strlen(filename); if (len >= sizeof(property_filename)) return -1; @@ -1183,7 +1181,7 @@ int __system_property_set_filename(const char* filename) { return 0; } -int __system_property_area_init() { +int __system_property_area_init2() { free_and_unmap_contexts(); mkdir(property_filename, S_IRWXU | S_IXGRP | S_IXOTH); if (!initialize_properties()) { @@ -1204,23 +1202,23 @@ int __system_property_area_init() { return fsetxattr_failed ? -2 : 0; } -uint32_t __system_property_area_serial() { +uint32_t __system_property_area_serial2() { prop_area* pa = __system_property_area__; if (!pa) { return -1; } - // Make sure this read fulfilled before __system_property_serial + // Make sure this read fulfilled before __system_property_serial2 return atomic_load_explicit(pa->serial(), memory_order_acquire); } -const prop_info* __system_property_find(const char* name) { +const prop_info* __system_property_find2(const char* name) { if (!__system_property_area__) { return nullptr; } 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; } @@ -1234,7 +1232,6 @@ int __system_property_del(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); return 1; } @@ -1257,9 +1254,9 @@ static inline uint_least32_t load_const_atomic(const atomic_uint_least32_t* s, m return atomic_load_explicit(non_const_s, mo); } -int __system_property_read(const prop_info* pi, char* name, char* value) { +int __system_property_read2(const prop_info* pi, char* name, char* value) { while (true) { - uint32_t serial = __system_property_serial(pi); // acquire semantics + uint32_t serial = __system_property_serial2(pi); // acquire semantics size_t len = SERIAL_VALUE_LEN(serial); memcpy(value, pi->value, len + 1); // TODO: Fix the synchronization scheme here. @@ -1274,34 +1271,34 @@ int __system_property_read(const prop_info* pi, char* name, char* value) { if (serial == load_const_atomic(&(pi->serial), memory_order_relaxed)) { 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); - } + // if (namelen >= PROP_NAME_MAX) { + // async_safe_format_log(ANDROID_LOG_ERROR, "libc", + // "The property name length for \"%s\" is >= %d;" + // " please use __system_property_read_callback2" + // " to read this property. (the name is truncated to \"%s\")", + // pi->name, PROP_NAME_MAX - 1, name); + // } } return len; } } } -void __system_property_read_callback(const prop_info* pi, +void __system_property_read_callback2(const prop_info* pi, void (*callback)(void* cookie, const char* name, const char* value, uint32_t serial), void* cookie) { while (true) { - uint32_t serial = __system_property_serial(pi); // acquire semantics + uint32_t serial = __system_property_serial2(pi); // acquire semantics size_t len = SERIAL_VALUE_LEN(serial); char value_buf[len + 1]; memcpy(value_buf, pi->value, len); value_buf[len] = '\0'; - // TODO: see todo in __system_property_read function + // TODO: see todo in __system_property_read2 function atomic_thread_fence(memory_order_acquire); if (serial == load_const_atomic(&(pi->serial), memory_order_relaxed)) { callback(cookie, pi->name, value_buf, serial); @@ -1310,11 +1307,11 @@ void __system_property_read_callback(const prop_info* pi, } } -int __system_property_get(const char* name, char* value) { - const prop_info* pi = __system_property_find(name); +int __system_property_get2(const char* name, char* value) { + const prop_info* pi = __system_property_find2(name); if (pi != 0) { - return __system_property_read(pi, nullptr, value); + return __system_property_read2(pi, nullptr, value); } else { value[0] = 0; return 0; @@ -1328,25 +1325,25 @@ static atomic_uint_least32_t g_propservice_protocol_version = 0; static void detect_protocol_version() { char value[PROP_VALUE_MAX]; - if (__system_property_get(kServiceVersionPropertyName, value) == 0) { + if (__system_property_get2(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(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; } } } -int __system_property_set(const char* key, const char* value) { +int __system_property_set2(const char* key, const char* value) { if (key == nullptr) return -1; if (value == nullptr) value = ""; if (strlen(value) >= PROP_VALUE_MAX) return -1; @@ -1370,50 +1367,50 @@ int __system_property_set(const char* key, const char* value) { // Use proper protocol 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)); + // errno = connection.GetLastError(); + // 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)); + // errno = connection.GetLastError(); + // 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)); + // errno = connection.GetLastError(); + // 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; } @@ -1421,7 +1418,7 @@ int __system_property_set(const char* key, const char* value) { } } -int __system_property_update(prop_info* pi, const char* value, unsigned int len) { +int __system_property_update2(prop_info* pi, const char* value, unsigned int len) { if (len >= PROP_VALUE_MAX) { return -1; } @@ -1451,7 +1448,7 @@ int __system_property_update(prop_info* pi, const char* value, unsigned int len) return 0; } -int __system_property_add(const char* name, unsigned int namelen, const char* value, +int __system_property_add2(const char* name, unsigned int namelen, const char* value, unsigned int valuelen) { if (valuelen >= PROP_VALUE_MAX) { return -1; @@ -1468,7 +1465,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; } @@ -1488,7 +1485,7 @@ int __system_property_add(const char* name, unsigned int namelen, const char* va } // Wait for non-locked serial, and retrieve it with acquire semantics. -uint32_t __system_property_serial(const prop_info* pi) { +uint32_t __system_property_serial2(const prop_info* pi) { uint32_t serial = load_const_atomic(&pi->serial, memory_order_acquire); while (SERIAL_DIRTY(serial)) { __futex_wait(const_cast<_Atomic(uint_least32_t)*>(&pi->serial), serial, nullptr); @@ -1497,13 +1494,13 @@ uint32_t __system_property_serial(const prop_info* pi) { return serial; } -uint32_t __system_property_wait_any(uint32_t old_serial) { +uint32_t __system_property_wait_any2(uint32_t old_serial) { uint32_t new_serial; - __system_property_wait(nullptr, old_serial, &new_serial, nullptr); + __system_property_wait2(nullptr, old_serial, &new_serial, nullptr); return new_serial; } -bool __system_property_wait(const prop_info* pi, +bool __system_property_wait2(const prop_info* pi, uint32_t old_serial, uint32_t* new_serial_ptr, const timespec* relative_timeout) { @@ -1529,33 +1526,30 @@ bool __system_property_wait(const prop_info* pi, return true; } -/* Deprecated, we won't use it anyways */ +const prop_info* __system_property_find_nth2(unsigned n) { + struct find_nth { + const uint32_t sought; + uint32_t current; + const prop_info* result; -// 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."); -// } + 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(ptr); + if (self->current++ == self->sought) self->result = pi; + } + } state(n); + __system_property_foreach2(find_nth::fn, &state); + return state.result; +} -// find_nth_cookie cookie(n); - -// const int err = __system_property_foreach(find_nth_fn, &cookie); -// if (err < 0) { -// return nullptr; -// } - -// return cookie.pi; -// } - -int __system_property_foreach(void (*propfn)(const prop_info* pi, void* cookie), void* cookie) { +int __system_property_foreach2(void (*propfn)(const prop_info* pi, void* cookie), void* cookie) { if (!__system_property_area__) { return -1; } 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; diff --git a/jni/resetprop/system_properties.h b/jni/resetprop/system_properties.h index b55566e69..ab51ce21c 100644 --- a/jni/resetprop/system_properties.h +++ b/jni/resetprop/system_properties.h @@ -43,30 +43,30 @@ typedef struct prop_info prop_info; /* * Sets system property `key` to `value`, creating the system property if it doesn't already exist. */ -int __system_property_set(const char* key, const char* value) __INTRODUCED_IN(12); +int __system_property_set2(const char* key, const char* value) __INTRODUCED_IN(12); /* * Returns a `prop_info` corresponding system property `name`, or nullptr if it doesn't exist. - * Use __system_property_read_callback to query the current value. + * Use __system_property_read_callback2 to query the current value. * * Property lookup is expensive, so it can be useful to cache the result of this function. */ -const prop_info* __system_property_find(const char* name); +const prop_info* __system_property_find2(const char* name); /* * Calls `callback` with a consistent trio of name, value, and serial number for property `pi`. */ -void __system_property_read_callback(const prop_info *pi, +void __system_property_read_callback2(const prop_info *pi, void (*callback)(void* cookie, const char *name, const char *value, uint32_t serial), - void* cookie) __INTRODUCED_IN_FUTURE; + void* cookie) __INTRODUCED_IN(26); /* * Passes a `prop_info` for each system property to the provided - * callback. Use __system_property_read_callback() to read the value. + * callback. Use __system_property_read_callback2() to read the value. * * This method is for inspecting and debugging the property system, and not generally useful. */ -int __system_property_foreach(void (*propfn)(const prop_info* pi, void* cookie), void* cookie) +int __system_property_foreach2(void (*propfn)(const prop_info* pi, void* cookie), void* cookie) __INTRODUCED_IN(19); /* @@ -82,20 +82,20 @@ int __system_property_foreach(void (*propfn)(const prop_info* pi, void* cookie), * timed out. */ struct timespec; -bool __system_property_wait(const prop_info* pi, +bool __system_property_wait2(const prop_info* pi, uint32_t old_serial, uint32_t* new_serial_ptr, const struct timespec* relative_timeout) - __INTRODUCED_IN_FUTURE; + __INTRODUCED_IN(26); /* Deprecated. In Android O and above, there's no limit on property name length. */ #define PROP_NAME_MAX 32 -/* Deprecated. Use __system_property_read_callback instead. */ -int __system_property_read(const prop_info *pi, char *name, char *value); -/* Deprecated. Use __system_property_read_callback instead. */ -int __system_property_get(const char *name, char *value); -/* Deprecated. Use __system_property_foreach instead. Aborts in Android O and above. */ -const prop_info *__system_property_find_nth(unsigned n) __REMOVED_IN(26); +/* Deprecated. Use __system_property_read_callback2 instead. */ +int __system_property_read2(const prop_info* pi, char* name, char* value); +/* Deprecated. Use __system_property_read_callback2 instead. */ +int __system_property_get2(const char* name, char* value); +/* Deprecated. Use __system_property_foreach2 instead. */ +const prop_info* __system_property_find_nth2(unsigned n); __END_DECLS