Always clone attribute from existing files to module files

This makes sure no weird permission/SELinux issues shall happen
This commit is contained in:
topjohnwu 2019-02-25 05:17:08 -05:00
parent c9fa8118d1
commit 0c227f2917

View File

@ -48,7 +48,7 @@ extern void auto_start_magiskhide();
// Precedence: MODULE > SKEL > INTER > DUMMY // Precedence: MODULE > SKEL > INTER > DUMMY
#define IS_DUMMY 0x01 /* mount from mirror */ #define IS_DUMMY 0x01 /* mount from mirror */
#define IS_INTER 0x02 /* intermediate node */ #define IS_INTER 0x02 /* intermediate node */
#define IS_SKEL 0x04 /* mount from skeleton */ #define IS_SKEL 0x04 /* replace with tmpfs */
#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)
@ -57,7 +57,8 @@ extern void auto_start_magiskhide();
class node_entry { class node_entry {
public: public:
explicit node_entry(const char *, uint8_t status = 0, uint8_t type = 0); explicit node_entry(const char *name, uint8_t status = 0, uint8_t type = 0)
: name(name), type(type), status(status), parent(nullptr) {}
~node_entry(); ~node_entry();
void create_module_tree(const char *module); void create_module_tree(const char *module);
void magic_mount(); void magic_mount();
@ -71,29 +72,25 @@ private:
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(node_entry *parent, const char *module, const char *name, uint8_t type)
bool is_root(); : node_entry(name, 0, type) {
this->parent = parent;
this->module = module;
}
bool is_vendor();
string get_path(); string get_path();
node_entry *insert(node_entry *); void insert(node_entry *&);
void clone_skeleton(); void clone_skeleton();
int get_path(char *path); int get_path(char *path);
}; };
node_entry::node_entry(const char *name, uint8_t status, uint8_t type)
: name(name), type(type), status(status), parent(nullptr) {}
node_entry::node_entry(const char *module, const char *name, uint8_t type)
: node_entry(name, (uint8_t) 0, type) {
this->module = module;
}
node_entry::~node_entry() { node_entry::~node_entry() {
for (auto &node : children) for (auto &node : children)
delete node; delete node;
} }
bool node_entry::is_root() { bool node_entry::is_vendor() {
return parent == nullptr; return parent ? (parent->parent ? false : name == "vendor") : false;
} }
string node_entry::get_path() { string node_entry::get_path() {
@ -109,7 +106,7 @@ int node_entry::get_path(char *path) {
return len; return len;
} }
node_entry *node_entry::insert(node_entry *node) { void node_entry::insert(node_entry *&node) {
node->parent = this; node->parent = this;
for (auto &child : children) { for (auto &child : children) {
if (child->name == node->name) { if (child->name == node->name) {
@ -117,15 +114,14 @@ node_entry *node_entry::insert(node_entry *node) {
// The new node has higher precedence // The new node has higher precedence
delete child; delete child;
child = node; child = node;
return node;
} else { } else {
delete node; delete node;
return child; node = child;
} }
return;
} }
} }
children.push_back(node); children.push_back(node);
return node;
} }
void node_entry::create_module_tree(const char *module) { void node_entry::create_module_tree(const char *module) {
@ -134,7 +130,6 @@ void node_entry::create_module_tree(const char *module) {
auto full_path = get_path(); auto full_path = get_path();
snprintf(buf, PATH_MAX, "%s/%s%s", MODULEROOT, module, full_path.c_str()); snprintf(buf, PATH_MAX, "%s/%s%s", MODULEROOT, module, full_path.c_str());
if (!(dir = xopendir(buf))) if (!(dir = xopendir(buf)))
return; return;
@ -142,8 +137,12 @@ 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
auto node = new node_entry(module, entry->d_name, entry->d_type); auto node = new node_entry(this, module, entry->d_name, entry->d_type);
// buf = real path, buf2 = module path
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);
int eo2 = snprintf(buf2, PATH_MAX, MODULEROOT "/%s%s/%s",
module, full_path.c_str(), entry->d_name);
/* /*
* Clone the parent in the following condition: * Clone the parent in the following condition:
@ -154,7 +153,7 @@ void node_entry::create_module_tree(const char *module) {
bool clone = false; bool clone = false;
if (IS_LNK(node) || access(buf, F_OK) == -1) { if (IS_LNK(node) || access(buf, F_OK) == -1) {
clone = true; clone = true;
} else if (!is_root() || node->name != "vendor") { } else if (!node->is_vendor()) {
struct stat s; struct stat s;
xstat(buf, &s); xstat(buf, &s);
if (S_ISLNK(s.st_mode)) if (S_ISLNK(s.st_mode))
@ -165,23 +164,27 @@ void node_entry::create_module_tree(const char *module) {
// Mark self as a skeleton // Mark self as a skeleton
status |= IS_SKEL; /* This will not overwrite if parent is module */ status |= IS_SKEL; /* This will not overwrite if parent is module */
node->status = IS_MODULE; node->status = IS_MODULE;
} else if (IS_DIR(node)) { } else {
// Check if marked as replace // Clone attributes from real path
snprintf(buf2, PATH_MAX, "%s/%s%s/.replace", MODULEROOT, module, buf); clone_attr(buf, buf2);
if (access(buf2, F_OK) == 0) { if (IS_DIR(node)) {
// Replace everything, mark as leaf // Check if marked as replace
strcpy(buf2 + eo2, "/.replace");
if (access(buf2, F_OK) == 0) {
// Replace everything, mark as leaf
node->status = IS_MODULE;
} else {
// This will be an intermediate node
node->status = IS_INTER;
}
} else if (IS_REG(node)) {
// This is a file, mark as leaf
node->status = IS_MODULE; node->status = IS_MODULE;
} else {
// This will be an intermediate node
node->status = IS_INTER;
} }
} else if (IS_REG(node)) {
// This is a file, mark as leaf
node->status = IS_MODULE;
} }
node = insert(node); insert(node);
if (node->status & (IS_SKEL | IS_INTER)) { if (IS_DIR(node)) {
// Intermediate folder, travel deeper // Recursive traverse through everything
node->create_module_tree(module); node->create_module_tree(module);
} }
} }
@ -225,7 +228,7 @@ void node_entry::clone_skeleton() {
close(creat(buf, 0644)); close(creat(buf, 0644));
// Links will be handled later // Links will be handled later
if (is_root() && child->name == "vendor") { if (child->is_vendor()) {
if (seperate_vendor) { if (seperate_vendor) {
cp_afc(MIRRDIR "/system/vendor", "/system/vendor"); cp_afc(MIRRDIR "/system/vendor", "/system/vendor");
VLOGI("copy_link ", "/system/vendor", MIRRDIR "/system/vendor"); VLOGI("copy_link ", "/system/vendor", MIRRDIR "/system/vendor");
@ -270,13 +273,13 @@ void node_entry::magic_mount() {
for (auto &child : children) for (auto &child : children)
child->magic_mount(); child->magic_mount();
} }
// The only thing goes here should be vendor placeholder // The only thing goes here should be placeholder nodes
// There should be no dummies, so don't need to handle it here // There should be no dummies, so don't need to handle it here
} }
node_entry *node_entry::extract(const char *name) { node_entry *node_entry::extract(const char *name) {
node_entry *node = nullptr; node_entry *node = nullptr;
// Extract the vendor node out of system tree and swap with placeholder // Extract the node out and swap with placeholder
for (auto &child : children) { for (auto &child : children) {
if (child->name == name) { if (child->name == name) {
node = child; node = child;