Migrate to STL

This commit is contained in:
topjohnwu 2019-01-19 23:59:37 -05:00
parent 03c39e692a
commit 3e4c12cf56
23 changed files with 226 additions and 548 deletions

View File

@ -13,6 +13,8 @@
#include <dirent.h> #include <dirent.h>
#include <sys/mount.h> #include <sys/mount.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <vector>
#include <string>
#include "magisk.h" #include "magisk.h"
#include "db.h" #include "db.h"
@ -23,8 +25,10 @@
#include "selinux.h" #include "selinux.h"
#include "flags.h" #include "flags.h"
using namespace std;
static char buf[PATH_MAX], buf2[PATH_MAX]; static char buf[PATH_MAX], buf2[PATH_MAX];
static Vector<CharArray> module_list; static vector<string> module_list;
static bool seperate_vendor; static bool seperate_vendor;
char *system_block, *vendor_block, *magiskloop; char *system_block, *vendor_block, *magiskloop;
@ -42,9 +46,9 @@ extern void auto_start_magiskhide();
#define IS_SKEL 0x04 /* mount from skeleton */ #define IS_SKEL 0x04 /* mount from skeleton */
#define IS_MODULE 0x08 /* mount from module */ #define IS_MODULE 0x08 /* mount from module */
#define IS_DIR(n) (n->type == DT_DIR) #define IS_DIR(n) ((n)->type == DT_DIR)
#define IS_LNK(n) (n->type == DT_LNK) #define IS_LNK(n) ((n)->type == DT_LNK)
#define IS_REG(n) (n->type == DT_REG) #define IS_REG(n) ((n)->type == DT_REG)
class node_entry { class node_entry {
public: public:
@ -56,15 +60,15 @@ public:
private: private:
const char *module; /* Only used when status & IS_MODULE */ const char *module; /* Only used when status & IS_MODULE */
const CharArray name; const string name;
uint8_t type; uint8_t type;
uint8_t status; uint8_t status;
node_entry *parent; node_entry *parent;
Vector<node_entry *> children; vector<node_entry *> children;
node_entry(const char *, const char *, uint8_t type); node_entry(const char *, const char *, uint8_t type);
bool is_root(); bool is_root();
CharArray get_path(); string get_path();
node_entry *insert(node_entry *); node_entry *insert(node_entry *);
void clone_skeleton(); void clone_skeleton();
int get_path(char *path); int get_path(char *path);
@ -87,7 +91,7 @@ bool node_entry::is_root() {
return parent == nullptr; return parent == nullptr;
} }
CharArray node_entry::get_path() { string node_entry::get_path() {
get_path(buf); get_path(buf);
return buf; return buf;
} }
@ -123,7 +127,7 @@ void node_entry::create_module_tree(const char *module) {
DIR *dir; DIR *dir;
struct dirent *entry; struct dirent *entry;
CharArray full_path = get_path(); auto full_path = get_path();
snprintf(buf, PATH_MAX, "%s/%s%s", MOUNTPOINT, module, full_path.c_str()); snprintf(buf, PATH_MAX, "%s/%s%s", MOUNTPOINT, module, full_path.c_str());
if (!(dir = xopendir(buf))) if (!(dir = xopendir(buf)))
@ -133,7 +137,7 @@ void node_entry::create_module_tree(const char *module) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
continue; continue;
// Create new node // Create new node
node_entry *node = new node_entry(module, entry->d_name, entry->d_type); auto node = new node_entry(module, entry->d_name, entry->d_type);
snprintf(buf, PATH_MAX, "%s/%s", full_path.c_str(), entry->d_name); snprintf(buf, PATH_MAX, "%s/%s", full_path.c_str(), entry->d_name);
/* /*
@ -185,7 +189,7 @@ void node_entry::clone_skeleton() {
struct node_entry *dummy; struct node_entry *dummy;
// Clone the structure // Clone the structure
CharArray full_path = get_path(); auto full_path = get_path();
snprintf(buf, PATH_MAX, "%s%s", MIRRDIR, full_path.c_str()); snprintf(buf, PATH_MAX, "%s%s", MIRRDIR, full_path.c_str());
if (!(dir = xopendir(buf))) if (!(dir = xopendir(buf)))
return; return;
@ -200,10 +204,10 @@ void node_entry::clone_skeleton() {
if (status & IS_SKEL) { if (status & IS_SKEL) {
file_attr attr; file_attr attr;
getattr(full_path, &attr); getattr(full_path.c_str(), &attr);
LOGI("mnt_tmpfs : %s\n", full_path.c_str()); LOGI("mnt_tmpfs : %s\n", full_path.c_str());
xmount("tmpfs", full_path, "tmpfs", 0, nullptr); xmount("tmpfs", full_path.c_str(), "tmpfs", 0, nullptr);
setattr(full_path, &attr); setattr(full_path.c_str(), &attr);
} }
for (auto &child : children) { for (auto &child : children) {
@ -254,9 +258,9 @@ void node_entry::clone_skeleton() {
void node_entry::magic_mount() { void node_entry::magic_mount() {
if (status & IS_MODULE) { if (status & IS_MODULE) {
// Mount module item // Mount module item
CharArray real_path = get_path(); auto real_path = get_path();
snprintf(buf, PATH_MAX, "%s/%s%s", MOUNTPOINT, module, real_path.c_str()); snprintf(buf, PATH_MAX, "%s/%s%s", MOUNTPOINT, module, real_path.c_str());
bind_mount(buf, real_path); bind_mount(buf, real_path.c_str());
} else if (status & IS_SKEL) { } else if (status & IS_SKEL) {
// The node is labeled to be cloned with skeleton, lets do it // The node is labeled to be cloned with skeleton, lets do it
clone_skeleton(); clone_skeleton();
@ -330,7 +334,8 @@ static void exec_common_script(const char* stage) {
} }
static void exec_module_script(const char* stage) { static void exec_module_script(const char* stage) {
for (const char *module : module_list) { for (const auto &m : module_list) {
const auto module = m.c_str();
snprintf(buf2, PATH_MAX, "%s/%s/%s.sh", MOUNTPOINT, module, stage); snprintf(buf2, PATH_MAX, "%s/%s/%s.sh", MOUNTPOINT, module, stage);
if (access(buf2, F_OK) == -1) if (access(buf2, F_OK) == -1)
continue; continue;
@ -364,7 +369,7 @@ static void simple_mount(const char *path) {
if (access(buf2, F_OK) == -1) if (access(buf2, F_OK) == -1)
continue; continue;
if (entry->d_type == DT_DIR) { if (entry->d_type == DT_DIR) {
simple_mount(CharArray(buf2)); simple_mount(string(buf2).c_str());
} else if (entry->d_type == DT_REG) { } else if (entry->d_type == DT_REG) {
// Actual file path // Actual file path
snprintf(buf, PATH_MAX, "%s%s", SIMPLEMOUNT, buf2); snprintf(buf, PATH_MAX, "%s%s", SIMPLEMOUNT, buf2);
@ -431,21 +436,20 @@ static bool magisk_env() {
xmkdir(SECURE_DIR "/post-fs-data.d", 0755); xmkdir(SECURE_DIR "/post-fs-data.d", 0755);
xmkdir(SECURE_DIR "/service.d", 0755); xmkdir(SECURE_DIR "/service.d", 0755);
CharArray sdk_prop = getprop("ro.build.version.sdk"); auto sdk_prop = getprop("ro.build.version.sdk");
int sdk = sdk_prop.empty() ? -1 : atoi(sdk_prop); int sdk = sdk_prop.empty() ? -1 : atoi(sdk_prop.c_str());
LOGI("* Mounting mirrors"); LOGI("* Mounting mirrors");
Vector<CharArray> mounts; auto mounts = file_to_vector("/proc/mounts");
file_to_vector("/proc/mounts", mounts);
bool system_as_root = false; bool system_as_root = false;
for (auto &line : mounts) { for (auto &line : mounts) {
if (line.contains(" /system_root ")) { if (line.find(" /system_root ") != string::npos) {
bind_mount("/system_root/system", MIRRDIR "/system"); bind_mount("/system_root/system", MIRRDIR "/system");
sscanf(line, "%s", buf); sscanf(line.c_str(), "%s", buf);
system_block = strdup2(buf); system_block = strdup2(buf);
system_as_root = true; system_as_root = true;
} else if (!system_as_root && line.contains(" /system ")) { } else if (!system_as_root && line.find(" /system ") != string::npos) {
sscanf(line, "%s %*s %s", buf, buf2); sscanf(line.c_str(), "%s %*s %s", buf, buf2);
system_block = strdup2(buf); system_block = strdup2(buf);
xmount(system_block, MIRRDIR "/system", buf2, MS_RDONLY, nullptr); xmount(system_block, MIRRDIR "/system", buf2, MS_RDONLY, nullptr);
#ifdef MAGISK_DEBUG #ifdef MAGISK_DEBUG
@ -453,9 +457,9 @@ static bool magisk_env() {
#else #else
LOGI("mount: %s\n", MIRRDIR "/system"); LOGI("mount: %s\n", MIRRDIR "/system");
#endif #endif
} else if (line.contains(" /vendor ")) { } else if (line.find(" /vendor ") != string::npos) {
seperate_vendor = true; seperate_vendor = true;
sscanf(line, "%s %*s %s", buf, buf2); sscanf(line.c_str(), "%s %*s %s", buf, buf2);
vendor_block = strdup2(buf); vendor_block = strdup2(buf);
xmkdir(MIRRDIR "/vendor", 0755); xmkdir(MIRRDIR "/vendor", 0755);
xmount(buf, MIRRDIR "/vendor", buf2, MS_RDONLY, nullptr); xmount(buf, MIRRDIR "/vendor", buf2, MS_RDONLY, nullptr);
@ -464,7 +468,9 @@ static bool magisk_env() {
#else #else
LOGI("mount: %s\n", MIRRDIR "/vendor"); LOGI("mount: %s\n", MIRRDIR "/vendor");
#endif #endif
} else if (sdk >= 24 && line.contains(" /proc ") && !line.contains("hidepid=2")) { } else if (sdk >= 24 &&
line.find(" /proc ") != string::npos &&
line.find("hidepid=2") == string::npos) {
// Enforce hidepid // Enforce hidepid
xmount(nullptr, "/proc", nullptr, MS_REMOUNT, "hidepid=2,gid=3009"); xmount(nullptr, "/proc", nullptr, MS_REMOUNT, "hidepid=2,gid=3009");
} }
@ -508,7 +514,7 @@ static void collect_modules() {
} }
unlink("update"); unlink("update");
if (access("disable", F_OK)) if (access("disable", F_OK))
module_list.push_back(entry->d_name); module_list.emplace_back(entry->d_name);
chdir(".."); chdir("..");
} }
} }
@ -559,7 +565,7 @@ static bool prepare_img() {
static void install_apk(const char *apk) { static void install_apk(const char *apk) {
setfilecon(apk, "u:object_r:" SEPOL_FILE_DOMAIN ":s0"); setfilecon(apk, "u:object_r:" SEPOL_FILE_DOMAIN ":s0");
while (1) { while (true) {
sleep(5); sleep(5);
LOGD("apk_install: attempting to install APK\n"); LOGD("apk_install: attempting to install APK\n");
int fd = -1, pid; int fd = -1, pid;
@ -586,14 +592,14 @@ static void install_apk(const char *apk) {
static bool check_data() { static bool check_data() {
bool mnt = false; bool mnt = false;
bool data = false; bool data = false;
Vector<CharArray> mounts; auto mounts = file_to_vector("/proc/mounts");
file_to_vector("/proc/mounts", mounts);
for (auto &line : mounts) { for (auto &line : mounts) {
if (line.contains(" /data ") && !line.contains("tmpfs")) if (line.find(" /data ") != string::npos &&
line.find("tmpfs") == string::npos)
mnt = true; mnt = true;
} }
if (mnt) { if (mnt) {
CharArray crypto = getprop("ro.crypto.state"); auto crypto = getprop("ro.crypto.state");
if (!crypto.empty()) { if (!crypto.empty()) {
if (crypto == "unencrypted") { if (crypto == "unencrypted") {
// Unencrypted, we can directly access data // Unencrypted, we can directly access data
@ -811,11 +817,11 @@ void post_fs_data(int client) {
exec_module_script("post-fs-data"); exec_module_script("post-fs-data");
// Recollect modules // Recollect modules
module_list.clear(true); module_list.clear();
collect_modules(); collect_modules();
// Create the system root entry // Create the system root entry
node_entry *sys_root = new node_entry("system", IS_INTER); auto sys_root = new node_entry("system", IS_INTER);
// Vendor root entry // Vendor root entry
node_entry *ven_root = nullptr; node_entry *ven_root = nullptr;
@ -823,7 +829,8 @@ void post_fs_data(int client) {
bool has_modules = false; bool has_modules = false;
LOGI("* Loading modules\n"); LOGI("* Loading modules\n");
for (const char *module : module_list) { for (const auto &m : module_list) {
const auto module = m.c_str();
// Read props // Read props
snprintf(buf, PATH_MAX, "%s/%s/system.prop", MOUNTPOINT, module); snprintf(buf, PATH_MAX, "%s/%s/system.prop", MOUNTPOINT, module);
if (access(buf, F_OK) == 0) { if (access(buf, F_OK) == 0) {
@ -911,7 +918,7 @@ core_only:
} }
// All boot stage done, cleanup // All boot stage done, cleanup
module_list.clear(true); module_list.clear();
} }
void boot_complete(int client) { void boot_complete(int client) {

View File

@ -12,14 +12,17 @@
#include <stdlib.h> #include <stdlib.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <fcntl.h> #include <fcntl.h>
#include <vector>
#include "magisk.h" #include "magisk.h"
#include "utils.h" #include "utils.h"
#include "daemon.h" #include "daemon.h"
#include "flags.h" #include "flags.h"
using namespace std;
bool log_daemon_started = false; bool log_daemon_started = false;
static Vector<const char *> log_cmd, clear_cmd; static vector<const char *> log_cmd, clear_cmd;
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
enum { enum {
@ -68,7 +71,7 @@ static void *monitor_thread(void *) {
sleep(5); sleep(5);
int fd; int fd;
char b; char b;
while (1) { while (true) {
fd = connect_daemon(); fd = connect_daemon();
write_int(fd, HANDSHAKE); write_int(fd, HANDSHAKE);
// This should hold unless the daemon is killed // This should hold unless the daemon is killed
@ -136,11 +139,7 @@ static void log_daemon() {
} }
chmod("/dev/null", 0666); chmod("/dev/null", 0666);
clear_cmd = log_cmd; clear_cmd = log_cmd;
log_cmd.push_back("-v"); log_cmd.insert(log_cmd.end(), { "-v", "threadtime", "-s", "am_proc_start", "Magisk" });
log_cmd.push_back("threadtime");
log_cmd.push_back("-s");
log_cmd.push_back("am_proc_start");
log_cmd.push_back("Magisk");
#ifdef MAGISK_DEBUG #ifdef MAGISK_DEBUG
log_cmd.push_back("*:F"); log_cmd.push_back("*:F");
#endif #endif
@ -163,7 +162,7 @@ static void log_daemon() {
if (xbind(sockfd, (struct sockaddr*) &sun, len)) if (xbind(sockfd, (struct sockaddr*) &sun, len))
exit(1); exit(1);
xlisten(sockfd, 10); xlisten(sockfd, 10);
while(1) { while(true) {
int fd = xaccept4(sockfd, nullptr, nullptr, SOCK_CLOEXEC); int fd = xaccept4(sockfd, nullptr, nullptr, SOCK_CLOEXEC);
switch(read_int(fd)) { switch(read_int(fd)) {
case HIDE_CONNECT: case HIDE_CONNECT:

View File

@ -3,12 +3,11 @@
#pragma once #pragma once
#include "CharArray.h" #include <string>
int prop_exist(const char *name); int prop_exist(const char *name);
int setprop(const char *name, const char *value, const bool trigger = true); int setprop(const char *name, const char *value, bool trigger = true);
CharArray getprop(const char *name, bool persist = false); std::string getprop(const char *name, bool persist = false);
void getprop(void (*callback)(const char *, const char *, void *), void *cookie, bool persist = false); void getprop(void (*callback)(const char *, const char *, void *), void *cookie, bool persist = false);
int deleteprop(const char *name, bool persist = false); int deleteprop(const char *name, bool persist = false);
int load_prop_file(const char *filename, const bool trigger = true); int load_prop_file(const char *filename, bool trigger = true);

View File

@ -2,11 +2,14 @@
#include <fcntl.h> #include <fcntl.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <algorithm>
#include "cpio.h" #include "cpio.h"
#include "utils.h" #include "utils.h"
#include "logging.h" #include "logging.h"
using namespace std;
#define parse_align() lseek(fd, align(lseek(fd, 0, SEEK_CUR), 4), SEEK_SET) #define parse_align() lseek(fd, align(lseek(fd, 0, SEEK_CUR), 4), SEEK_SET)
static uint32_t x8u(char *hex) { static uint32_t x8u(char *hex) {
@ -40,8 +43,8 @@ cpio_entry::cpio_entry(int fd, cpio_newc_header &header) {
// rdevminor = x8u(header.rdevminor); // rdevminor = x8u(header.rdevminor);
uint32_t namesize = x8u(header.namesize); uint32_t namesize = x8u(header.namesize);
// check = x8u(header.check); // check = x8u(header.check);
filename = CharArray(namesize); filename.resize(namesize - 1);
xxread(fd, filename, filename.size()); xxread(fd, &filename[0], namesize);
parse_align(); parse_align();
if (filesize) { if (filesize) {
data = xmalloc(filesize); data = xmalloc(filesize);
@ -54,22 +57,13 @@ cpio_entry::~cpio_entry() {
free(data); free(data);
} }
// Define the way to sort cpio_entry
template<>
int(*Vector<cpio_entry*>::_cmp)(cpio_entry*&, cpio_entry*&) = [](auto a, auto b) -> int {
if (a == b) return 0;
if (a == nullptr) return 1;
if (b == nullptr) return -1;
return a->filename.compare(b->filename);
};
cpio::cpio(const char *filename) { cpio::cpio(const char *filename) {
int fd = open(filename, O_RDONLY); int fd = open(filename, O_RDONLY);
if (fd < 0) return; if (fd < 0) return;
fprintf(stderr, "Loading cpio: [%s]\n", filename); fprintf(stderr, "Loading cpio: [%s]\n", filename);
cpio_newc_header header; cpio_newc_header header;
cpio_entry *entry; cpio_entry *entry;
int i = 0;
while(xxread(fd, &header, sizeof(cpio_newc_header)) != -1) { while(xxread(fd, &header, sizeof(cpio_newc_header)) != -1) {
entry = new cpio_entry(fd, header); entry = new cpio_entry(fd, header);
if (entry->filename == "." || entry->filename == ".." || entry->filename == "TRAILER!!!") { if (entry->filename == "." || entry->filename == ".." || entry->filename == "TRAILER!!!") {
@ -86,7 +80,7 @@ cpio::cpio(const char *filename) {
cpio::~cpio() { cpio::~cpio() {
for (auto &e : arr) for (auto &e : arr)
if (e) delete e; delete e;
} }
#define dump_align() write_zero(fd, align_off(lseek(fd, 0, SEEK_CUR), 4)) #define dump_align() write_zero(fd, align_off(lseek(fd, 0, SEEK_CUR), 4))
@ -109,11 +103,11 @@ void cpio::dump(const char *file) {
0, // e->devminor 0, // e->devminor
0, // e->rdevmajor 0, // e->rdevmajor
0, // e->rdevminor 0, // e->rdevminor
(uint32_t) e->filename.size(), (uint32_t) e->filename.size() + 1,
0 // e->check 0 // e->check
); );
xwrite(fd, header, 110); xwrite(fd, header, 110);
xwrite(fd, e->filename, e->filename.size()); xwrite(fd, e->filename.c_str(), e->filename.size() + 1);
dump_align(); dump_align();
if (e->filesize) { if (e->filesize) {
xwrite(fd, e->data, e->filesize); xwrite(fd, e->data, e->filesize);
@ -140,7 +134,7 @@ int cpio::find(const char *name) {
} }
void cpio::insert(cpio_entry *e) { void cpio::insert(cpio_entry *e) {
int i = find(e->filename); int i = find(e->filename.c_str());
if (i >= 0) { if (i >= 0) {
delete arr[i]; delete arr[i];
arr[i] = e; arr[i] = e;
@ -149,17 +143,12 @@ void cpio::insert(cpio_entry *e) {
} }
} }
void cpio::insert(Vector<cpio_entry *> &arr) {
for (auto &e : arr)
insert(e);
}
void cpio::rm(const char *name, bool r) { void cpio::rm(const char *name, bool r) {
size_t len = strlen(name); size_t len = strlen(name);
for (auto &e : arr) { for (auto &e : arr) {
if (!e) if (!e)
continue; continue;
if (e->filename.compare(name, len) == 0 && if (e->filename.compare(0, len, name) == 0 &&
((r && e->filename[len] == '/') || e->filename[len] == '\0')) { ((r && e->filename[len] == '/') || e->filename[len] == '\0')) {
fprintf(stderr, "Remove [%s]\n", e->filename.c_str()); fprintf(stderr, "Remove [%s]\n", e->filename.c_str());
delete e; delete e;
@ -171,17 +160,15 @@ void cpio::rm(const char *name, bool r) {
} }
void cpio::makedir(mode_t mode, const char *name) { void cpio::makedir(mode_t mode, const char *name) {
auto e = new cpio_entry(); auto e = new cpio_entry(name);
e->mode = S_IFDIR | mode; e->mode = S_IFDIR | mode;
e->filename = name;
insert(e); insert(e);
fprintf(stderr, "Create directory [%s] (%04o)\n", name, mode); fprintf(stderr, "Create directory [%s] (%04o)\n", name, mode);
} }
void cpio::ln(const char *target, const char *name) { void cpio::ln(const char *target, const char *name) {
auto e = new cpio_entry(); auto e = new cpio_entry(name);
e->mode = S_IFLNK; e->mode = S_IFLNK;
e->filename = name;
e->filesize = strlen(target); e->filesize = strlen(target);
e->data = strdup(target); e->data = strdup(target);
insert(e); insert(e);
@ -190,9 +177,8 @@ void cpio::ln(const char *target, const char *name) {
void cpio::add(mode_t mode, const char *name, const char *file) { void cpio::add(mode_t mode, const char *name, const char *file) {
int fd = xopen(file, O_RDONLY); int fd = xopen(file, O_RDONLY);
auto e = new cpio_entry(); auto e = new cpio_entry(name);
e->mode = S_IFREG | mode; e->mode = S_IFREG | mode;
e->filename = name;
e->filesize = lseek(fd, 0, SEEK_END); e->filesize = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET); lseek(fd, 0, SEEK_SET);
e->data = xmalloc(e->filesize); e->data = xmalloc(e->filesize);
@ -239,17 +225,15 @@ static void extract_entry(cpio_entry *e, const char *file) {
void cpio::extract() { void cpio::extract() {
for (auto &e : arr) { for (auto &e : arr) {
if (!e) if (!e) continue;
continue; extract_entry(e, e->filename.c_str());
extract_entry(e, e->filename);
} }
} }
bool cpio::extract(const char *name, const char *file) { bool cpio::extract(const char *name, const char *file) {
int i = find(name); int i = find(name);
if (i > 0) { if (i > 0) {
auto e = arr[i]; extract_entry(arr[i], file);
extract_entry(e, file);
return true; return true;
} }
fprintf(stderr, "Cannot find the file entry [%s]\n", name); fprintf(stderr, "Cannot find the file entry [%s]\n", name);
@ -257,7 +241,13 @@ bool cpio::extract(const char *name, const char *file) {
} }
void cpio::sort() { void cpio::sort() {
arr.sort(); std::sort(arr.begin(), arr.end(), [] (auto a, auto b) -> bool {
if (a == b || a == nullptr)
return false;
if (b == nullptr)
return true;
return a->filename.compare(b->filename) < 0;
});
while (arr.back() == nullptr) while (arr.back() == nullptr)
arr.pop_back(); arr.pop_back();
} }

View File

@ -2,9 +2,8 @@
#define _CPIO_H_ #define _CPIO_H_
#include <stdint.h> #include <stdint.h>
#include <vector>
#include "Vector.h" #include <string>
#include "CharArray.h"
struct cpio_newc_header { struct cpio_newc_header {
char magic[6]; char magic[6];
@ -38,17 +37,18 @@ struct cpio_entry {
// uint32_t namesize; // uint32_t namesize;
// uint32_t check; // uint32_t check;
// char *filename = nullptr; // char *filename = nullptr;
CharArray filename; std::string filename;
void *data = nullptr; void *data = nullptr;
cpio_entry() {} cpio_entry() = default;
explicit cpio_entry(const char *name) : filename(name) {}
cpio_entry(int fd, cpio_newc_header &header); cpio_entry(int fd, cpio_newc_header &header);
~cpio_entry(); ~cpio_entry();
}; };
class cpio { class cpio {
public: public:
cpio(const char *filename); explicit cpio(const char *filename);
~cpio(); ~cpio();
void dump(const char *file); void dump(const char *file);
int find(const char *name); int find(const char *name);
@ -57,14 +57,13 @@ public:
void makedir(mode_t mode, const char *name); void makedir(mode_t mode, const char *name);
void ln(const char *target, const char *name); void ln(const char *target, const char *name);
void add(mode_t mode, const char *name, const char *file); void add(mode_t mode, const char *name, const char *file);
void insert(Vector<cpio_entry *> &arr);
bool mv(const char *from, const char *to); bool mv(const char *from, const char *to);
void extract(); void extract();
bool extract(const char *name, const char *file); bool extract(const char *name, const char *file);
void sort(); void sort();
protected: protected:
Vector<cpio_entry *> arr; std::vector<cpio_entry *> arr;
}; };
#endif #endif

View File

@ -6,9 +6,11 @@
#include "cpio.h" #include "cpio.h"
#include "utils.h" #include "utils.h"
using namespace std;
class magisk_cpio : public cpio { class magisk_cpio : public cpio {
public: public:
magisk_cpio(const char *filename) : cpio(filename) {} explicit magisk_cpio(const char *filename) : cpio(filename) {}
void patch(bool keepverity, bool keepforceencrypt); void patch(bool keepverity, bool keepforceencrypt);
int test(); int test();
char * sha1(); char * sha1();
@ -23,8 +25,8 @@ void magisk_cpio::patch(bool keepverity, bool keepforceencrypt) {
if (!e) if (!e)
continue; continue;
bool fstab = (!keepverity || !keepforceencrypt) && bool fstab = (!keepverity || !keepforceencrypt) &&
!e->filename.starts_with(".backup") && !str_starts(e->filename, ".backup") &&
e->filename.contains("fstab") && S_ISREG(e->mode); str_contains(e->filename, "fstab") && S_ISREG(e->mode);
if (!keepverity) { if (!keepverity) {
if (fstab) { if (fstab) {
patch_verity(&e->data, &e->filesize, 1); patch_verity(&e->data, &e->filesize, 1);
@ -98,7 +100,7 @@ char *magisk_cpio::sha1() {
void magisk_cpio::restore() { void magisk_cpio::restore() {
for (auto &e : arr) { for (auto &e : arr) {
if (!e) continue; if (!e) continue;
if (e->filename.starts_with(".backup")) { if (str_starts(e->filename, ".backup")) {
if (e->filename[7] == '\0') continue; if (e->filename[7] == '\0') continue;
if (e->filename[8] == '.') { if (e->filename[8] == '.') {
if (strcmp(&e->filename[8], ".rmlist") == 0) { if (strcmp(&e->filename[8], ".rmlist") == 0) {
@ -106,7 +108,7 @@ void magisk_cpio::restore() {
rm((char *) e->data + pos, false); rm((char *) e->data + pos, false);
} }
} else { } else {
mv(e->filename, e->filename + 8); mv(e->filename.c_str(), &e->filename[8]);
} }
} }
} }
@ -120,17 +122,15 @@ void magisk_cpio::restore() {
} }
void magisk_cpio::backup(const char *orig) { void magisk_cpio::backup(const char *orig) {
Vector<cpio_entry*> bak; vector<cpio_entry*> bak;
cpio_entry *m, *n, *rem; cpio_entry *m, *n, *rem;
char buf[PATH_MAX]; char buf[PATH_MAX];
m = new cpio_entry(); m = new cpio_entry(".backup");
m->filename = ".backup";
m->mode = S_IFDIR; m->mode = S_IFDIR;
bak.push_back(m); bak.push_back(m);
rem = new cpio_entry(); rem = new cpio_entry(".backup/.rmlist");
rem->filename = ".backup/.rmlist";
rem->mode = S_IFREG; rem->mode = S_IFREG;
magisk_cpio o(orig); magisk_cpio o(orig);
@ -176,7 +176,7 @@ void magisk_cpio::backup(const char *orig) {
// Something new in ramdisk, record in rem // Something new in ramdisk, record in rem
++j; ++j;
rem->data = xrealloc(rem->data, rem->filesize + n->filename.size()); rem->data = xrealloc(rem->data, rem->filesize + n->filename.size());
memcpy((char *) rem->data + rem->filesize, n->filename, n->filename.size()); memcpy((char *) rem->data + rem->filesize, n->filename.c_str(), n->filename.size());
rem->filesize += n->filename.size(); rem->filesize += n->filename.size();
fprintf(stderr, "Record new entry: [%s] -> [.backup/.rmlist]\n", n->filename.c_str()); fprintf(stderr, "Record new entry: [%s] -> [.backup/.rmlist]\n", n->filename.c_str());
} }
@ -196,7 +196,8 @@ void magisk_cpio::backup(const char *orig) {
delete rem; delete rem;
if (bak.size() > 1) if (bak.size() > 1)
insert(bak); for (auto item : bak)
insert(item);
} }
@ -249,11 +250,11 @@ int cpio_commands(int argc, char *argv[]) {
return 0; return 0;
} }
} else if (cmdc == 3 && strcmp(cmdv[0], "mkdir") == 0) { } else if (cmdc == 3 && strcmp(cmdv[0], "mkdir") == 0) {
cpio.makedir(strtoul(cmdv[1], NULL, 8), cmdv[2]); cpio.makedir(strtoul(cmdv[1], nullptr, 8), cmdv[2]);
} else if (cmdc == 3 && strcmp(cmdv[0], "ln") == 0) { } else if (cmdc == 3 && strcmp(cmdv[0], "ln") == 0) {
cpio.ln(cmdv[1], cmdv[2]); cpio.ln(cmdv[1], cmdv[2]);
} else if (cmdc == 4 && strcmp(cmdv[0], "add") == 0) { } else if (cmdc == 4 && strcmp(cmdv[0], "add") == 0) {
cpio.add(strtoul(cmdv[1], NULL, 8), cmdv[2], cmdv[3]); cpio.add(strtoul(cmdv[1], nullptr, 8), cmdv[2], cmdv[3]);
} else { } else {
return 1; return 1;
} }

View File

@ -15,10 +15,12 @@
#include "daemon.h" #include "daemon.h"
#include "db.h" #include "db.h"
using namespace std;
#define SAFETYNET_COMPONENT "com.google.android.gms/.droidguard.DroidGuardService" #define SAFETYNET_COMPONENT "com.google.android.gms/.droidguard.DroidGuardService"
#define SAFETYNET_PROCESS "com.google.android.gms.unstable" #define SAFETYNET_PROCESS "com.google.android.gms.unstable"
Vector<CharArray> hide_list; vector<string> hide_list;
pthread_mutex_t list_lock; pthread_mutex_t list_lock;
static pthread_t proc_monitor_thread; static pthread_t proc_monitor_thread;
@ -55,7 +57,7 @@ void hide_sensitive_props() {
// Hide all sensitive props // Hide all sensitive props
for (int i = 0; prop_key[i]; ++i) { for (int i = 0; prop_key[i]; ++i) {
CharArray value = getprop(prop_key[i]); auto value = getprop(prop_key[i]);
if (!value.empty() && value != prop_value[i]) if (!value.empty() && value != prop_value[i])
setprop(prop_key[i], prop_value[i], false); setprop(prop_key[i], prop_value[i], false);
} }
@ -118,7 +120,7 @@ static bool proc_name_match(int pid, const char *name) {
} }
static void kill_proc_cb(int pid, void *v) { static void kill_proc_cb(int pid, void *v) {
ps_arg *args = static_cast<ps_arg *>(v); auto args = static_cast<ps_arg *>(v);
if (proc_name_match(pid, args->name)) if (proc_name_match(pid, args->name))
kill(pid, SIGTERM); kill(pid, SIGTERM);
else if (args->uid > 0) { else if (args->uid > 0) {
@ -183,7 +185,7 @@ int add_list(const char *proc) {
// Critical region // Critical region
pthread_mutex_lock(&list_lock); pthread_mutex_lock(&list_lock);
hide_list.push_back(proc); hide_list.emplace_back(proc);
kill_process(proc); kill_process(proc);
pthread_mutex_unlock(&list_lock); pthread_mutex_unlock(&list_lock);
@ -247,10 +249,9 @@ bool init_list() {
// Migrate old hide list into database // Migrate old hide list into database
if (access(LEGACY_LIST, R_OK) == 0) { if (access(LEGACY_LIST, R_OK) == 0) {
Vector<CharArray> tmp; auto tmp = file_to_vector(LEGACY_LIST);
file_to_vector(LEGACY_LIST, tmp);
for (auto &s : tmp) for (auto &s : tmp)
add_list(s); add_list(s.c_str());
unlink(LEGACY_LIST); unlink(LEGACY_LIST);
} }
@ -307,7 +308,7 @@ int launch_magiskhide(int client) {
// Start monitoring // Start monitoring
proc_monitor(); proc_monitor();
error: error:
hide_enabled = false; hide_enabled = false;
return DAEMON_ERROR; return DAEMON_ERROR;
} }

View File

@ -2,10 +2,10 @@
#define MAGISK_HIDE_H #define MAGISK_HIDE_H
#include <pthread.h> #include <pthread.h>
#include <vector>
#include <string>
#include "daemon.h" #include "daemon.h"
#include "Vector.h"
#include "CharArray.h"
#define TERM_THREAD SIGUSR1 #define TERM_THREAD SIGUSR1
@ -30,7 +30,7 @@ bool init_list();
extern bool hide_enabled; extern bool hide_enabled;
extern pthread_mutex_t list_lock; extern pthread_mutex_t list_lock;
extern Vector<CharArray> hide_list; extern std::vector<std::string> hide_list;
enum { enum {
LAUNCH_MAGISKHIDE, LAUNCH_MAGISKHIDE,

View File

@ -15,19 +15,23 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/mount.h> #include <sys/mount.h>
#include <vector>
#include <string>
#include "magisk.h" #include "magisk.h"
#include "daemon.h" #include "daemon.h"
#include "utils.h" #include "utils.h"
#include "magiskhide.h" #include "magiskhide.h"
using namespace std;
static int sockfd = -1; static int sockfd = -1;
extern char *system_block, *vendor_block, *magiskloop; extern char *system_block, *vendor_block, *magiskloop;
// Workaround for the lack of pthread_cancel // Workaround for the lack of pthread_cancel
static void term_thread(int) { static void term_thread(int) {
LOGD("proc_monitor: running cleanup\n"); LOGD("proc_monitor: running cleanup\n");
hide_list.clear(true); hide_list.clear();
hide_enabled = false; hide_enabled = false;
close(sockfd); close(sockfd);
sockfd = -1; sockfd = -1;
@ -64,7 +68,7 @@ static void hide_daemon(int pid) {
LOGD("hide_daemon: handling pid=[%d]\n", pid); LOGD("hide_daemon: handling pid=[%d]\n", pid);
char buffer[4096]; char buffer[4096];
Vector<CharArray> mounts; vector<string> mounts;
manage_selinux(); manage_selinux();
clean_magisk_props(); clean_magisk_props();
@ -75,24 +79,24 @@ static void hide_daemon(int pid) {
snprintf(buffer, sizeof(buffer), "/proc/%d", pid); snprintf(buffer, sizeof(buffer), "/proc/%d", pid);
chdir(buffer); chdir(buffer);
file_to_vector("mounts", mounts); mounts = file_to_vector("mounts");
// Unmount dummy skeletons and /sbin links // Unmount dummy skeletons and /sbin links
for (auto &s : mounts) { for (auto &s : mounts) {
if (s.contains("tmpfs /system/") || s.contains("tmpfs /vendor/") || s.contains("tmpfs /sbin")) { if (str_contains(s, "tmpfs /system/") || str_contains(s, "tmpfs /vendor/") ||
sscanf(s, "%*s %4096s", buffer); str_contains(s, "tmpfs /sbin")) {
sscanf(s.c_str(), "%*s %4096s", buffer);
lazy_unmount(buffer); lazy_unmount(buffer);
} }
} }
mounts.clear();
// Re-read mount infos // Re-read mount infos
file_to_vector("mounts", mounts); mounts = file_to_vector("mounts");
// Unmount everything under /system, /vendor, and loop mounts // Unmount everything under /system, /vendor, and loop mounts
for (auto &s : mounts) { for (auto &s : mounts) {
if ((s.contains(" /system/") || s.contains(" /vendor/")) && if ((str_contains(s, " /system/") || str_contains(s, " /vendor/")) &&
(s.contains(system_block) || s.contains(vendor_block) || s.contains(magiskloop))) { (str_contains(s, system_block) || str_contains(s, vendor_block) || str_contains(s, magiskloop))) {
sscanf(s, "%*s %4096s", buffer); sscanf(s.c_str(), "%*s %4096s", buffer);
lazy_unmount(buffer); lazy_unmount(buffer);
} }
} }
@ -108,13 +112,12 @@ void proc_monitor() {
sigset_t block_set; sigset_t block_set;
sigemptyset(&block_set); sigemptyset(&block_set);
sigaddset(&block_set, TERM_THREAD); sigaddset(&block_set, TERM_THREAD);
pthread_sigmask(SIG_UNBLOCK, &block_set, NULL); pthread_sigmask(SIG_UNBLOCK, &block_set, nullptr);
// Register the cancel signal // Register the cancel signal
struct sigaction act; struct sigaction act{};
memset(&act, 0, sizeof(act));
act.sa_handler = term_thread; act.sa_handler = term_thread;
sigaction(TERM_THREAD, &act, NULL); sigaction(TERM_THREAD, &act, nullptr);
if (access("/proc/1/ns/mnt", F_OK) != 0) { if (access("/proc/1/ns/mnt", F_OK) != 0) {
LOGE("proc_monitor: Your kernel doesn't support mount namespace :(\n"); LOGE("proc_monitor: Your kernel doesn't support mount namespace :(\n");
@ -155,7 +158,7 @@ void proc_monitor() {
bool hide = false; bool hide = false;
pthread_mutex_lock(&list_lock); pthread_mutex_lock(&list_lock);
for (auto &s : hide_list) { for (auto &s : hide_list) {
if (strncmp(cpnt, s, s.size() - 1) == 0) { if (strncmp(cpnt, s.c_str(), s.size() - 1) == 0) {
hide = true; hide = true;
break; break;
} }

View File

@ -5,6 +5,8 @@
#include <stdio.h> #include <stdio.h>
#include <limits.h> #include <limits.h>
#include <vector>
#include <string>
#include "sepolicy.h" #include "sepolicy.h"
#include "magiskpolicy.h" #include "magiskpolicy.h"
@ -12,6 +14,8 @@
#include "utils.h" #include "utils.h"
#include "flags.h" #include "flags.h"
using namespace std;
static const char *type_msg_1 = static const char *type_msg_1 =
"Type 1:\n" "Type 1:\n"
"\"<rule_name> source_type target_type class perm_set\"\n" "\"<rule_name> source_type target_type class perm_set\"\n"
@ -101,7 +105,7 @@ static const char *type_msg_6 =
exit(1); exit(1);
} }
static int parse_bracket(char *tok, char *&stmt, Vector<const char *> *vec) { static int parse_bracket(char *tok, char *&stmt, vector<const char *> *vec) {
if (tok == nullptr || tok[0] != '{') { if (tok == nullptr || tok[0] != '{') {
// Not in a bracket // Not in a bracket
vec->push_back(tok); vec->push_back(tok);
@ -143,10 +147,10 @@ static int parse_pattern_1(int action, const char *action_str, char *stmt) {
int state = 0; int state = 0;
char *cur, *cls; char *cur, *cls;
Vector<const char*> source, target, permission; vector<const char*> source, target, permission;
while ((cur = strtok_r(nullptr, " ", &stmt)) != nullptr) { while ((cur = strtok_r(nullptr, " ", &stmt)) != nullptr) {
if (cur[0] == '*') cur = ALL; if (cur[0] == '*') cur = ALL;
Vector<const char *> *vec; vector<const char *> *vec;
switch (state) { switch (state) {
case 0: case 0:
vec = &source; vec = &source;
@ -200,10 +204,10 @@ static int parse_pattern_2(int action, const char *action_str, char *stmt) {
int state = 0; int state = 0;
char *cur, *range; char *cur, *range;
Vector<const char *> source, target, classes; vector<const char *> source, target, classes;
while ((cur = strtok_r(nullptr, " ", &stmt)) != nullptr) { while ((cur = strtok_r(nullptr, " ", &stmt)) != nullptr) {
if (cur[0] == '*') cur = ALL; if (cur[0] == '*') cur = ALL;
Vector<const char *> *vec; vector<const char *> *vec;
switch (state) { switch (state) {
case 0: case 0:
vec = &source; vec = &source;
@ -216,7 +220,7 @@ static int parse_pattern_2(int action, const char *action_str, char *stmt) {
break; break;
case 3: case 3:
// Currently only support ioctl // Currently only support ioctl
if (strcmp(cur, "ioctl")) if (strcmp(cur, "ioctl") != 0)
return 1; return 1;
vec = nullptr; vec = nullptr;
break; break;
@ -262,7 +266,7 @@ static int parse_pattern_3(int action, const char *action_str, char* stmt) {
} }
char *cur; char *cur;
Vector<const char *> domains; vector<const char *> domains;
while ((cur = strtok_r(nullptr, " {}", &stmt)) != nullptr) { while ((cur = strtok_r(nullptr, " {}", &stmt)) != nullptr) {
if (cur[0] == '*') cur = ALL; if (cur[0] == '*') cur = ALL;
domains.push_back(cur); domains.push_back(cur);
@ -291,10 +295,10 @@ static int parse_pattern_4(int action, const char *action_str, char *stmt) {
int state = 0; int state = 0;
char *cur; char *cur;
Vector<const char *> classes, attribute; vector<const char *> classes, attribute;
while ((cur = strtok_r(nullptr, " ", &stmt)) != nullptr) { while ((cur = strtok_r(nullptr, " ", &stmt)) != nullptr) {
if (cur[0] == '*') cur = ALL; if (cur[0] == '*') cur = ALL;
Vector<const char *> *vec; vector<const char *> *vec;
switch (state) { switch (state) {
case 0: case 0:
vec = &classes; vec = &classes;
@ -409,7 +413,7 @@ static void parse_statement(char *statement) {
char *action, *remain; char *action, *remain;
// strtok will modify the origin string, duplicate the statement for error messages // strtok will modify the origin string, duplicate the statement for error messages
CharArray orig(statement); string orig(statement);
action = strtok_r(statement, " ", &remain); action = strtok_r(statement, " ", &remain);
if (remain == nullptr) remain = &action[strlen(action)]; if (remain == nullptr) remain = &action[strlen(action)];

View File

@ -5,15 +5,15 @@
#ifndef MAGISK_PROPS_H #ifndef MAGISK_PROPS_H
#define MAGISK_PROPS_H #define MAGISK_PROPS_H
#include <CharArray.h> #include <string>
#include "resetprop/private/system_properties.h" #include "resetprop/private/system_properties.h"
#include "logging.h" #include "logging.h"
struct prop_t { struct prop_t {
char *name; char *name;
char value[PROP_VALUE_MAX]; char value[PROP_VALUE_MAX];
prop_t() = default; prop_t() : name(nullptr) {}
prop_t(const char *name) { explicit prop_t(const char *name) {
this->name = strdup(name); this->name = strdup(name);
value[0] = '\0'; value[0] = '\0';
} }
@ -21,7 +21,13 @@ struct prop_t {
this->name = strdup(name); this->name = strdup(name);
strcpy(this->value, value); strcpy(this->value, value);
} }
prop_t& operator= (prop_t&& prop) { prop_t(prop_t &&prop): name(nullptr) {
operator=(std::move(prop));
}
bool operator<(const prop_t &prop) const {
return strcmp(name, prop.name) < 0;
}
prop_t& operator= (prop_t &&prop) {
if (this != &prop) { if (this != &prop) {
free(name); free(name);
name = prop.name; name = prop.name;
@ -38,7 +44,7 @@ struct prop_t {
struct read_cb_t { struct read_cb_t {
void (*cb)(const char *, const char *, void *); void (*cb)(const char *, const char *, void *);
void *arg; void *arg;
read_cb_t(void (*cb)(const char *, const char *, void *) = nullptr, void *arg = nullptr) explicit read_cb_t(void (*cb)(const char *, const char *, void *) = nullptr, void *arg = nullptr)
: cb(cb), arg(arg) {} : cb(cb), arg(arg) {}
void exec(const char *name, const char *value) { void exec(const char *name, const char *value) {
cb(name, value, arg); cb(name, value, arg);
@ -49,7 +55,7 @@ struct read_cb_t {
extern bool use_pb; extern bool use_pb;
CharArray persist_getprop(const char *name); std::string persist_getprop(const char *name);
void persist_getprop(read_cb_t *read_cb); void persist_getprop(read_cb_t *read_cb);
bool persist_deleteprop(const char *name); bool persist_deleteprop(const char *name);
void collect_props(const char *name, const char *value, void *v_plist); void collect_props(const char *name, const char *value, void *v_plist);

View File

@ -5,6 +5,8 @@
#include <unistd.h> #include <unistd.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <vector>
#include <pb.h> #include <pb.h>
#include <pb_decode.h> #include <pb_decode.h>
#include <pb_encode.h> #include <pb_encode.h>
@ -12,6 +14,8 @@
#include "_resetprop.h" #include "_resetprop.h"
#include "utils.h" #include "utils.h"
using namespace std;
/* *********************************************************************** /* ***********************************************************************
* Auto generated header and constant definitions compiled from * Auto generated header and constant definitions compiled from
* android/platform/system/core/master/init/persistent_properties.proto * android/platform/system/core/master/init/persistent_properties.proto
@ -113,7 +117,7 @@ static bool prop_encode(pb_ostream_t *stream, const pb_field_t *field, void * co
PersistentProperties_PersistentPropertyRecord prop = {}; PersistentProperties_PersistentPropertyRecord prop = {};
prop.name.funcs.encode = name_encode; prop.name.funcs.encode = name_encode;
prop.has_value = true; prop.has_value = true;
Vector<prop_t> &prop_list = *(Vector<prop_t> *) *arg; auto &prop_list = *(vector<prop_t> *) *arg;
for (auto &p : prop_list) { for (auto &p : prop_list) {
if (!pb_encode_tag_for_field(stream, field)) if (!pb_encode_tag_for_field(stream, field))
return false; return false;
@ -160,16 +164,16 @@ static void pb_getprop(read_cb_t *read_cb) {
munmap(buf, size); munmap(buf, size);
} }
static void file_getprop(const char *name, char *value) { static bool file_getprop(const char *name, char *value) {
value[0] = '\0';
char path[PATH_MAX]; char path[PATH_MAX];
snprintf(path, sizeof(path), PERSISTENT_PROPERTY_DIR "/%s", name); snprintf(path, sizeof(path), PERSISTENT_PROPERTY_DIR "/%s", name);
int fd = open(path, O_RDONLY | O_CLOEXEC); int fd = open(path, O_RDONLY | O_CLOEXEC);
if (fd < 0) if (fd < 0)
return; return false;
LOGD("resetprop: read prop from [%s]\n", path); LOGD("resetprop: read prop from [%s]\n", path);
value[read(fd, value, sizeof(PROP_VALUE_MAX))] = '\0'; // Null terminate the read value value[read(fd, value, PROP_VALUE_MAX)] = '\0'; // Null terminate the read value
close(fd); close(fd);
return value[0] != '\0';
} }
void persist_getprop(read_cb_t *read_cb) { void persist_getprop(read_cb_t *read_cb) {
@ -182,14 +186,13 @@ void persist_getprop(read_cb_t *read_cb) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0 ) if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0 )
continue; continue;
char value[PROP_VALUE_MAX]; char value[PROP_VALUE_MAX];
file_getprop(entry->d_name, value); if (file_getprop(entry->d_name, value))
if (value[0])
read_cb->exec(entry->d_name, value); read_cb->exec(entry->d_name, value);
} }
} }
} }
CharArray persist_getprop(const char *name) { string persist_getprop(const char *name) {
prop_t prop(name); prop_t prop(name);
if (use_pb) { if (use_pb) {
read_cb_t read_cb(pb_getprop_cb, &prop); read_cb_t read_cb(pb_getprop_cb, &prop);
@ -199,21 +202,20 @@ CharArray persist_getprop(const char *name) {
} else { } else {
// Try to read from file // Try to read from file
char value[PROP_VALUE_MAX]; char value[PROP_VALUE_MAX];
file_getprop(name, value); if (file_getprop(name, value))
if (value[0])
return value; return value;
} }
return CharArray(); return string();
} }
bool persist_deleteprop(const char *name) { bool persist_deleteprop(const char *name) {
if (use_pb) { if (use_pb) {
Vector<prop_t> prop_list; vector<prop_t> prop_list;
read_cb_t read_cb(collect_props, &prop_list); read_cb_t read_cb(collect_props, &prop_list);
persist_getprop(&read_cb); persist_getprop(&read_cb);
for (auto it = prop_list.begin(); it != prop_list.end(); ++it) { for (auto it = prop_list.begin(); it != prop_list.end(); ++it) {
if (strcmp((*it).name, name) == 0) { if (strcmp(it->name, name) == 0) {
prop_list.erase(it); prop_list.erase(it);
// Dump the props back // Dump the props back
PersistentProperties props = PersistentProperties_init_zero; PersistentProperties props = PersistentProperties_init_zero;

View File

@ -6,6 +6,8 @@
#include <string.h> #include <string.h>
#include <dirent.h> #include <dirent.h>
#include <sys/types.h> #include <sys/types.h>
#include <vector>
#include <algorithm>
#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
#include "private/_system_properties.h" #include "private/_system_properties.h"
@ -17,6 +19,8 @@
#include "utils.h" #include "utils.h"
#include "flags.h" #include "flags.h"
using namespace std;
bool use_pb = false; bool use_pb = false;
static bool verbose = false; static bool verbose = false;
@ -74,12 +78,6 @@ illegal:
exit(1); exit(1);
} }
// Define the way to sort prop_t
template<>
int(*Vector<prop_t>::_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) { static void read_props(const prop_info *pi, void *read_cb) {
__system_property_read_callback( __system_property_read_callback(
pi, [](auto cb, auto name, auto value, auto) -> void pi, [](auto cb, auto name, auto value, auto) -> void
@ -89,12 +87,12 @@ static void read_props(const prop_info *pi, void *read_cb) {
} }
void collect_props(const char *name, const char *value, void *v_plist) { void collect_props(const char *name, const char *value, void *v_plist) {
Vector<prop_t> &prop_list = *static_cast<Vector<prop_t> *>(v_plist); auto &prop_list = *static_cast<vector<prop_t> *>(v_plist);
prop_list.push_back(prop_t(name, value)); prop_list.emplace_back(name, value);
} }
static void collect_unique_props(const char *name, const char *value, void *v_plist) { static void collect_unique_props(const char *name, const char *value, void *v_plist) {
Vector<prop_t> &prop_list = *static_cast<Vector<prop_t> *>(v_plist); auto &prop_list = *static_cast<vector<prop_t> *>(v_plist);
for (auto &prop : prop_list) { for (auto &prop : prop_list) {
if (strcmp(name, prop.name) == 0) if (strcmp(name, prop.name) == 0)
return; return;
@ -112,9 +110,9 @@ static int init_resetprop() {
} }
static void print_props(bool persist) { static void print_props(bool persist) {
Vector<prop_t> prop_list; vector<prop_t> prop_list;
getprop(collect_props, &prop_list, persist); getprop(collect_props, &prop_list, persist);
prop_list.sort(); sort(prop_list.begin(), prop_list.end());
for (auto &prop : prop_list) for (auto &prop : prop_list)
printf("[%s]: [%s]\n", prop.name, prop.value); printf("[%s]: [%s]\n", prop.name, prop.value);
} }
@ -128,19 +126,19 @@ int prop_exist(const char *name) {
return __system_property_find(name) != nullptr; return __system_property_find(name) != nullptr;
} }
// Get prop by name, return string (should free manually!) // Get prop by name, return string
CharArray getprop(const char *name, bool persist) { string getprop(const char *name, bool persist) {
if (!check_legal_property_name(name) || init_resetprop()) if (!check_legal_property_name(name) || init_resetprop())
return nullptr; return nullptr;
const prop_info *pi = __system_property_find(name); const prop_info *pi = __system_property_find(name);
if (pi == nullptr) { if (pi == nullptr) {
if (persist && strncmp(name, "persist.", 8) == 0) { if (persist && strncmp(name, "persist.", 8) == 0) {
CharArray value = persist_getprop(name); auto value = persist_getprop(name);
if (!value.empty()) if (value.empty())
return value; LOGD("resetprop: prop [%s] does not exist\n", name);
return value;
} }
LOGD("resetprop: prop [%s] does not exist\n", name); return string();
return CharArray();
} else { } else {
char value[PROP_VALUE_MAX]; char value[PROP_VALUE_MAX];
read_cb_t read_cb; read_cb_t read_cb;
@ -162,7 +160,7 @@ void getprop(void (*callback)(const char *, const char *, void *), void *cookie,
} }
} }
int setprop(const char *name, const char *value, const bool trigger) { int setprop(const char *name, const char *value, bool trigger) {
if (!check_legal_property_name(name)) if (!check_legal_property_name(name))
return 1; return 1;
if (init_resetprop()) if (init_resetprop())
@ -170,7 +168,7 @@ int setprop(const char *name, const char *value, const bool trigger) {
int ret; int ret;
prop_info *pi = (prop_info*) __system_property_find(name); auto pi = (prop_info*) __system_property_find(name);
if (pi != nullptr) { if (pi != nullptr) {
if (trigger) { if (trigger) {
if (strncmp(name, "ro.", 3) == 0) deleteprop(name); if (strncmp(name, "ro.", 3) == 0) deleteprop(name);
@ -208,7 +206,7 @@ int deleteprop(const char *name, bool persist) {
return __system_property_del(name) && !(persist && strncmp(name, "persist.", 8) == 0); return __system_property_del(name) && !(persist && strncmp(name, "persist.", 8) == 0);
} }
int load_prop_file(const char *filename, const bool trigger) { int load_prop_file(const char *filename, bool trigger) {
if (init_resetprop()) return -1; if (init_resetprop()) return -1;
LOGD("resetprop: Load prop file [%s]\n", filename); LOGD("resetprop: Load prop file [%s]\n", filename);
FILE *fp = xfopen(filename, "re"); FILE *fp = xfopen(filename, "re");
@ -254,14 +252,14 @@ int resetprop_main(int argc, char *argv[]) {
bool trigger = true, persist = false; bool trigger = true, persist = false;
char *argv0 = argv[0]; char *argv0 = argv[0];
CharArray prop; string prop;
--argc; --argc;
++argv; ++argv;
// Parse flags and -- options // Parse flags and -- options
while (argc && argv[0][0] == '-') { while (argc && argv[0][0] == '-') {
for (int idx = 1; 1; ++idx) { for (int idx = 1; true; ++idx) {
switch (argv[0][idx]) { switch (argv[0][idx]) {
case '-': case '-':
if (strcmp(argv[0], "--file") == 0 && argc == 2) { if (strcmp(argv[0], "--file") == 0 && argc == 2) {
@ -275,10 +273,10 @@ int resetprop_main(int argc, char *argv[]) {
verbose = true; verbose = true;
continue; continue;
case 'p': case 'p':
persist = 1; persist = true;
continue; continue;
case 'n': case 'n':
trigger = 0; trigger = false;
continue; continue;
case '\0': case '\0':
break; break;
@ -297,8 +295,8 @@ int resetprop_main(int argc, char *argv[]) {
print_props(persist); print_props(persist);
return 0; return 0;
case 1: case 1:
prop = utils::move(getprop(argv[0], persist)); prop = getprop(argv[0], persist);
if (!prop) return 1; if (prop.empty()) return 1;
printf("%s\n", prop.c_str()); printf("%s\n", prop.c_str());
return 0; return 0;
case 2: case 2:

View File

@ -9,7 +9,6 @@ LOCAL_SRC_FILES := \
misc.cpp \ misc.cpp \
selinux.cpp \ selinux.cpp \
logging.cpp \ logging.cpp \
xwrap.cpp \ xwrap.cpp
CharArray.cpp
include $(BUILD_STATIC_LIBRARY) include $(BUILD_STATIC_LIBRARY)

View File

@ -1,99 +0,0 @@
#include "CharArray.h"
#include "utils.h"
CharArray::CharArray() : _buf(nullptr), _size(0){}
CharArray::CharArray(const char *s) : CharArray() {
this->operator=(s);
}
CharArray::CharArray(const CharArray &s) : CharArray() {
this->operator=(s);
}
CharArray::CharArray(size_t i) {
_size = i;
_buf = new char[i](); /* Zero initialize */
}
CharArray::~CharArray() {
delete[] _buf;
}
CharArray::operator char *() {
return _buf;
}
CharArray::operator const char *() const {
return _buf;
}
const char *CharArray::c_str() const {
return _buf;
}
size_t CharArray::length() const {
return strlen(_buf);
}
size_t CharArray::size() const {
return _size;
}
CharArray &CharArray::operator=(const CharArray &s) {
delete[] _buf;
_size = s._size;
_buf = new char[_size];
memcpy(_buf, s._buf, _size);
return *this;
}
CharArray &CharArray::operator=(const char *s) {
delete[] _buf;
_buf = strdup2(s, &_size);
return *this;
}
CharArray &CharArray::operator=(CharArray &&s) {
delete[] _buf;
_size = s._size;
_buf = s._buf;
s._buf = nullptr;
s._size = 0;
return *this;
}
bool CharArray::operator==(const char *s) const {
if (_buf == nullptr || s == nullptr)
return false;
return strcmp(_buf, s) == 0;
}
bool CharArray::operator==(char *s) const {
return *this == (const char *) s;
}
bool CharArray::operator!=(const char *s) const {
return !(*this == s);
}
int CharArray::compare(const char *s) const {
return strcmp(_buf, s);
}
int CharArray::compare(const char *s, size_t len) const {
return strncmp(_buf, s, len);
}
bool CharArray::contains(const char *s) const {
return s == nullptr ? false : strstr(_buf, s) != nullptr;
}
bool CharArray::starts_with(const char *s) const {
return s == nullptr ? false : compare(s, strlen(s)) == 0;
}
bool CharArray::empty() const {
return _buf == nullptr || _buf[0] == '\0';
}

View File

@ -15,6 +15,8 @@
#include "utils.h" #include "utils.h"
#include "selinux.h" #include "selinux.h"
using namespace std;
const char **excl_list = nullptr; const char **excl_list = nullptr;
static int is_excl(const char *name) { static int is_excl(const char *name) {
@ -307,7 +309,7 @@ void clone_attr(const char *source, const char *target) {
setattr(target, &a); setattr(target, &a);
} }
void fclone_attr(const int sourcefd, const int targetfd) { void fclone_attr(int sourcefd, int targetfd) {
struct file_attr a; struct file_attr a;
fgetattr(sourcefd, &a); fgetattr(sourcefd, &a);
fsetattr(targetfd, &a); fsetattr(targetfd, &a);
@ -388,24 +390,25 @@ void write_zero(int fd, size_t size) {
lseek(fd, pos + size, SEEK_SET); lseek(fd, pos + size, SEEK_SET);
} }
int file_to_vector(const char *filename, Vector<CharArray> &arr) { vector<string> file_to_vector(const char *filename) {
auto arr = vector<string>();
if (access(filename, R_OK) != 0) if (access(filename, R_OK) != 0)
return 1; return arr;
char *line = nullptr; char *line = nullptr;
size_t len = 0; size_t len = 0;
ssize_t read; ssize_t read;
FILE *fp = xfopen(filename, "re"); FILE *fp = xfopen(filename, "re");
if (fp == nullptr) if (fp == nullptr)
return 1; return arr;
while ((read = getline(&line, &len, fp)) != -1) { while ((read = getline(&line, &len, fp)) != -1) {
// Remove end newline // Remove end newline
if (line[read - 1] == '\n') if (line[read - 1] == '\n')
line[read - 1] = '\0'; line[read - 1] = '\0';
arr.push_back(line); arr.emplace_back(line);
} }
fclose(fp); fclose(fp);
free(line); free(line);
return 0; return arr;
} }

View File

@ -1,39 +0,0 @@
#pragma once
#include <string.h>
/* A wrapper around char array */
class CharArray {
public:
CharArray();
CharArray(const char *s);
CharArray(const CharArray &s);
CharArray(size_t i);
~CharArray();
CharArray &operator=(const CharArray &s);
CharArray &operator=(CharArray &&s);
CharArray &operator=(const char *s);
operator char *();
operator const char *() const;
bool operator==(char *s) const;
bool operator==(const char *s) const;
bool operator!=(const char *s) const;
int compare(const char *s) const;
int compare(const char *s, size_t len) const;
bool starts_with(const char *s) const;
bool contains(const char *s) const;
bool empty() const;
const char *c_str() const;
size_t length() const;
size_t size() const;
/* These 2 ops are incompatible with implicit char* conversion */
// char &operator[](size_t i);
// const char &operator[](size_t i) const;
private:
char *_buf;
size_t _size;
};

View File

@ -1,191 +0,0 @@
#pragma once
#include <stdlib.h>
#include "cpputils.h"
template <class T>
class Vector {
public:
Vector() : _data(0), _size(0), _capacity(0) {}
~Vector() { delete []_data; }
class iterator {
friend class Vector;
public:
iterator(T* n= 0): _node(n) {}
iterator(const iterator& i): _node(i._node) {}
~iterator() {} // Should NOT delete _node
const T& operator * () const { return (*_node); }
T& operator * () { return (*_node); }
iterator& operator ++ () {
++_node;
return (*this);
}
iterator operator ++ (int) {
iterator temp = *this;
++_node;
return temp;
}
iterator& operator -- () {
--_node;
return (*this);
}
iterator operator -- (int) {
iterator temp = *this;
--_node;
return temp;
}
iterator operator + (int i) const {
iterator temp = *this;
temp += i;
return temp;
}
iterator& operator += (int i) {
_node += i;
return (*this);
}
iterator& operator = (const iterator& i) {
_node = i._node;
return (*this);
}
bool operator != (const iterator& i) const {
return _node != i._node;
}
bool operator == (const iterator& i) const { return !(*this != i); }
private:
T* _node;
};
Vector &operator=(const Vector& a) {
delete [] _data;
_data = nullptr;
_size = a._size;
_capacity = a._capacity;
if (_capacity) {
_data = new T[_capacity];
for(int i = 0; i < _size; ++i)
_data[i] = a[i];
}
return *this;
}
Vector &operator=(Vector&& a) {
delete [] _data;
_size = a._size;
_capacity = a._capacity;
_data = a._data;
a._size = 0;
a._capacity = 0;
a._data = nullptr;
return *this;
}
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]; }
void push_back(const T& x) {
if(_size == _capacity)
expand();
_data[_size] = x;
++_size;
}
void push_back(T&& x) {
if(_size == _capacity)
expand();
_data[_size] = utils::move(x);
++_size;
}
void pop_front() { erase(begin()); }
void pop_back() { if(_size) --_size; }
bool erase(iterator pos) {
T* d = pos._node;
if (_size == 0 || d < _data || d >= _data + _size)
return false;
for (; d < _data + _size - 1; ++d)
*d = utils::move(*(d + 1));
--_size;
return true;
}
bool erase(const T& x) {
for (T* i = _data; i < _data + _size; ++i) {
if(*i == x) {
erase(iterator(i));
return true;
}
}
return false;
}
void clear(bool dealloc = false) {
_size = 0;
if (dealloc) {
_capacity = 0;
delete [] _data;
_data = nullptr;
}
}
void sort() {
qsort(_data, _size, sizeof(T), compare);
}
T* data() { return _data; }
const T* data() const { return _data; }
// void reserve(size_t n) { ... }
// void resize(size_t n) { ... }
private:
T* _data;
size_t _size; // number of valid elements
size_t _capacity; // max number of elements
static int(*_cmp)(T&, T&);
static int compare(const void *a, const void *b) {
return _cmp ? _cmp(*((T*) a), *((T*) b)) : 0;
}
void expand() {
if (_capacity == 0)
_capacity = 1;
else
_capacity *= 2;
T* temp = _data;
_data = new T[_capacity];
for(int i = 0; i < _size; ++i)
_data[i] = utils::move(temp[i]);
delete [] temp;
}
};
template<class T>
int(* Vector<T>::_cmp)(T&, T&) = nullptr;

View File

@ -1,12 +0,0 @@
#pragma once
namespace utils {
template< class T > struct remove_reference {typedef T type;};
template< class T > struct remove_reference<T&> {typedef T type;};
template< class T > struct remove_reference<T&&> {typedef T type;};
template< class T >
constexpr typename remove_reference<T>::type&& move( T&& t ) noexcept {
return static_cast<typename remove_reference<T>::type&&>(t);
}
}

View File

@ -13,15 +13,17 @@
#ifdef __cplusplus #ifdef __cplusplus
#include "Vector.h" #include <string>
#include "CharArray.h" #include <vector>
#include "cpputils.h"
int file_to_vector(const char *filename, Vector<CharArray> &arr); #define str_contains(s, ss) ((s).find(ss) != string::npos)
#define str_starts(s, ss) ((s).compare(0, strlen(ss), ss) == 0)
std::vector<std::string> file_to_vector(const char *filename);
char *strdup2(const char *s, size_t *size = nullptr); char *strdup2(const char *s, size_t *size = nullptr);
int exec_array(bool err, int *fd, void (*pre_exec)(void), const char **argv); int exec_array(bool err, int *fd, void (*pre_exec)(), const char **argv);
int exec_command(bool err, int *fd, void (*cb)(void), const char *argv0, ...); int exec_command(bool err, int *fd, void (*cb)(), const char *argv0, ...);
extern "C" { extern "C" {
#endif #endif
@ -134,7 +136,7 @@ int fgetattr(int fd, struct file_attr *a);
int setattr(const char *path, struct file_attr *a); int setattr(const char *path, struct file_attr *a);
int setattrat(int dirfd, const char *pathname, struct file_attr *a); int setattrat(int dirfd, const char *pathname, struct file_attr *a);
int fsetattr(int fd, struct file_attr *a); int fsetattr(int fd, struct file_attr *a);
void fclone_attr(const int sourcefd, const int targetfd); void fclone_attr(int sourcefd, int targetfd);
void clone_attr(const char *source, const char *target); void clone_attr(const char *source, const char *target);
void mmap_ro(const char *filename, void **buf, size_t *size); void mmap_ro(const char *filename, void **buf, size_t *size);
void mmap_rw(const char *filename, void **buf, size_t *size); void mmap_rw(const char *filename, void **buf, size_t *size);

View File

@ -11,10 +11,13 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/sysmacros.h> #include <sys/sysmacros.h>
#include <vector>
#include "logging.h" #include "logging.h"
#include "utils.h" #include "utils.h"
using namespace std;
unsigned get_shell_uid() { unsigned get_shell_uid() {
struct passwd* ppwd = getpwnam("shell"); struct passwd* ppwd = getpwnam("shell");
if (nullptr == ppwd) if (nullptr == ppwd)
@ -199,7 +202,7 @@ int exec_array(bool err, int *fd, void (*pre_exec)(void), const char **argv) {
static int v_exec_command(bool err, int *fd, void (*cb)(void), const char *argv0, va_list argv) { static int v_exec_command(bool err, int *fd, void (*cb)(void), const char *argv0, va_list argv) {
// Collect va_list into vector // Collect va_list into vector
Vector<const char *> args; vector<const char *> args;
args.push_back(argv0); args.push_back(argv0);
for (const char *arg = va_arg(argv, char*); arg; arg = va_arg(argv, char*)) for (const char *arg = va_arg(argv, char*); arg; arg = va_arg(argv, char*))
args.push_back(arg); args.push_back(arg);

View File

@ -1,6 +1,9 @@
#include <new> #include <new>
#include <stdlib.h> #include <stdlib.h>
/* Override libc++ new implementation
* to optimize final build size */
void* operator new(std::size_t s) { return malloc(s); } void* operator new(std::size_t s) { return malloc(s); }
void* operator new[](std::size_t s) { return malloc(s); } void* operator new[](std::size_t s) { return malloc(s); }
void operator delete(void *p) { free(p); } void operator delete(void *p) { free(p); }

View File

@ -86,7 +86,7 @@ ssize_t xread(int fd, void *buf, size_t count) {
ssize_t xxread(int fd, void *buf, size_t count) { ssize_t xxread(int fd, void *buf, size_t count) {
int ret = read(fd, buf, count); int ret = read(fd, buf, count);
if (count != ret) { if (count != ret) {
PLOGE("read"); PLOGE("read (%d != %d)", count, ret);
} }
return ret; return ret;
} }