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
#define IS_DUMMY 0x01 /* mount from mirror */
#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_DIR(n) ((n)->type == DT_DIR)
@ -57,7 +57,8 @@ extern void auto_start_magiskhide();
class node_entry {
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();
void create_module_tree(const char *module);
void magic_mount();
@ -71,29 +72,25 @@ private:
node_entry *parent;
vector<node_entry *> children;
node_entry(const char *, const char *, uint8_t type);
bool is_root();
node_entry(node_entry *parent, const char *module, const char *name, uint8_t type)
: node_entry(name, 0, type) {
this->parent = parent;
this->module = module;
}
bool is_vendor();
string get_path();
node_entry *insert(node_entry *);
void insert(node_entry *&);
void clone_skeleton();
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() {
for (auto &node : children)
delete node;
}
bool node_entry::is_root() {
return parent == nullptr;
bool node_entry::is_vendor() {
return parent ? (parent->parent ? false : name == "vendor") : false;
}
string node_entry::get_path() {
@ -109,7 +106,7 @@ int node_entry::get_path(char *path) {
return len;
}
node_entry *node_entry::insert(node_entry *node) {
void node_entry::insert(node_entry *&node) {
node->parent = this;
for (auto &child : children) {
if (child->name == node->name) {
@ -117,15 +114,14 @@ node_entry *node_entry::insert(node_entry *node) {
// The new node has higher precedence
delete child;
child = node;
return node;
} else {
delete node;
return child;
node = child;
}
return;
}
}
children.push_back(node);
return node;
}
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();
snprintf(buf, PATH_MAX, "%s/%s%s", MODULEROOT, module, full_path.c_str());
if (!(dir = xopendir(buf)))
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)
continue;
// 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);
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:
@ -154,7 +153,7 @@ void node_entry::create_module_tree(const char *module) {
bool clone = false;
if (IS_LNK(node) || access(buf, F_OK) == -1) {
clone = true;
} else if (!is_root() || node->name != "vendor") {
} else if (!node->is_vendor()) {
struct stat s;
xstat(buf, &s);
if (S_ISLNK(s.st_mode))
@ -165,23 +164,27 @@ void node_entry::create_module_tree(const char *module) {
// Mark self as a skeleton
status |= IS_SKEL; /* This will not overwrite if parent is module */
node->status = IS_MODULE;
} else if (IS_DIR(node)) {
// Check if marked as replace
snprintf(buf2, PATH_MAX, "%s/%s%s/.replace", MODULEROOT, module, buf);
if (access(buf2, F_OK) == 0) {
// Replace everything, mark as leaf
} else {
// Clone attributes from real path
clone_attr(buf, buf2);
if (IS_DIR(node)) {
// 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;
} 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);
if (node->status & (IS_SKEL | IS_INTER)) {
// Intermediate folder, travel deeper
insert(node);
if (IS_DIR(node)) {
// Recursive traverse through everything
node->create_module_tree(module);
}
}
@ -225,7 +228,7 @@ void node_entry::clone_skeleton() {
close(creat(buf, 0644));
// Links will be handled later
if (is_root() && child->name == "vendor") {
if (child->is_vendor()) {
if (seperate_vendor) {
cp_afc(MIRRDIR "/system/vendor", "/system/vendor");
VLOGI("copy_link ", "/system/vendor", MIRRDIR "/system/vendor");
@ -270,13 +273,13 @@ void node_entry::magic_mount() {
for (auto &child : children)
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
}
node_entry *node_entry::extract(const char *name) {
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) {
if (child->name == name) {
node = child;