forked from topjohnwu/Magisk
-
Notifications
You must be signed in to change notification settings - Fork 1
/
twostage.cpp
85 lines (69 loc) · 2.3 KB
/
twostage.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include <sys/mount.h>
#include <magisk.hpp>
#include <base.hpp>
#include <socket.hpp>
#include "init.hpp"
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);
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");
}
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);
{
auto init = mmap_data("/init");
init.patch({ make_pair(INIT_PATH, REDIR_PATH) });
write(dest, init.buf, init.sz);
fclone_attr(src, dest);
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;
// Some weird devices like meizu, uses 2SI but still have legacy rootfs
// Check if root and system are on different filesystems
struct stat root{}, system{};
xstat("/", &root);
xstat("/system", &system);
if (root.st_dev != system.st_dev) {
// We are still on rootfs, so make sure we will execute the init of the 2nd stage
unlink("/init");
xsymlink(INIT_PATH, "/init");
return true;
}
return false;
}