Use partition name or devpath's name

This commit is contained in:
LoveSy 2023-03-16 21:37:29 +08:00 committed by John Wu
parent 76405bd984
commit b9d0a3b3d4
6 changed files with 87 additions and 55 deletions

View File

@ -79,6 +79,7 @@ static void mount_mirrors() {
xmkdir(preinit_dir.data(), 0700); xmkdir(preinit_dir.data(), 0700);
auto mirror_dir = MAGISKTMP + "/" PREINITMIRR; auto mirror_dir = MAGISKTMP + "/" PREINITMIRR;
mount_mirror(preinit_dir, mirror_dir); mount_mirror(preinit_dir, mirror_dir);
xmount(nullptr, mirror_dir.data(), nullptr, MS_UNBINDABLE, nullptr);
break; break;
} }
} }
@ -109,23 +110,24 @@ static void mount_mirrors() {
} }
} }
dev_t find_preinit_device() { string find_preinit_device() {
const int UNKNOWN = 0; enum {
const int PERSIST = 1; UNKNOWN,
const int METADATA = 2; PERSIST,
const int CACHE = 3; METADATA,
const int DATA = 4; CACHE,
int matched = UNKNOWN; DATA,
dev_t rules_dev = 0; } matched = UNKNOWN;
bool encrypted = getprop("ro.crypto.state") == "encrypted"; bool encrypted = getprop("ro.crypto.state") == "encrypted";
string preinit_dir;
bool mount = getuid() == 0 && getenv("MAGISKTMP"); bool mount = getuid() == 0 && getenv("MAGISKTMP");
string preinit_source;
string preinit_dir;
for (const auto &info: parse_mount_info("self")) { for (const auto &info: parse_mount_info("self")) {
if (info.target.ends_with(PREINITMIRR)) if (info.target.ends_with(PREINITMIRR))
return info.device; return basename(info.source.data());
if (info.root != "/" || info.source.find("/dm-") != string::npos) if (info.root != "/" || info.source[0] != '/' || info.source.find("/dm-") != string::npos)
continue; continue;
if (info.type != "ext4" && info.type != "f2fs") if (info.type != "ext4" && info.type != "f2fs")
continue; continue;
@ -134,27 +136,46 @@ dev_t find_preinit_device() {
return flag == "rw"sv; return flag == "rw"sv;
}); });
if (!rw) continue; if (!rw) continue;
int new_matched; if (auto base = std::string_view(info.source).substr(0, info.source.find_last_of('/'));
if (info.target == "/cache" && matched < CACHE) { !base.ends_with("/by-name") && !base.ends_with("/block")) {
new_matched = CACHE; continue;
} else if (info.target == "/data" && matched < DATA) { }
if (encrypted && access("/data/unencrypted", F_OK)) {
switch (matched) {
case UNKNOWN:
if (info.target == "/persist" || info.target == "/mnt/vendor/persist") {
matched = PERSIST;
break;
}
[[fallthrough]];
case PERSIST:
if (info.target == "/metadata") {
matched = METADATA;
break;
}
[[fallthrough]];
case METADATA:
if (info.target == "/cache") {
matched = CACHE;
break;
}
[[fallthrough]];
case CACHE:
if (info.target == "/data") {
if (!encrypted || access("/data/unencrypted", F_OK) == 0) {
matched = DATA;
break;
}
}
[[fallthrough]];
case DATA:
continue; continue;
} else { }
new_matched = DATA;
}
} else if (info.target == "/metadata" && matched < METADATA) {
new_matched = METADATA;
} else if ((info.target == "/persist" || info.target == "/mnt/vendor/persist") &&
matched < PERSIST) {
new_matched = PERSIST;
} else continue;
if (mount) { if (mount) {
preinit_dir = resolve_preinit_dir(info.target.data()); preinit_dir = resolve_preinit_dir(info.target.data());
} }
rules_dev = info.device; preinit_source = info.source;
matched = new_matched;
} }
if (!preinit_dir.empty()) { if (!preinit_dir.empty()) {
@ -163,8 +184,7 @@ dev_t find_preinit_device() {
mkdirs(mirror_dir.data(), 0700); mkdirs(mirror_dir.data(), 0700);
xmount(preinit_dir.data(), mirror_dir.data(), nullptr, MS_BIND, nullptr); xmount(preinit_dir.data(), mirror_dir.data(), nullptr, MS_BIND, nullptr);
} }
return preinit_source.empty() ? "" : basename(preinit_source.data());
return rules_dev;
} }
static bool magisk_env() { static bool magisk_env() {

View File

@ -6,7 +6,7 @@
extern bool RECOVERY_MODE; extern bool RECOVERY_MODE;
extern std::atomic<ino_t> pkg_xml_ino; extern std::atomic<ino_t> pkg_xml_ino;
dev_t find_preinit_device(); std::string find_preinit_device();
void unlock_blocks(); void unlock_blocks();
void reboot(); void reboot();
void start_log_daemon(); void start_log_daemon();

View File

@ -1,5 +1,4 @@
#include <sys/mount.h> #include <sys/mount.h>
#include <sys/sysmacros.h>
#include <libgen.h> #include <libgen.h>
#include <base.hpp> #include <base.hpp>
@ -134,9 +133,14 @@ int magisk_main(int argc, char *argv[]) {
} else if (argc >= 3 && argv[1] == "--install-module"sv) { } else if (argc >= 3 && argv[1] == "--install-module"sv) {
install_module(argv[2]); install_module(argv[2]);
} else if (argv[1] == "--preinit-device"sv) { } else if (argv[1] == "--preinit-device"sv) {
auto dev = find_preinit_device(); set_log_level_state(LogLevel::Warn, false);
if (dev) printf("%u:%u\n", major(dev), minor(dev)); auto name = find_preinit_device();
return dev ? 0 : 1; LOGD("preinit device: %s\n", name.data());
if (!name.empty()) {
printf("%s\n", name.data());
return 0;
}
return 1;
} }
#if 0 #if 0
/* Entry point for testing stuffs */ /* Entry point for testing stuffs */

View File

@ -57,7 +57,7 @@ public:
class MagiskInit : public BaseInit { class MagiskInit : public BaseInit {
private: private:
dev_t preinit_dev = 0; std::string preinit_dev;
void parse_config_file(); void parse_config_file();
void patch_sepolicy(const char *in, const char *out); void patch_sepolicy(const char *in, const char *out);

View File

@ -17,12 +17,14 @@ struct devinfo {
char devname[32]; char devname[32];
char partname[32]; char partname[32];
char dmname[32]; char dmname[32];
char devpath[PATH_MAX];
}; };
static vector<devinfo> dev_list; static vector<devinfo> dev_list;
static void parse_device(devinfo *dev, const char *uevent) { static void parse_device(devinfo *dev, const char *uevent) {
dev->partname[0] = '\0'; dev->partname[0] = '\0';
dev->devpath[0] = '\0';
parse_prop_file(uevent, [=](string_view key, string_view value) -> bool { parse_prop_file(uevent, [=](string_view key, string_view value) -> bool {
if (key == "MAJOR") if (key == "MAJOR")
dev->major = parse_int(value.data()); dev->major = parse_int(value.data());
@ -38,7 +40,7 @@ static void parse_device(devinfo *dev, const char *uevent) {
} }
static void collect_devices() { static void collect_devices() {
char path[128]; char path[PATH_MAX];
devinfo dev{}; devinfo dev{};
if (auto dir = xopen_dir("/sys/dev/block"); dir) { if (auto dir = xopen_dir("/sys/dev/block"); dir) {
for (dirent *entry; (entry = readdir(dir.get()));) { for (dirent *entry; (entry = readdir(dir.get()));) {
@ -51,6 +53,8 @@ static void collect_devices() {
auto name = rtrim(full_read(path)); auto name = rtrim(full_read(path));
strcpy(dev.dmname, name.data()); strcpy(dev.dmname, name.data());
} }
sprintf(path, "/sys/dev/block/%s", entry->d_name);
xrealpath(path, dev.devpath, sizeof(dev.devpath));
dev_list.push_back(dev); dev_list.push_back(dev);
} }
} }
@ -61,7 +65,7 @@ static struct {
char block_dev[64]; char block_dev[64];
} blk_info; } blk_info;
static int64_t setup_block() { static dev_t setup_block() {
if (dev_list.empty()) if (dev_list.empty())
collect_devices(); collect_devices();
@ -71,6 +75,10 @@ static int64_t setup_block() {
LOGD("Setup %s: [%s] (%d, %d)\n", dev.partname, dev.devname, dev.major, dev.minor); LOGD("Setup %s: [%s] (%d, %d)\n", dev.partname, dev.devname, dev.major, dev.minor);
else if (strcasecmp(dev.dmname, blk_info.partname) == 0) else if (strcasecmp(dev.dmname, blk_info.partname) == 0)
LOGD("Setup %s: [%s] (%d, %d)\n", dev.dmname, dev.devname, dev.major, dev.minor); LOGD("Setup %s: [%s] (%d, %d)\n", dev.dmname, dev.devname, dev.major, dev.minor);
else if (strcasecmp(dev.devname, blk_info.partname) == 0)
LOGD("Setup %s: [%s] (%d, %d)\n", dev.devname, dev.devname, dev.major, dev.minor);
else if (std::string_view(dev.devpath).ends_with("/"s + blk_info.partname))
LOGD("Setup %s: [%s] (%d, %d)\n", dev.devpath, dev.devname, dev.major, dev.minor);
else else
continue; continue;
@ -85,7 +93,7 @@ static int64_t setup_block() {
} }
// The requested partname does not exist // The requested partname does not exist
return -1; return 0;
} }
static void switch_root(const string &path) { static void switch_root(const string &path) {
@ -113,15 +121,20 @@ static void switch_root(const string &path) {
#define PREINITMNT MIRRDIR "/preinit" #define PREINITMNT MIRRDIR "/preinit"
static void mount_preinit_dir(string path, dev_t preinit_dev) { static void mount_preinit_dir(string path, string preinit_dev) {
if (!preinit_dev) return; if (preinit_dev.empty()) return;
xmknod(PREINITDEV, S_IFBLK | 0600, preinit_dev); strcpy(blk_info.partname, preinit_dev.data());
strcpy(blk_info.block_dev, PREINITDEV);
auto dev = setup_block();
if (dev == 0) {
LOGE("Cannot find preinit %s, abort!\n", preinit_dev.data());
return;
}
xmkdir(PREINITMNT, 0); xmkdir(PREINITMNT, 0);
bool mounted = false; bool mounted = false;
// First, find if it is already mounted // First, find if it is already mounted
for (auto &info : parse_mount_info("self")) { for (auto &info : parse_mount_info("self")) {
if (info.root == "/" && info.device == preinit_dev) { if (info.root == "/" && info.device == dev) {
// Already mounted, just bind mount // Already mounted, just bind mount
xmount(info.target.data(), PREINITMNT, nullptr, MS_BIND, nullptr); xmount(info.target.data(), PREINITMNT, nullptr, MS_BIND, nullptr);
mounted = true; mounted = true;
@ -147,7 +160,7 @@ static void mount_preinit_dir(string path, dev_t preinit_dev) {
} }
xumount2(PREINITMNT, MNT_DETACH); xumount2(PREINITMNT, MNT_DETACH);
} else { } else {
PLOGE("Failed to mount rules %u:%u", major(preinit_dev), minor(preinit_dev)); PLOGE("Failed to mount preinit %s\n", preinit_dev.data());
unlink(PREINITDEV); unlink(PREINITDEV);
} }
} }
@ -164,18 +177,18 @@ bool LegacySARInit::mount_system_root() {
// Try legacy SAR dm-verity // Try legacy SAR dm-verity
strcpy(blk_info.partname, "vroot"); strcpy(blk_info.partname, "vroot");
auto dev = setup_block(); auto dev = setup_block();
if (dev >= 0) if (dev > 0)
goto mount_root; goto mount_root;
// Try NVIDIA naming scheme // Try NVIDIA naming scheme
strcpy(blk_info.partname, "APP"); strcpy(blk_info.partname, "APP");
dev = setup_block(); dev = setup_block();
if (dev >= 0) if (dev > 0)
goto mount_root; goto mount_root;
sprintf(blk_info.partname, "system%s", config->slot); sprintf(blk_info.partname, "system%s", config->slot);
dev = setup_block(); dev = setup_block();
if (dev >= 0) if (dev > 0)
goto mount_root; goto mount_root;
// Poll forever if rootwait was given in cmdline // Poll forever if rootwait was given in cmdline

View File

@ -183,18 +183,13 @@ static void extract_files(bool sbin) {
} }
void MagiskInit::parse_config_file() { void MagiskInit::parse_config_file() {
dev_t dev = 0; parse_prop_file("/data/.backup/.magisk", [this](auto key, auto value) -> bool {
parse_prop_file("/data/.backup/.magisk", [&dev](auto key, auto value) -> bool {
if (key == "PREINITDEVICE") { if (key == "PREINITDEVICE") {
unsigned int dev_major = 0; preinit_dev = value;
unsigned int dev_minor = 0;
sscanf(value.data(), "%u:%u", &dev_major, &dev_minor);
dev = makedev(dev_major, dev_minor);
return false; return false;
} }
return true; return true;
}); });
preinit_dev = dev;
} }
#define ROOTMIR MIRRDIR "/system_root" #define ROOTMIR MIRRDIR "/system_root"