diff --git a/native/jni/Android.mk b/native/jni/Android.mk index b079aa82b..3fbca5135 100644 --- a/native/jni/Android.mk +++ b/native/jni/Android.mk @@ -43,8 +43,8 @@ LOCAL_SRC_FILES := \ magiskhide/magiskhide.cpp \ magiskhide/proc_monitor.cpp \ magiskhide/hide_utils.cpp \ - resetprop/persist_properties.c \ - resetprop/resetprop.c \ + resetprop/persist_properties.cpp \ + resetprop/resetprop.cpp \ resetprop/system_property_api.cpp \ resetprop/system_property_set.cpp \ su/su.c \ diff --git a/native/jni/resetprop/_resetprop.h b/native/jni/resetprop/_resetprop.h index 5266fdbf9..7984909b7 100644 --- a/native/jni/resetprop/_resetprop.h +++ b/native/jni/resetprop/_resetprop.h @@ -8,21 +8,49 @@ #include "resetprop/private/system_properties.h" #include "logging.h" -extern int prop_verbose; - struct prop_t { char *name; char value[PROP_VALUE_MAX]; + prop_t() = default; + prop_t(const char *name) { + this->name = strdup(name); + } + prop_t(const char *name, const char *value) { + this->name = strdup(name); + strcpy(this->value, value); + } + prop_t& operator= (prop_t&& prop) { + if (this != &prop) { + free(name); + name = prop.name; + strcpy(value, prop.value); + prop.name = nullptr; + } + return *this; + }; + ~prop_t() { + free(name); + } }; struct read_cb_t { - void (*func)(const char *name, const char *value, void *cookie); - void *cookie; + void (*cb)(const char *, const char *, void *); + void *arg; + read_cb_t() = default; + read_cb_t(void (*cb)(const char *, const char *, void *), void *arg) + : cb(cb), arg(arg) {} + void exec(const char *name, const char *value) { + cb(name, value, arg); + } }; +#define PERSISTENT_PROPERTY_DIR "/data/property" + +extern bool use_pb; + char *persist_getprop(const char *name); -void persist_getprop_all(struct read_cb_t *read_cb); +void persist_getprop_all(read_cb_t *read_cb); bool persist_deleteprop(const char *name); -void collect_props(const char *name, const char *value, void *prop_list); +void collect_props(const char *name, const char *value, void *v_plist); #endif //MAGISK_PROPS_H diff --git a/native/jni/resetprop/persist_properties.c b/native/jni/resetprop/persist_properties.cpp similarity index 61% rename from native/jni/resetprop/persist_properties.c rename to native/jni/resetprop/persist_properties.cpp index 90fb77fb8..889a14c8f 100644 --- a/native/jni/resetprop/persist_properties.c +++ b/native/jni/resetprop/persist_properties.cpp @@ -11,9 +11,7 @@ #include "_resetprop.h" #include "utils.h" -#include "vector.h" - -#define PERSISTENT_PROPERTY_DIR "/data/property" +#include "array.h" /* *********************************************************************** * Auto generated header and constant definitions compiled from @@ -89,7 +87,7 @@ const pb_field_t PersistentProperties_fields[2] = { * ***************************/ static bool name_decode(pb_istream_t *stream, const pb_field_t *field, void **arg) { - uint8_t *name = xmalloc(stream->bytes_left + 1); + uint8_t *name = (uint8_t *) xmalloc(stream->bytes_left + 1); name[stream->bytes_left] = '\0'; if (!pb_read(stream, name, stream->bytes_left)) return false; @@ -98,7 +96,8 @@ static bool name_decode(pb_istream_t *stream, const pb_field_t *field, void **ar } static bool name_encode(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) { - return pb_encode_tag_for_field(stream, field) && pb_encode_string(stream, *arg, strlen(*arg)); + return pb_encode_tag_for_field(stream, field) && + pb_encode_string(stream, (const pb_byte_t *) *arg, strlen((const char *) *arg)); } static bool prop_decode(pb_istream_t *stream, const pb_field_t *field, void **arg) { @@ -106,8 +105,7 @@ static bool prop_decode(pb_istream_t *stream, const pb_field_t *field, void **ar prop.name.funcs.decode = name_decode; if (!pb_decode(stream, PersistentProperties_PersistentPropertyRecord_fields, &prop)) return false; - struct read_cb_t *read_cb = *arg; - read_cb->func(prop.name.arg, prop.value, read_cb->cookie); + ((read_cb_t *) *arg)->exec((const char *) prop.name.arg, prop.value); return true; } @@ -115,19 +113,14 @@ static bool prop_encode(pb_ostream_t *stream, const pb_field_t *field, void * co PersistentProperties_PersistentPropertyRecord prop = {}; prop.name.funcs.encode = name_encode; prop.has_value = true; - struct vector *v = *arg; - struct prop_t *e; - vec_for_each(v, e) { - if (e == NULL) - continue; + Array &prop_list = *(Array *) *arg; + for (auto &p : prop_list) { if (!pb_encode_tag_for_field(stream, field)) return false; - prop.name.arg = e->name; - strcpy(prop.value, e->value); + prop.name.arg = p.name; + strcpy(prop.value, p.value); if (!pb_encode_submessage(stream, PersistentProperties_PersistentPropertyRecord_fields, &prop)) return false; - free(e->name); - free(e); } return true; } @@ -139,107 +132,111 @@ static bool write_callback(pb_ostream_t *stream, const uint8_t *buf, size_t coun static pb_ostream_t create_ostream(const char *filename) { int fd = creat(filename, 0644); - pb_ostream_t o = {&write_callback, (void*)(intptr_t)fd, SIZE_MAX, 0}; + pb_ostream_t o = { + .callback = write_callback, + .state = (void*)(intptr_t)fd, + .max_size = SIZE_MAX, + .bytes_written = 0, + }; return o; } static void pb_getprop_cb(const char *name, const char *value, void *v) { - struct prop_t *prop = v; + struct prop_t *prop = static_cast(v); if (prop->name && strcmp(name, prop->name) == 0) { strcpy(prop->value, value); - prop->name = NULL; + free(prop->name); + prop->name = nullptr; } } -void persist_getprop_all(struct read_cb_t *read_cb) { - if (access(PERSISTENT_PROPERTY_DIR "/persistent_properties", R_OK) == 0) { - LOGD("resetprop: decode with protobuf from [" PERSISTENT_PROPERTY_DIR "/persistent_properties]\n"); - PersistentProperties props = PersistentProperties_init_zero; - props.properties.funcs.decode = prop_decode; - props.properties.arg = read_cb; - uint8_t *buf; - size_t size; - mmap_ro(PERSISTENT_PROPERTY_DIR "/persistent_properties", (void **) &buf, &size); - pb_istream_t stream = pb_istream_from_buffer(buf, size); - pb_decode(&stream, PersistentProperties_fields, &props); - munmap(buf, size); +static void pb_getprop_all(read_cb_t *read_cb) { + LOGD("resetprop: decode with protobuf [" PERSISTENT_PROPERTY_DIR "/persistent_properties]\n"); + PersistentProperties props = {}; + props.properties.funcs.decode = prop_decode; + props.properties.arg = read_cb; + uint8_t *buf; + size_t size; + mmap_ro(PERSISTENT_PROPERTY_DIR "/persistent_properties", (void **) &buf, &size); + pb_istream_t stream = pb_istream_from_buffer(buf, size); + pb_decode(&stream, PersistentProperties_fields, &props); + munmap(buf, size); +} + +static void file_getprop(const char *name, char *value) { + value[0] = '\0'; + char path[PATH_MAX]; + snprintf(path, sizeof(path), PERSISTENT_PROPERTY_DIR "/%s", name); + int fd = open(path, O_RDONLY | O_CLOEXEC); + if (fd < 0) + return; + LOGD("resetprop: read prop from [%s]\n", path); + value[read(fd, value, sizeof(PROP_VALUE_MAX))] = '\0'; // Null terminate the read value + close(fd); +} + +void persist_getprop_all(read_cb_t *read_cb) { + if (use_pb) { + pb_getprop_all(read_cb); } else { DIR *dir = opendir(PERSISTENT_PROPERTY_DIR); struct dirent *entry; while ((entry = readdir(dir))) { if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0 ) continue; - char *value = persist_getprop(entry->d_name); - if (value) { - read_cb->func(strdup(entry->d_name), value, read_cb->cookie); - free(value); - } + char value[PROP_VALUE_MAX]; + file_getprop(entry->d_name, value); + if (value[0]) + read_cb->exec(entry->d_name, value); } } } char *persist_getprop(const char *name) { - struct prop_t prop; - prop.name = (char *) name; - if (access(PERSISTENT_PROPERTY_DIR "/persistent_properties", R_OK) == 0) { - struct read_cb_t read_cb = { - .func = pb_getprop_cb, - .cookie = &prop - }; - persist_getprop_all(&read_cb); - if (prop.name) - return NULL; + prop_t prop(name); + if (use_pb) { + struct read_cb_t read_cb(pb_getprop_cb, &prop); + pb_getprop_all(&read_cb); + if (prop.name == nullptr) + return strdup(prop.value); } else { // Try to read from file - char path[PATH_MAX]; - snprintf(path, sizeof(path), PERSISTENT_PROPERTY_DIR "/%s", name); - int fd = open(path, O_RDONLY | O_CLOEXEC); - if (fd < 0) - return NULL; - LOGD("resetprop: read prop from [%s]\n", path); - prop.value[read(fd, prop.value, sizeof(PROP_VALUE_MAX))] = '\0'; // Null terminate the read value - close(fd); + char value[PROP_VALUE_MAX]; + file_getprop(name, value); + if (value[0]) + return strdup(value); } - return strdup(prop.value); + return nullptr; } bool persist_deleteprop(const char *name) { - if (access(PERSISTENT_PROPERTY_DIR "/persistent_properties", R_OK) == 0) { - struct vector v; - vec_init(&v); - struct read_cb_t read_cb = { - .func = collect_props, - .cookie = &v - }; + if (use_pb) { + auto prop_list = Array(); + struct read_cb_t read_cb(collect_props, &prop_list); persist_getprop_all(&read_cb); - struct prop_t *p; - bool reencode = false; - vec_for_each(&v, p) { - if (strcmp(p->name, name) == 0) { - // Remove the prop from the list - free(p->name); - free(p); - vec_cur(&v) = NULL; - reencode = true; - break; + + for (auto it = prop_list.begin(); it != prop_list.end(); ++it) { + if (strcmp((*it).name, name) == 0) { + prop_list.erase(it); + // Dump the props back + PersistentProperties props = PersistentProperties_init_zero; + pb_ostream_t ostream = create_ostream(PERSISTENT_PROPERTY_DIR + "/persistent_properties.tmp"); + props.properties.funcs.encode = prop_encode; + props.properties.arg = &prop_list; + LOGD("resetprop: encode with protobuf [" PERSISTENT_PROPERTY_DIR + "/persistent_properties.tmp]\n"); + if (!pb_encode(&ostream, PersistentProperties_fields, &props)) + return false; + clone_attr(PERSISTENT_PROPERTY_DIR "/persistent_properties", + PERSISTENT_PROPERTY_DIR "/persistent_properties.tmp"); + rename(PERSISTENT_PROPERTY_DIR "/persistent_properties.tmp", + PERSISTENT_PROPERTY_DIR "/persistent_properties"); + return true; } } - if (reencode) { - // Dump the props back - PersistentProperties props = PersistentProperties_init_zero; - pb_ostream_t ostream = create_ostream(PERSISTENT_PROPERTY_DIR "/persistent_properties.tmp"); - props.properties.funcs.encode = prop_encode; - props.properties.arg = &v; - LOGD("resetprop: encode with protobuf to [" PERSISTENT_PROPERTY_DIR "/persistent_properties.tmp]\n"); - if (!pb_encode(&ostream, PersistentProperties_fields, &props)) - return false; - clone_attr(PERSISTENT_PROPERTY_DIR "/persistent_properties", PERSISTENT_PROPERTY_DIR "/persistent_properties.tmp"); - rename(PERSISTENT_PROPERTY_DIR "/persistent_properties.tmp", PERSISTENT_PROPERTY_DIR "/persistent_properties"); - } - - vec_destroy(&v); - return reencode; + return false; } else { char path[PATH_MAX]; snprintf(path, sizeof(path), PERSISTENT_PROPERTY_DIR "/%s", name); diff --git a/native/jni/resetprop/resetprop.c b/native/jni/resetprop/resetprop.cpp similarity index 70% rename from native/jni/resetprop/resetprop.c rename to native/jni/resetprop/resetprop.cpp index 814128704..9b7fd8fc6 100644 --- a/native/jni/resetprop/resetprop.c +++ b/native/jni/resetprop/resetprop.cpp @@ -20,13 +20,14 @@ #include "magisk.h" #include "resetprop.h" #include "_resetprop.h" -#include "vector.h" #include "utils.h" +#include "array.h" #include "flags.h" -int prop_verbose = 0; +bool use_pb = false; +static bool verbose = false; -static int check_legal_property_name(const char *name) { +static bool check_legal_property_name(const char *name) { int namelen = strlen(name); if (namelen < 1) goto illegal; @@ -48,14 +49,14 @@ static int check_legal_property_name(const char *name) { goto illegal; } - return 0; + return true; illegal: LOGE("Illegal property name: [%s]\n", name); - return 1; + return false; } -static int usage(char* arg0) { +[[noreturn]] static void usage(char* arg0) { fprintf(stderr, "resetprop v" xstr(MAGISK_VERSION) "(" xstr(MAGISK_VER_CODE) ") (by topjohnwu & nkk71) - System Props Modification Tool\n\n" "Usage: %s [flags] [options...]\n" @@ -77,53 +78,39 @@ static int usage(char* arg0) { "\n" , arg0); - return 1; + exit(1); } -// The callback passes to __system_property_read_callback, actually runs the callback in read_cb -static void callback_wrapper(void *read_cb, const char *name, const char *value, uint32_t serial) { - ((struct read_cb_t *) read_cb)->func(name, value, ((struct read_cb_t *) read_cb)->cookie); +// Define the way to sort prop_t +template<> +int(*Array::_cmp)(prop_t&, prop_t&) = [](auto a, auto b) -> int { + return strcmp(a.name, b.name); +}; + +static void read_props(const prop_info *pi, void *read_cb) { + __system_property_read_callback( + pi, [](auto cb, auto name, auto value, auto) -> void + { + ((read_cb_t *) cb)->exec(name, value); + }, read_cb); } -/* ********************************** - * Callback functions for read_cb_t - * **********************************/ - -void collect_props(const char *name, const char *value, void *prop_list) { - struct prop_t *p = (struct prop_t *) xmalloc(sizeof(*p)); - p->name = strdup(name); - strcpy(p->value, value); - vec_push_back(prop_list, p); +void collect_props(const char *name, const char *value, void *v_plist) { + Array &prop_list = *static_cast *>(v_plist); + prop_list.push_back(prop_t(name, value)); } -static void collect_unique_props(const char *name, const char *value, void *prop_list) { - struct vector *v = prop_list; - struct prop_t *p; - bool uniq = true; - vec_for_each(v, p) { - if (strcmp(name, p->name) == 0) { - uniq = 0; - break; - } +static void collect_unique_props(const char *name, const char *value, void *v_plist) { + Array &prop_list = *static_cast *>(v_plist); + for (auto &prop : prop_list) { + if (strcmp(name, prop.name) == 0) + return; } - if (uniq) - collect_props(name, value, prop_list); -} - -static void store_prop_value(const char *name, const char *value, void *dst) { - strcpy(dst, value); -} - -static void prop_foreach_cb(const prop_info* pi, void* read_cb) { - __system_property_read_callback(pi, callback_wrapper, read_cb); -} - -// Comparision function used to sort prop vectors -static int prop_cmp(const void *p1, const void *p2) { - return strcmp(((struct prop_t *) p1)->name, ((struct prop_t *) p2)->name); + collect_props(name, value, v_plist); } static int init_resetprop() { + use_pb = use_pb ? true : access(PERSISTENT_PROPERTY_DIR "/persistent_properties", R_OK) == 0; if (__system_properties_init()) { LOGE("resetprop: Initialize error\n"); return -1; @@ -132,24 +119,15 @@ static int init_resetprop() { } static void print_props(int persist) { - struct prop_t *p; - struct vector prop_list; - vec_init(&prop_list); + auto prop_list = Array(); getprop_all(collect_props, &prop_list); if (persist) { - struct read_cb_t read_cb = { - .func = collect_unique_props, - .cookie = &prop_list - }; + read_cb_t read_cb(collect_unique_props, &prop_list); persist_getprop_all(&read_cb); } - vec_sort(&prop_list, prop_cmp); - vec_for_each(&prop_list, p) { - printf("[%s]: [%s]\n", p->name, p->value); - free(p->name); - free(p); - } - vec_destroy(&prop_list); + prop_list.sort(); + for (auto &prop : prop_list) + printf("[%s]: [%s]\n", prop.name, prop.value); } /* ************************************************** @@ -158,7 +136,7 @@ static void print_props(int persist) { int prop_exist(const char *name) { if (init_resetprop()) return 0; - return __system_property_find(name) != NULL; + return __system_property_find(name) != nullptr; } char *getprop(const char *name) { @@ -167,25 +145,23 @@ char *getprop(const char *name) { // Get prop by name, return string (should free manually!) char *getprop2(const char *name, int persist) { - if (check_legal_property_name(name)) - return NULL; - if (init_resetprop()) return NULL; + if (!check_legal_property_name(name) || init_resetprop()) + return nullptr; const prop_info *pi = __system_property_find(name); - if (pi == NULL) { + if (pi == nullptr) { if (persist && strncmp(name, "persist.", 8) == 0) { char *value = persist_getprop(name); if (value) return value; } LOGD("resetprop: prop [%s] does not exist\n", name); - return NULL; + return nullptr; } else { char value[PROP_VALUE_MAX]; - struct read_cb_t read_cb = { - .func = store_prop_value, - .cookie = value - }; - __system_property_read_callback(pi, callback_wrapper, &read_cb); + read_cb_t read_cb; + read_cb.cb = [](auto, auto value, auto dst) -> void { strcpy((char *) dst, value); }; + read_cb.arg = value; + read_props(pi, &read_cb); LOGD("resetprop: getprop [%s]: [%s]\n", name, value); return strdup(value); } @@ -193,11 +169,8 @@ char *getprop2(const char *name, int persist) { void getprop_all(void (*callback)(const char *, const char *, void *), void *cookie) { if (init_resetprop()) return; - struct read_cb_t read_cb = { - .func = callback, - .cookie = cookie - }; - __system_property_foreach(prop_foreach_cb, &read_cb); + read_cb_t read_cb(callback, cookie); + __system_property_foreach(read_props, &read_cb); } int setprop(const char *name, const char *value) { @@ -205,13 +178,15 @@ int setprop(const char *name, const char *value) { } int setprop2(const char *name, const char *value, const int trigger) { - if (check_legal_property_name(name)) + if (!check_legal_property_name(name)) return 1; - if (init_resetprop()) return -1; + if (init_resetprop()) + return -1; + int ret; prop_info *pi = (prop_info*) __system_property_find(name); - if (pi != NULL) { + if (pi != nullptr) { if (trigger) { if (strncmp(name, "ro.", 3) == 0) deleteprop(name); ret = __system_property_set(name, value); @@ -241,7 +216,7 @@ int deleteprop(const char *name) { } int deleteprop2(const char *name, int persist) { - if (check_legal_property_name(name)) + if (!check_legal_property_name(name)) return 1; if (init_resetprop()) return -1; char path[PATH_MAX]; @@ -256,11 +231,11 @@ int read_prop_file(const char* filename, const int trigger) { if (init_resetprop()) return -1; LOGD("resetprop: Load prop file [%s]\n", filename); FILE *fp = fopen(filename, "r"); - if (fp == NULL) { + if (fp == nullptr) { LOGE("Cannot open [%s]\n", filename); return 1; } - char *line = NULL, *pch; + char *line = nullptr, *pch; size_t len; ssize_t read; int comment = 0, i; @@ -283,7 +258,7 @@ int read_prop_file(const char* filename, const int trigger) { if (comment) continue; pch = strchr(line, '='); // Ignore invalid formats - if ( ((pch == NULL) || (i >= (pch - line))) || (pch >= line + read - 1) ) continue; + if ( ((pch == nullptr) || (i >= (pch - line))) || (pch >= line + read - 1) ) continue; // Separate the string *pch = '\0'; setprop2(line + i, pch + 1, trigger); @@ -293,12 +268,8 @@ int read_prop_file(const char* filename, const int trigger) { return 0; } -static int verbose_logging(const char *fmt, va_list ap) { - return prop_verbose ? vfprintf(stderr, fmt, ap) : 0; -} - int resetprop_main(int argc, char *argv[]) { - log_cb.d = verbose_logging; + log_cb.d = [](auto fmt, auto ap) -> int { return verbose ? vfprintf(stderr, fmt, ap) : 0; }; int trigger = 1, persist = 0; char *argv0 = argv[0], *prop; @@ -316,10 +287,10 @@ int resetprop_main(int argc, char *argv[]) { } else if (strcmp(argv[0], "--delete") == 0 && argc == 2) { return deleteprop2(argv[1], persist); } else if (strcmp(argv[0], "--help") == 0) { - goto usage; + usage(argv0); } case 'v': - prop_verbose = 1; + verbose = true; continue; case 'p': persist = 1; @@ -331,8 +302,7 @@ int resetprop_main(int argc, char *argv[]) { break; case 'h': default: - usage: - return usage(argv0); + usage(argv0); } break; } @@ -346,7 +316,7 @@ int resetprop_main(int argc, char *argv[]) { return 0; case 1: prop = getprop2(argv[0], persist); - if (prop == NULL) return 1; + if (prop == nullptr) return 1; printf("%s\n", prop); free(prop); return 0; @@ -354,6 +324,5 @@ int resetprop_main(int argc, char *argv[]) { return setprop2(argv[0], argv[1], trigger); default: usage(argv0); - return 1; } } diff --git a/native/jni/utils/include/array.h b/native/jni/utils/include/array.h index 38c3d245a..41b468c14 100644 --- a/native/jni/utils/include/array.h +++ b/native/jni/utils/include/array.h @@ -22,15 +22,18 @@ public: ++_node; return (*this); } + iterator operator ++ (int) { iterator temp = *this; ++_node; return temp; } + iterator& operator -- () { --_node; return (*this); } + iterator operator -- (int) { iterator temp = *this; --_node; @@ -42,6 +45,7 @@ public: temp += i; return temp; } + iterator& operator += (int i) { _node += i; return (*this); @@ -55,6 +59,7 @@ public: bool operator != (const iterator& i) const { return _node != i._node; } + bool operator == (const iterator& i) const { return !(*this != i); } private: @@ -62,11 +67,15 @@ public: }; iterator begin() const { return iterator(_data); } + iterator end() const { return iterator(_data + _size); } + bool empty() const { return !_size; } + size_t size() const { return _size; } T& operator [] (size_t i) { return _data[i]; } + const T& operator [] (size_t i) const { return _data[i]; } const T& back() const { return _data[_size - 1]; } @@ -78,6 +87,13 @@ public: ++_size; } + void push_back(T&& x) { + if(_size == _capacity) + expand(); + _data[_size] = (T&&) x; + ++_size; + } + void pop_front() { erase(begin()); } void pop_back() { if(_size) --_size; } @@ -87,7 +103,7 @@ public: if (_size == 0 || d < _data || d >= _data + _size) return false; for (; d < _data + _size - 1; ++d) - *d = *(d + 1); + *d = (T&&) *(d + 1); --_size; return true; @@ -129,7 +145,7 @@ private: _capacity *= 2; T* temp = _data; _data = new T[_capacity]; - for(int i = 0; i < _size; ++i) _data[i] = temp[i]; + for(int i = 0; i < _size; ++i) _data[i] = (T&&) temp[i]; delete [] temp; } };