From d11a352c4298c94e70a6845df1265cd870581ace Mon Sep 17 00:00:00 2001 From: LuK1337 Date: Mon, 7 Oct 2024 17:36:32 +0200 Subject: [PATCH] Fix prop override on Android V Change-Id: Iead5765395ffe4d8a5a8f93db4841c68e3c0b9b3 --- .../libc/bionic/system_property_api.cpp | 5 +++ .../libc/include/sys/_system_properties.h | 6 +++ .../include/system_properties/prop_area.h | 1 + .../system_properties/system_properties.h | 1 + .../libc/system_properties/prop_area.cpp | 43 +++++++++++++++++++ .../system_properties/system_properties.cpp | 30 +++++++++++++ main.cpp | 3 +- 7 files changed, 88 insertions(+), 1 deletion(-) diff --git a/aosp/bionic/libc/bionic/system_property_api.cpp b/aosp/bionic/libc/bionic/system_property_api.cpp index 051bc4c..bcec6c9 100644 --- a/aosp/bionic/libc/bionic/system_property_api.cpp +++ b/aosp/bionic/libc/bionic/system_property_api.cpp @@ -98,6 +98,11 @@ int __system_property_add(const char* name, unsigned int namelen, const char* va return system_properties.Add(name, namelen, value, valuelen); } +__BIONIC_WEAK_FOR_NATIVE_BRIDGE +int __system_property_del(const char* name) { + return system_properties.Delete(name); +} + __BIONIC_WEAK_FOR_NATIVE_BRIDGE uint32_t __system_property_serial(const prop_info* pi) { return system_properties.Serial(pi); diff --git a/aosp/bionic/libc/include/sys/_system_properties.h b/aosp/bionic/libc/include/sys/_system_properties.h index 744a45b..cf6581b 100644 --- a/aosp/bionic/libc/include/sys/_system_properties.h +++ b/aosp/bionic/libc/include/sys/_system_properties.h @@ -104,6 +104,12 @@ uint32_t __system_property_area_serial(void); */ int __system_property_add(const char* __name, unsigned int __name_length, const char* __value, unsigned int __value_length); +/* Delete a system property. +** +** Returns 0 on success, -1 if the property area is full. +*/ +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 ** that has write access to the property area, and that process diff --git a/aosp/bionic/libc/system_properties/include/system_properties/prop_area.h b/aosp/bionic/libc/system_properties/include/system_properties/prop_area.h index a69f90e..97cee43 100644 --- a/aosp/bionic/libc/system_properties/include/system_properties/prop_area.h +++ b/aosp/bionic/libc/system_properties/include/system_properties/prop_area.h @@ -110,6 +110,7 @@ class prop_area { const prop_info* find(const char* name); bool add(const char* name, unsigned int namelen, const char* value, unsigned int valuelen); + bool del(const char* name); bool foreach (void (*propfn)(const prop_info* pi, void* cookie), void* cookie); diff --git a/aosp/bionic/libc/system_properties/include/system_properties/system_properties.h b/aosp/bionic/libc/system_properties/include/system_properties/system_properties.h index cad29cc..eeb4f02 100644 --- a/aosp/bionic/libc/system_properties/include/system_properties/system_properties.h +++ b/aosp/bionic/libc/system_properties/include/system_properties/system_properties.h @@ -66,6 +66,7 @@ class SystemProperties { int Get(const char* name, char* value); int Update(prop_info* pi, const char* value, unsigned int len); int Add(const char* name, unsigned int namelen, const char* value, unsigned int valuelen); + int Delete(const char* name); uint32_t Serial(const prop_info* pi); uint32_t WaitAny(uint32_t old_serial); bool Wait(const prop_info* pi, uint32_t old_serial, uint32_t* new_serial_ptr, diff --git a/aosp/bionic/libc/system_properties/prop_area.cpp b/aosp/bionic/libc/system_properties/prop_area.cpp index 91b273c..5e0f955 100644 --- a/aosp/bionic/libc/system_properties/prop_area.cpp +++ b/aosp/bionic/libc/system_properties/prop_area.cpp @@ -368,6 +368,49 @@ bool prop_area::add(const char* name, unsigned int namelen, const char* value, return find_property(root_node(), name, namelen, value, valuelen, true); } +bool prop_area::del(const char* name) { + prop_bt* const trie = root_node(); + if (!trie) return false; + + const char* remaining_name = name; + prop_bt* current = trie; + while (true) { + const char* sep = strchr(remaining_name, '.'); + const bool want_subtree = (sep != nullptr); + const uint32_t substr_size = (want_subtree) ? sep - remaining_name : strlen(remaining_name); + + if (!substr_size) { + return false; + } + + prop_bt* root = nullptr; + uint_least32_t children_offset = atomic_load_explicit(¤t->children, memory_order_relaxed); + if (children_offset != 0) { + root = to_prop_bt(¤t->children); + } + + if (!root) { + return false; + } + + current = find_prop_bt(root, remaining_name, substr_size, false); + if (!current) { + return false; + } + + if (!want_subtree) break; + + remaining_name = sep + 1; + } + + uint_least32_t prop_offset = atomic_load_explicit(¤t->prop, memory_order_relaxed); + if (prop_offset != 0) { + uint_least32_t new_offset = 0; + atomic_store_explicit(¤t->prop, new_offset, memory_order_release); + } + return true; +} + bool prop_area::foreach (void (*propfn)(const prop_info* pi, void* cookie), void* cookie) { return foreach_property(root_node(), propfn, cookie); } diff --git a/aosp/bionic/libc/system_properties/system_properties.cpp b/aosp/bionic/libc/system_properties/system_properties.cpp index d7c441b..7647584 100644 --- a/aosp/bionic/libc/system_properties/system_properties.cpp +++ b/aosp/bionic/libc/system_properties/system_properties.cpp @@ -294,6 +294,36 @@ int SystemProperties::Add(const char* name, unsigned int namelen, const char* va return 0; } +int SystemProperties::Delete(const char* name) { + if (!initialized_) { + return -1; + } + + prop_area* serial_pa = contexts_->GetSerialPropArea(); + if (serial_pa == nullptr) { + return -1; + } + + prop_area* pa = contexts_->GetPropAreaForName(name); + if (!pa) { + async_safe_format_log(ANDROID_LOG_ERROR, "libc", "Access denied deleting property \"%s\"", name); + return -1; + } + + bool ret = pa->del(name); + if (!ret) { + return -1; + } + + // There is only a single mutator, but we want to make sure that + // updates are visible to a reader waiting for the update. + atomic_store_explicit(serial_pa->serial(), + atomic_load_explicit(serial_pa->serial(), memory_order_relaxed) + 1, + memory_order_release); + __futex_wake(serial_pa->serial(), INT32_MAX); + return 0; +} + // Wait for non-locked serial, and retrieve it with acquire semantics. uint32_t SystemProperties::Serial(const prop_info* pi) { uint32_t serial = load_const_atomic(&pi->serial, memory_order_acquire); diff --git a/main.cpp b/main.cpp index c66dd4e..bc7550e 100644 --- a/main.cpp +++ b/main.cpp @@ -9,7 +9,8 @@ void property_override(char const prop[], char const value[], bool add = false) auto pi = (prop_info *) __system_property_find(prop); if (pi != nullptr) { - __system_property_update(pi, value, strlen(value)); + __system_property_del(prop); + __system_property_add(prop, strlen(prop), value, strlen(value)); } else if (add) { __system_property_add(prop, strlen(prop), value, strlen(value)); }