diff --git a/native/src/core/bootstages.cpp b/native/src/core/bootstages.cpp index a611623e6..09fba4c55 100644 --- a/native/src/core/bootstages.cpp +++ b/native/src/core/bootstages.cpp @@ -79,6 +79,7 @@ static void mount_mirrors() { xmkdir(preinit_dir.data(), 0700); auto mirror_dir = MAGISKTMP + "/" PREINITMIRR; mount_mirror(preinit_dir, mirror_dir); + xmount(nullptr, mirror_dir.data(), nullptr, MS_UNBINDABLE, nullptr); break; } } @@ -109,23 +110,24 @@ static void mount_mirrors() { } } -dev_t find_preinit_device() { - const int UNKNOWN = 0; - const int PERSIST = 1; - const int METADATA = 2; - const int CACHE = 3; - const int DATA = 4; - int matched = UNKNOWN; - dev_t rules_dev = 0; +string find_preinit_device() { + enum { + UNKNOWN, + PERSIST, + METADATA, + CACHE, + DATA, + } matched = UNKNOWN; bool encrypted = getprop("ro.crypto.state") == "encrypted"; - string preinit_dir; - bool mount = getuid() == 0 && getenv("MAGISKTMP"); + string preinit_source; + string preinit_dir; + for (const auto &info: parse_mount_info("self")) { if (info.target.ends_with(PREINITMIRR)) - return info.device; - if (info.root != "/" || info.source.find("/dm-") != string::npos) + return basename(info.source.data()); + if (info.root != "/" || info.source[0] != '/' || info.source.find("/dm-") != string::npos) continue; if (info.type != "ext4" && info.type != "f2fs") continue; @@ -134,27 +136,46 @@ dev_t find_preinit_device() { return flag == "rw"sv; }); if (!rw) continue; - int new_matched; - if (info.target == "/cache" && matched < CACHE) { - new_matched = CACHE; - } else if (info.target == "/data" && matched < DATA) { - if (encrypted && access("/data/unencrypted", F_OK)) { + if (auto base = std::string_view(info.source).substr(0, info.source.find_last_of('/')); + !base.ends_with("/by-name") && !base.ends_with("/block")) { + continue; + } + + 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; - } 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) { preinit_dir = resolve_preinit_dir(info.target.data()); } - rules_dev = info.device; - matched = new_matched; + preinit_source = info.source; } if (!preinit_dir.empty()) { @@ -163,8 +184,7 @@ dev_t find_preinit_device() { mkdirs(mirror_dir.data(), 0700); xmount(preinit_dir.data(), mirror_dir.data(), nullptr, MS_BIND, nullptr); } - - return rules_dev; + return preinit_source.empty() ? "" : basename(preinit_source.data()); } static bool magisk_env() { diff --git a/native/src/core/core.hpp b/native/src/core/core.hpp index a21fcc738..b0a2d4016 100644 --- a/native/src/core/core.hpp +++ b/native/src/core/core.hpp @@ -6,7 +6,7 @@ extern bool RECOVERY_MODE; extern std::atomic pkg_xml_ino; -dev_t find_preinit_device(); +std::string find_preinit_device(); void unlock_blocks(); void reboot(); void start_log_daemon(); diff --git a/native/src/core/magisk.cpp b/native/src/core/magisk.cpp index 425679d94..fb9d09b25 100644 --- a/native/src/core/magisk.cpp +++ b/native/src/core/magisk.cpp @@ -1,5 +1,4 @@ #include -#include #include #include @@ -134,9 +133,14 @@ int magisk_main(int argc, char *argv[]) { } else if (argc >= 3 && argv[1] == "--install-module"sv) { install_module(argv[2]); } else if (argv[1] == "--preinit-device"sv) { - auto dev = find_preinit_device(); - if (dev) printf("%u:%u\n", major(dev), minor(dev)); - return dev ? 0 : 1; + set_log_level_state(LogLevel::Warn, false); + auto name = find_preinit_device(); + LOGD("preinit device: %s\n", name.data()); + if (!name.empty()) { + printf("%s\n", name.data()); + return 0; + } + return 1; } #if 0 /* Entry point for testing stuffs */ diff --git a/native/src/init/init.hpp b/native/src/init/init.hpp index 9688bded8..f4fe36ffd 100644 --- a/native/src/init/init.hpp +++ b/native/src/init/init.hpp @@ -57,7 +57,7 @@ public: class MagiskInit : public BaseInit { private: - dev_t preinit_dev = 0; + std::string preinit_dev; void parse_config_file(); void patch_sepolicy(const char *in, const char *out); diff --git a/native/src/init/mount.cpp b/native/src/init/mount.cpp index c9dd68ace..9dd4d7d5a 100644 --- a/native/src/init/mount.cpp +++ b/native/src/init/mount.cpp @@ -17,12 +17,14 @@ struct devinfo { char devname[32]; char partname[32]; char dmname[32]; + char devpath[PATH_MAX]; }; static vector dev_list; static void parse_device(devinfo *dev, const char *uevent) { dev->partname[0] = '\0'; + dev->devpath[0] = '\0'; parse_prop_file(uevent, [=](string_view key, string_view value) -> bool { if (key == "MAJOR") dev->major = parse_int(value.data()); @@ -38,7 +40,7 @@ static void parse_device(devinfo *dev, const char *uevent) { } static void collect_devices() { - char path[128]; + char path[PATH_MAX]; devinfo dev{}; if (auto dir = xopen_dir("/sys/dev/block"); dir) { for (dirent *entry; (entry = readdir(dir.get()));) { @@ -51,6 +53,8 @@ static void collect_devices() { auto name = rtrim(full_read(path)); 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); } } @@ -61,7 +65,7 @@ static struct { char block_dev[64]; } blk_info; -static int64_t setup_block() { +static dev_t setup_block() { if (dev_list.empty()) 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); else if (strcasecmp(dev.dmname, blk_info.partname) == 0) 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 continue; @@ -85,7 +93,7 @@ static int64_t setup_block() { } // The requested partname does not exist - return -1; + return 0; } static void switch_root(const string &path) { @@ -113,15 +121,20 @@ static void switch_root(const string &path) { #define PREINITMNT MIRRDIR "/preinit" -static void mount_preinit_dir(string path, dev_t preinit_dev) { - if (!preinit_dev) return; - xmknod(PREINITDEV, S_IFBLK | 0600, preinit_dev); +static void mount_preinit_dir(string path, string preinit_dev) { + if (preinit_dev.empty()) return; + 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); - bool mounted = false; // First, find if it is already mounted 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 xmount(info.target.data(), PREINITMNT, nullptr, MS_BIND, nullptr); mounted = true; @@ -147,7 +160,7 @@ static void mount_preinit_dir(string path, dev_t preinit_dev) { } xumount2(PREINITMNT, MNT_DETACH); } 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); } } @@ -164,18 +177,18 @@ bool LegacySARInit::mount_system_root() { // Try legacy SAR dm-verity strcpy(blk_info.partname, "vroot"); auto dev = setup_block(); - if (dev >= 0) + if (dev > 0) goto mount_root; // Try NVIDIA naming scheme strcpy(blk_info.partname, "APP"); dev = setup_block(); - if (dev >= 0) + if (dev > 0) goto mount_root; sprintf(blk_info.partname, "system%s", config->slot); dev = setup_block(); - if (dev >= 0) + if (dev > 0) goto mount_root; // Poll forever if rootwait was given in cmdline diff --git a/native/src/init/rootdir.cpp b/native/src/init/rootdir.cpp index 3d322b803..59f4bc6ab 100644 --- a/native/src/init/rootdir.cpp +++ b/native/src/init/rootdir.cpp @@ -183,18 +183,13 @@ static void extract_files(bool sbin) { } void MagiskInit::parse_config_file() { - dev_t dev = 0; - parse_prop_file("/data/.backup/.magisk", [&dev](auto key, auto value) -> bool { + parse_prop_file("/data/.backup/.magisk", [this](auto key, auto value) -> bool { if (key == "PREINITDEVICE") { - unsigned int dev_major = 0; - unsigned int dev_minor = 0; - sscanf(value.data(), "%u:%u", &dev_major, &dev_minor); - dev = makedev(dev_major, dev_minor); + preinit_dev = value; return false; } return true; }); - preinit_dev = dev; } #define ROOTMIR MIRRDIR "/system_root"