mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-04-30 14:34:28 +02:00
Cleanup mount code in magiskinit
This commit is contained in:
parent
837c679a31
commit
c8e9ce7627
@ -148,6 +148,12 @@ void BootConfig::set(const kv_pairs &kv) {
|
|||||||
strscpy(fstab_suffix, value.data(), sizeof(fstab_suffix));
|
strscpy(fstab_suffix, value.data(), sizeof(fstab_suffix));
|
||||||
} else if (key == "qemu") {
|
} else if (key == "qemu") {
|
||||||
emulator = true;
|
emulator = true;
|
||||||
|
} else if (key == "androidboot.partition_map") {
|
||||||
|
// androidboot.partition_map allows mapping a partition name to a raw block device.
|
||||||
|
// For example, "androidboot.partition_map=vdb,metadata;vdc,userdata" maps
|
||||||
|
// "vdb" to "metadata", and "vdc" to "userdata".
|
||||||
|
// https://android.googlesource.com/platform/system/core/+/refs/heads/android13-release/init/devices.cpp#191
|
||||||
|
partition_map = parse_partition_map(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -165,41 +171,44 @@ void BootConfig::print() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define read_dt(name, key) \
|
#define read_dt(name, key) \
|
||||||
ssprintf(file_name, sizeof(file_name), "%s/" name, config->dt_dir); \
|
ssprintf(file_name, sizeof(file_name), "%s/" name, dt_dir); \
|
||||||
if (access(file_name, R_OK) == 0) { \
|
if (access(file_name, R_OK) == 0) { \
|
||||||
string data = full_read(file_name); \
|
string data = full_read(file_name); \
|
||||||
if (!data.empty()) { \
|
if (!data.empty()) { \
|
||||||
data.pop_back(); \
|
data.pop_back(); \
|
||||||
strscpy(config->key, data.data(), sizeof(config->key)); \
|
strscpy(key, data.data(), sizeof(key)); \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
void load_kernel_info(BootConfig *config) {
|
BootConfig::BootConfig() {
|
||||||
// Get kernel data using procfs and sysfs
|
// Get kernel data using procfs and sysfs
|
||||||
|
if (access("/proc/cmdline", F_OK) != 0) {
|
||||||
xmkdir("/proc", 0755);
|
xmkdir("/proc", 0755);
|
||||||
xmount("proc", "/proc", "proc", 0, nullptr);
|
xmount("proc", "/proc", "proc", 0, nullptr);
|
||||||
|
mount_list.emplace_back("/proc");
|
||||||
|
}
|
||||||
|
if (access("/sys/block", F_OK) != 0) {
|
||||||
xmkdir("/sys", 0755);
|
xmkdir("/sys", 0755);
|
||||||
xmount("sysfs", "/sys", "sysfs", 0, nullptr);
|
xmount("sysfs", "/sys", "sysfs", 0, nullptr);
|
||||||
|
|
||||||
mount_list.emplace_back("/proc");
|
|
||||||
mount_list.emplace_back("/sys");
|
mount_list.emplace_back("/sys");
|
||||||
|
}
|
||||||
|
|
||||||
// Log to kernel
|
// Log to kernel
|
||||||
rust::setup_klog();
|
rust::setup_klog();
|
||||||
|
|
||||||
config->set(parse_cmdline(full_read("/proc/cmdline")));
|
set(parse_cmdline(full_read("/proc/cmdline")));
|
||||||
config->set(parse_bootconfig(full_read("/proc/bootconfig")));
|
set(parse_bootconfig(full_read("/proc/bootconfig")));
|
||||||
|
|
||||||
parse_prop_file("/.backup/.magisk", [=](auto key, auto value) -> bool {
|
parse_prop_file("/.backup/.magisk", [&](auto key, auto value) -> bool {
|
||||||
if (key == "RECOVERYMODE" && value == "true") {
|
if (key == "RECOVERYMODE" && value == "true") {
|
||||||
config->skip_initramfs = config->emulator || !check_key_combo();
|
skip_initramfs = emulator || !check_key_combo();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (config->dt_dir[0] == '\0')
|
if (dt_dir[0] == '\0')
|
||||||
strscpy(config->dt_dir, DEFAULT_DT_DIR, sizeof(config->dt_dir));
|
strscpy(dt_dir, DEFAULT_DT_DIR, sizeof(dt_dir));
|
||||||
|
|
||||||
char file_name[128];
|
char file_name[128];
|
||||||
read_dt("fstab_suffix", fstab_suffix)
|
read_dt("fstab_suffix", fstab_suffix)
|
||||||
@ -207,26 +216,7 @@ void load_kernel_info(BootConfig *config) {
|
|||||||
read_dt("hardware.platform", hardware_plat)
|
read_dt("hardware.platform", hardware_plat)
|
||||||
|
|
||||||
LOGD("Device config:\n");
|
LOGD("Device config:\n");
|
||||||
config->print();
|
print();
|
||||||
}
|
|
||||||
|
|
||||||
// `androidboot.partition_map` allows associating a partition name for a raw block device
|
|
||||||
// through a comma separated and semicolon deliminated list. For example,
|
|
||||||
// `androidboot.partition_map=vdb,metadata;vdc,userdata` maps `vdb` to `metadata` and `vdc` to
|
|
||||||
// `userdata`.
|
|
||||||
// https://android.googlesource.com/platform/system/core/+/refs/heads/android13-release/init/devices.cpp#191
|
|
||||||
|
|
||||||
kv_pairs load_partition_map() {
|
|
||||||
const string_view kPartitionMapKey = "androidboot.partition_map";
|
|
||||||
for (const auto &[key, value] : parse_cmdline(full_read("/proc/cmdline"))) {
|
|
||||||
if (key == kPartitionMapKey)
|
|
||||||
return parse_partition_map(value);
|
|
||||||
}
|
|
||||||
for (const auto &[key, value] : parse_bootconfig(full_read("/proc/bootconfig"))) {
|
|
||||||
if (key == kPartitionMapKey)
|
|
||||||
return parse_partition_map(value);
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool check_two_stage() {
|
bool check_two_stage() {
|
||||||
|
@ -82,16 +82,11 @@ int main(int argc, char *argv[]) {
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
BaseInit *init;
|
BaseInit *init;
|
||||||
BootConfig config{};
|
BootConfig config;
|
||||||
|
|
||||||
if (argc > 1 && argv[1] == "selinux_setup"sv) {
|
if (argc > 1 && argv[1] == "selinux_setup"sv)
|
||||||
rust::setup_klog();
|
init = new SecondStageInit(argv, &config);
|
||||||
init = new SecondStageInit(argv);
|
else if (config.skip_initramfs)
|
||||||
} else {
|
|
||||||
// This will also mount /sys and /proc
|
|
||||||
load_kernel_info(&config);
|
|
||||||
|
|
||||||
if (config.skip_initramfs)
|
|
||||||
init = new LegacySARInit(argv, &config);
|
init = new LegacySARInit(argv, &config);
|
||||||
else if (config.force_normal_boot)
|
else if (config.force_normal_boot)
|
||||||
init = new FirstStageInit(argv, &config);
|
init = new FirstStageInit(argv, &config);
|
||||||
@ -101,7 +96,6 @@ int main(int argc, char *argv[]) {
|
|||||||
init = new FirstStageInit(argv, &config);
|
init = new FirstStageInit(argv, &config);
|
||||||
else
|
else
|
||||||
init = new RootFSInit(argv, &config);
|
init = new RootFSInit(argv, &config);
|
||||||
}
|
|
||||||
|
|
||||||
// Run the main routine
|
// Run the main routine
|
||||||
init->start();
|
init->start();
|
||||||
|
@ -6,16 +6,19 @@
|
|||||||
using kv_pairs = std::vector<std::pair<std::string, std::string>>;
|
using kv_pairs = std::vector<std::pair<std::string, std::string>>;
|
||||||
|
|
||||||
struct BootConfig {
|
struct BootConfig {
|
||||||
bool skip_initramfs;
|
bool skip_initramfs = false;
|
||||||
bool force_normal_boot;
|
bool force_normal_boot = false;
|
||||||
bool rootwait;
|
bool rootwait = false;
|
||||||
bool emulator;
|
bool emulator = false;
|
||||||
char slot[3];
|
char slot[3]{};
|
||||||
char dt_dir[64];
|
char dt_dir[64]{};
|
||||||
char fstab_suffix[32];
|
char fstab_suffix[32]{};
|
||||||
char hardware[32];
|
char hardware[32]{};
|
||||||
char hardware_plat[32];
|
char hardware_plat[32]{};
|
||||||
|
kv_pairs partition_map;
|
||||||
|
|
||||||
|
BootConfig();
|
||||||
|
private:
|
||||||
void set(const kv_pairs &);
|
void set(const kv_pairs &);
|
||||||
void print();
|
void print();
|
||||||
};
|
};
|
||||||
@ -28,8 +31,6 @@ extern std::vector<std::string> mount_list;
|
|||||||
|
|
||||||
int magisk_proxy_main(int argc, char *argv[]);
|
int magisk_proxy_main(int argc, char *argv[]);
|
||||||
bool unxz(out_stream &strm, rust::Slice<const uint8_t> bytes);
|
bool unxz(out_stream &strm, rust::Slice<const uint8_t> bytes);
|
||||||
void load_kernel_info(BootConfig *config);
|
|
||||||
kv_pairs load_partition_map();
|
|
||||||
bool check_two_stage();
|
bool check_two_stage();
|
||||||
const char *backup_init();
|
const char *backup_init();
|
||||||
void restore_ramdisk_init();
|
void restore_ramdisk_init();
|
||||||
@ -40,13 +41,15 @@ void restore_ramdisk_init();
|
|||||||
|
|
||||||
class BaseInit {
|
class BaseInit {
|
||||||
protected:
|
protected:
|
||||||
BootConfig *config = nullptr;
|
BootConfig *config;
|
||||||
char **argv = nullptr;
|
char **argv;
|
||||||
|
|
||||||
[[noreturn]] void exec_init();
|
[[noreturn]] void exec_init();
|
||||||
void prepare_data();
|
void prepare_data();
|
||||||
|
dev_t find_block(const char *partname);
|
||||||
|
void collect_devices();
|
||||||
public:
|
public:
|
||||||
BaseInit(char *argv[], BootConfig *config = nullptr) : config(config), argv(argv) {}
|
BaseInit(char *argv[], BootConfig *config) : config(config), argv(argv) {}
|
||||||
virtual ~BaseInit() = default;
|
virtual ~BaseInit() = default;
|
||||||
virtual void start() = 0;
|
virtual void start() = 0;
|
||||||
};
|
};
|
||||||
@ -59,6 +62,7 @@ private:
|
|||||||
void patch_sepolicy(const char *in, const char *out);
|
void patch_sepolicy(const char *in, const char *out);
|
||||||
bool hijack_sepolicy();
|
bool hijack_sepolicy();
|
||||||
void setup_tmp(const char *path);
|
void setup_tmp(const char *path);
|
||||||
|
void mount_preinit_dir();
|
||||||
protected:
|
protected:
|
||||||
void patch_rw_root();
|
void patch_rw_root();
|
||||||
void patch_ro_root();
|
void patch_ro_root();
|
||||||
@ -87,7 +91,7 @@ class SecondStageInit : public MagiskInit {
|
|||||||
private:
|
private:
|
||||||
bool prepare();
|
bool prepare();
|
||||||
public:
|
public:
|
||||||
SecondStageInit(char *argv[]) : MagiskInit(argv) {
|
SecondStageInit(char *argv[], BootConfig *config) : MagiskInit(argv, config) {
|
||||||
LOGD("%s\n", __FUNCTION__);
|
LOGD("%s\n", __FUNCTION__);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ static void parse_device(devinfo *dev, const char *uevent) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static void collect_devices(const auto &partition_map) {
|
void BaseInit::collect_devices() {
|
||||||
char path[PATH_MAX];
|
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) {
|
||||||
@ -59,9 +59,9 @@ static void collect_devices(const auto &partition_map) {
|
|||||||
auto name = rtrim(full_read(path));
|
auto name = rtrim(full_read(path));
|
||||||
strscpy(dev.dmname, name.data(), sizeof(dev.dmname));
|
strscpy(dev.dmname, name.data(), sizeof(dev.dmname));
|
||||||
}
|
}
|
||||||
if (auto it = std::ranges::find_if(partition_map, [&](const auto &i) {
|
if (auto it = std::ranges::find_if(config->partition_map, [&](const auto &i) {
|
||||||
return i.first == dev.devname;
|
return i.first == dev.devname;
|
||||||
}); dev.partname[0] == '\0' && it != partition_map.end()) {
|
}); dev.partname[0] == '\0' && it != config->partition_map.end()) {
|
||||||
// use androidboot.partition_map as partname fallback.
|
// use androidboot.partition_map as partname fallback.
|
||||||
strscpy(dev.partname, it->second.data(), sizeof(dev.partname));
|
strscpy(dev.partname, it->second.data(), sizeof(dev.partname));
|
||||||
}
|
}
|
||||||
@ -72,52 +72,45 @@ static void collect_devices(const auto &partition_map) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct {
|
dev_t BaseInit::find_block(const char *partname) {
|
||||||
char partname[32];
|
|
||||||
char block_dev[64];
|
|
||||||
} blk_info;
|
|
||||||
|
|
||||||
static dev_t setup_block() {
|
|
||||||
static const auto partition_map = load_partition_map();
|
|
||||||
if (dev_list.empty())
|
if (dev_list.empty())
|
||||||
collect_devices(partition_map);
|
collect_devices();
|
||||||
|
|
||||||
for (int tries = 0; tries < 3; ++tries) {
|
for (int tries = 0; tries < 3; ++tries) {
|
||||||
for (auto &dev : dev_list) {
|
for (auto &dev : dev_list) {
|
||||||
if (strcasecmp(dev.partname, blk_info.partname) == 0)
|
const char *name;
|
||||||
LOGD("Setup %s: [%s] (%d, %d)\n", dev.partname, dev.devname, dev.major, dev.minor);
|
if (strcasecmp(dev.partname, partname) == 0)
|
||||||
else if (strcasecmp(dev.dmname, blk_info.partname) == 0)
|
name = dev.partname;
|
||||||
LOGD("Setup %s: [%s] (%d, %d)\n", dev.dmname, dev.devname, dev.major, dev.minor);
|
else if (strcasecmp(dev.dmname, partname) == 0)
|
||||||
else if (strcasecmp(dev.devname, blk_info.partname) == 0)
|
name = dev.dmname;
|
||||||
LOGD("Setup %s: [%s] (%d, %d)\n", dev.devname, dev.devname, dev.major, dev.minor);
|
else if (strcasecmp(dev.devname, partname) == 0)
|
||||||
else if (std::string_view(dev.devpath).ends_with("/"s + blk_info.partname))
|
name = dev.devname;
|
||||||
LOGD("Setup %s: [%s] (%d, %d)\n", dev.devpath, dev.devname, dev.major, dev.minor);
|
else if (std::string_view(dev.devpath).ends_with("/"s + partname))
|
||||||
|
name = dev.devpath;
|
||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
dev_t rdev = makedev(dev.major, dev.minor);
|
LOGD("Found %s: [%s] (%d, %d)\n", name, dev.devname, dev.major, dev.minor);
|
||||||
xmknod(blk_info.block_dev, S_IFBLK | 0600, rdev);
|
return makedev(dev.major, dev.minor);
|
||||||
return rdev;
|
|
||||||
}
|
}
|
||||||
// Wait 10ms and try again
|
// Wait 10ms and try again
|
||||||
usleep(10000);
|
usleep(10000);
|
||||||
dev_list.clear();
|
dev_list.clear();
|
||||||
collect_devices(partition_map);
|
collect_devices();
|
||||||
}
|
}
|
||||||
|
|
||||||
// The requested partname does not exist
|
// The requested partname does not exist
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mount_preinit_dir(string preinit_dev) {
|
void MagiskInit::mount_preinit_dir() {
|
||||||
if (preinit_dev.empty()) return;
|
if (preinit_dev.empty()) return;
|
||||||
strcpy(blk_info.partname, preinit_dev.data());
|
auto dev = find_block(preinit_dev.data());
|
||||||
strcpy(blk_info.block_dev, PREINITDEV);
|
|
||||||
auto dev = setup_block();
|
|
||||||
if (dev == 0) {
|
if (dev == 0) {
|
||||||
LOGE("Cannot find preinit %s, abort!\n", preinit_dev.data());
|
LOGE("Cannot find preinit %s, abort!\n", preinit_dev.data());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
xmknod(PREINITDEV, S_IFBLK | 0600, dev);
|
||||||
xmkdir(MIRRDIR, 0);
|
xmkdir(MIRRDIR, 0);
|
||||||
bool mounted = false;
|
bool mounted = false;
|
||||||
// First, find if it is already mounted
|
// First, find if it is already mounted
|
||||||
@ -156,23 +149,22 @@ bool LegacySARInit::mount_system_root() {
|
|||||||
// there's no /dev in stub cpio
|
// there's no /dev in stub cpio
|
||||||
xmkdir("/dev", 0777);
|
xmkdir("/dev", 0777);
|
||||||
|
|
||||||
strcpy(blk_info.block_dev, "/dev/root");
|
dev_t dev;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
// Try legacy SAR dm-verity
|
// Try legacy SAR dm-verity
|
||||||
strcpy(blk_info.partname, "vroot");
|
dev = find_block("vroot");
|
||||||
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");
|
dev = find_block("APP");
|
||||||
dev = setup_block();
|
|
||||||
if (dev > 0)
|
if (dev > 0)
|
||||||
goto mount_root;
|
goto mount_root;
|
||||||
|
|
||||||
sprintf(blk_info.partname, "system%s", config->slot);
|
// Try normal partname
|
||||||
dev = setup_block();
|
char sys_part[32];
|
||||||
|
sprintf(sys_part, "system%s", config->slot);
|
||||||
|
dev = find_block(sys_part);
|
||||||
if (dev > 0)
|
if (dev > 0)
|
||||||
goto mount_root;
|
goto mount_root;
|
||||||
|
|
||||||
@ -184,6 +176,7 @@ bool LegacySARInit::mount_system_root() {
|
|||||||
exit(1);
|
exit(1);
|
||||||
|
|
||||||
mount_root:
|
mount_root:
|
||||||
|
xmknod("/dev/root", S_IFBLK | 0600, dev);
|
||||||
xmkdir("/system_root", 0755);
|
xmkdir("/system_root", 0755);
|
||||||
|
|
||||||
if (xmount("/dev/root", "/system_root", "ext4", MS_RDONLY, nullptr)) {
|
if (xmount("/dev/root", "/system_root", "ext4", MS_RDONLY, nullptr)) {
|
||||||
@ -208,11 +201,10 @@ mount_root:
|
|||||||
if (!is_two_stage && config->emulator) {
|
if (!is_two_stage && config->emulator) {
|
||||||
avd_hack = true;
|
avd_hack = true;
|
||||||
// These values are hardcoded for API 28 AVD
|
// These values are hardcoded for API 28 AVD
|
||||||
|
auto vendor_dev = find_block("vendor");
|
||||||
xmkdir("/dev/block", 0755);
|
xmkdir("/dev/block", 0755);
|
||||||
strcpy(blk_info.block_dev, "/dev/block/vde1");
|
xmknod("/dev/block/vde1", S_IFBLK | 0600, vendor_dev);
|
||||||
strcpy(blk_info.partname, "vendor");
|
xmount("/dev/block/vde1", "/vendor", "ext4", MS_RDONLY, nullptr);
|
||||||
setup_block();
|
|
||||||
xmount(blk_info.block_dev, "/vendor", "ext4", MS_RDONLY, nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return is_two_stage;
|
return is_two_stage;
|
||||||
@ -246,7 +238,7 @@ void MagiskInit::setup_tmp(const char *path) {
|
|||||||
xmkdir(DEVICEDIR, 0711);
|
xmkdir(DEVICEDIR, 0711);
|
||||||
xmkdir(WORKERDIR, 0);
|
xmkdir(WORKERDIR, 0);
|
||||||
|
|
||||||
mount_preinit_dir(preinit_dev);
|
mount_preinit_dir();
|
||||||
|
|
||||||
cp_afc(".backup/.magisk", MAIN_CONFIG);
|
cp_afc(".backup/.magisk", MAIN_CONFIG);
|
||||||
rm_rf(".backup");
|
rm_rf(".backup");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user