Eliminate unnecessarily copy on magiskinit

This patch reuses the abused /data tmpfs for magisktmp
This commit is contained in:
LoveSy 2022-12-14 21:14:12 +08:00 committed by John Wu
parent 0d38c94c9c
commit 4ed34cd648
4 changed files with 30 additions and 76 deletions

View File

@ -25,6 +25,7 @@ struct BootConfig {
#define DEFAULT_DT_DIR "/proc/device-tree/firmware/android"
#define INIT_PATH "/system/bin/init"
#define REDIR_PATH "/data/magiskinit"
extern std::vector<std::string> mount_list;
@ -48,6 +49,7 @@ protected:
char **argv = nullptr;
[[noreturn]] void exec_init();
void prepare_data();
public:
BaseInit(char *argv[], BootConfig *config = nullptr) : config(config), argv(argv) {}
virtual ~BaseInit() = default;
@ -58,8 +60,6 @@ class MagiskInit : public BaseInit {
private:
void mount_rules_dir();
protected:
mmap_data self;
mmap_data magisk_cfg;
std::string custom_rules_dir;
#if ENABLE_AVD_HACK
@ -72,16 +72,12 @@ protected:
bool hijack_sepolicy();
void setup_tmp(const char *path);
void patch_rw_root();
void patch_ro_root();
public:
using BaseInit::BaseInit;
};
class SARBase : public MagiskInit {
protected:
std::vector<raw_file> overlays;
void backup_files();
void patch_ro_root();
public:
using MagiskInit::MagiskInit;
};
@ -134,6 +130,7 @@ public:
LOGD("%s\n", __FUNCTION__);
};
void start() override {
prepare_data();
if (mount_system_root())
first_stage_prep();
else

View File

@ -214,8 +214,6 @@ success:
}
bool LegacySARInit::mount_system_root() {
backup_files();
LOGD("Mounting system_root\n");
// there's no /dev in stub cpio
@ -296,11 +294,19 @@ void BaseInit::exec_init() {
exit(1);
}
void BaseInit::prepare_data() {
LOGD("Setup data tmp\n");
xmkdir("/data", 0755);
xmount("tmpfs", "/data", "tmpfs", 0, "mode=755");
cp_afc("/init", "/data/magiskinit");
cp_afc("/.backup", "/data/.backup");
cp_afc("/overlay.d", "/data/overlay.d");
}
void MagiskInit::setup_tmp(const char *path) {
LOGD("Setup Magisk tmp at %s\n", path);
xmount("tmpfs", path, "tmpfs", 0, "mode=755");
chdir(path);
chdir("/data");
xmkdir(INTLROOT, 0755);
xmkdir(MIRRDIR, 0);
@ -308,14 +314,15 @@ void MagiskInit::setup_tmp(const char *path) {
mount_rules_dir();
int fd = xopen(INTLROOT "/config", O_WRONLY | O_CREAT, 0);
xwrite(fd, magisk_cfg.buf, magisk_cfg.sz);
close(fd);
cp_afc(".backup/.magisk", INTLROOT "/config");
rm_rf(".backup");
// Create applet symlinks
for (int i = 0; applet_names[i]; ++i)
xsymlink("./magisk", applet_names[i]);
xsymlink("./magiskpolicy", "supolicy");
xmount(".", path, nullptr, MS_BIND, nullptr);
chdir("/");
}

View File

@ -130,19 +130,6 @@ static void magic_mount(const string &sdir, const string &ddir = "") {
}
}
void SARBase::backup_files() {
if (access("/overlay.d", F_OK) == 0)
backup_folder("/overlay.d", overlays);
else if (access("/data/overlay.d", F_OK) == 0)
backup_folder("/data/overlay.d", overlays);
self = mmap_data("/proc/self/exe");
if (access("/.backup/.magisk", R_OK) == 0)
magisk_cfg = mmap_data("/.backup/.magisk");
else if (access("/data/.backup/.magisk", R_OK) == 0)
magisk_cfg = mmap_data("/data/.backup/.magisk");
}
static void patch_socket_name(const char *path) {
static char rstr[16] = { 0 };
if (rstr[0] == '\0')
@ -181,7 +168,9 @@ static void extract_files(bool sbin) {
#define ROOTMIR MIRRDIR "/system_root"
#define NEW_INITRC "/system/etc/init/hw/init.rc"
void SARBase::patch_ro_root() {
void MagiskInit::patch_ro_root() {
mount_list.emplace_back("/data");
string tmp_dir;
if (access("/sbin", F_OK) == 0) {
@ -205,7 +194,7 @@ void SARBase::patch_ro_root() {
if (tmp_dir == "/sbin")
recreate_sbin(ROOTMIR "/sbin", true);
xmkdir(ROOTOVL, 0);
xrename("overlay.d", ROOTOVL);
#if ENABLE_AVD_HACK
// Handle avd hack
@ -222,9 +211,6 @@ void SARBase::patch_ro_root() {
}
#endif
// Handle overlay.d
restore_folder(ROOTOVL, overlays);
overlays.clear();
load_overlay_rc(ROOTOVL);
if (access(ROOTOVL "/sbin", F_OK) == 0) {
// Move files in overlay.d/sbin into tmp_dir
@ -260,9 +246,7 @@ void SARBase::patch_ro_root() {
}
void RootFSInit::prepare() {
self = mmap_data("/init");
magisk_cfg = mmap_data("/.backup/.magisk");
prepare_data();
LOGD("Restoring /init\n");
rename(backup_init(), "/init");
}
@ -270,6 +254,7 @@ void RootFSInit::prepare() {
#define PRE_TMPDIR "/magisk-tmp"
void MagiskInit::patch_rw_root() {
mount_list.emplace_back("/data");
// Create hardlink mirror of /sbin to /root
mkdir("/root", 0777);
clone_attr("/sbin", "/root");
@ -307,9 +292,7 @@ void MagiskInit::patch_rw_root() {
chdir("/");
// Dump magiskinit as magisk
int fd = xopen("/sbin/magisk", O_WRONLY | O_CREAT, 0755);
write(fd, self.buf, self.sz);
close(fd);
cp_afc(REDIR_PATH, "/sbin/magisk");
}
int magisk_proxy_main(int argc, char *argv[]) {

View File

@ -8,30 +8,15 @@
using namespace std;
#define REDIR_PATH "/data/magiskinit"
void FirstStageInit::prepare() {
xmkdirs("/data", 0755);
xmount("tmpfs", "/data", "tmpfs", 0, "mode=755");
cp_afc("/init" /* magiskinit */, REDIR_PATH);
prepare_data();
restore_ramdisk_init();
{
auto init = mmap_data("/init", true);
// Redirect original init to magiskinit
init.patch({ make_pair(INIT_PATH, REDIR_PATH) });
}
// Copy files to tmpfs
cp_afc(".backup", "/data/.backup");
cp_afc("overlay.d", "/data/overlay.d");
auto init = mmap_data("/init", true);
// Redirect original init to magiskinit
init.patch({ make_pair(INIT_PATH, REDIR_PATH) });
}
void LegacySARInit::first_stage_prep() {
xmkdir("/data", 0755);
xmount("tmpfs", "/data", "tmpfs", 0, "mode=755");
// Patch init binary
int src = xopen("/init", O_RDONLY);
int dest = xopen("/data/init", O_CREAT | O_WRONLY, 0);
@ -43,29 +28,11 @@ void LegacySARInit::first_stage_prep() {
close(dest);
}
xmount("/data/init", "/init", nullptr, MS_BIND, nullptr);
// Replace redirect init with magiskinit
dest = xopen(REDIR_PATH, O_CREAT | O_WRONLY, 0);
write(dest, self.buf, self.sz);
fclone_attr(src, dest);
close(src);
close(dest);
// Copy files to tmpfs
xmkdir("/data/.backup", 0);
xmkdir("/data/overlay.d", 0);
restore_folder("/data/overlay.d", overlays);
int cfg = xopen("/data/.backup/.magisk", O_WRONLY | O_CREAT, 0);
xwrite(cfg, magisk_cfg.buf, magisk_cfg.sz);
close(cfg);
}
bool SecondStageInit::prepare() {
backup_files();
umount2("/init", MNT_DETACH);
umount2("/proc/self/exe", MNT_DETACH);
umount2("/data", MNT_DETACH);
// Make sure init dmesg logs won't get messed up
argv[0] = (char *) INIT_PATH;