2019-05-27 07:29:43 +00:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <fcntl.h>
|
2019-07-16 08:08:28 +00:00
|
|
|
#include <vector>
|
2019-05-27 07:29:43 +00:00
|
|
|
|
2020-03-09 08:50:30 +00:00
|
|
|
#include <magisk.hpp>
|
|
|
|
#include <magiskpolicy.hpp>
|
|
|
|
#include <utils.hpp>
|
2020-04-12 12:34:56 +00:00
|
|
|
#include <socket.hpp>
|
2019-05-27 07:29:43 +00:00
|
|
|
|
2020-03-09 08:50:30 +00:00
|
|
|
#include "init.hpp"
|
|
|
|
#include "magiskrc.inc"
|
2019-05-27 07:29:43 +00:00
|
|
|
|
|
|
|
#ifdef USE_64BIT
|
|
|
|
#define LIBNAME "lib64"
|
|
|
|
#else
|
|
|
|
#define LIBNAME "lib"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
2019-07-16 08:08:28 +00:00
|
|
|
static vector<raw_data> rc_list;
|
|
|
|
|
2019-06-26 06:31:59 +00:00
|
|
|
static void patch_init_rc(FILE *rc) {
|
Logical Resizable Android Partitions support
The way how logical partition, or "Logical Resizable Android Partitions"
as they say in AOSP source code, is setup makes it impossible to early
mount the partitions from the shared super partition with just
a few lines of code; in fact, AOSP has a whole "fs_mgr" folder which
consist of multiple complex libraries, with 15K lines of code just
to deal with the device mapper shenanigans.
In order to keep the already overly complicated MagiskInit more
managable, I chose NOT to go the route of including fs_mgr directly
into MagiskInit. Luckily, starting from Android Q, Google decided to
split init startup into 3 stages, with the first stage doing _only_
early mount. This is great news, because we can simply let the stock
init do its own thing for us, and we intercept the bootup sequence.
So the workflow can be visualized roughly below:
Magisk First Stage --> First Stage Mount --> Magisk Second Stage --+
(MagiskInit) (Original Init) (MagiskInit) +
+
+
...Rest of the boot... <-- Second Stage <-- Selinux Setup <--+
(__________________ Original Init ____________________)
The catch here is that after doing all the first stage mounting, /init
will pivot /system as root directory (/), leaving us impossible to
regain control after we hand it over. So the solution here is to patch
fstab in /first_stage_ramdisk on-the-fly to redirect /system to
/system_root, making the original init do all the hard work for
us and mount required early mount partitions, but skips the step of
switching root directory. It will also conveniently hand over execution
back to MagiskInit, which we will reuse the routine for patching
root directory in normal system-as-root situations.
2019-06-29 07:47:29 +00:00
|
|
|
file_readline("/init.rc", [=](string_view line) -> bool {
|
2019-06-26 06:31:59 +00:00
|
|
|
// Do not start vaultkeeper
|
|
|
|
if (str_contains(line, "start vaultkeeper")) {
|
|
|
|
LOGD("Remove vaultkeeper\n");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
// Do not run flash_recovery
|
|
|
|
if (str_starts(line, "service flash_recovery")) {
|
|
|
|
LOGD("Remove flash_recovery\n");
|
|
|
|
fprintf(rc, "service flash_recovery /system/bin/xxxxx\n");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
// Else just write the line
|
|
|
|
fprintf(rc, "%s", line.data());
|
|
|
|
return true;
|
|
|
|
});
|
2019-07-16 08:08:28 +00:00
|
|
|
|
|
|
|
fprintf(rc, "\n");
|
|
|
|
|
|
|
|
// Inject custom rc scripts
|
|
|
|
for (auto &d : rc_list)
|
|
|
|
fprintf(rc, "\n%s\n", d.buf);
|
|
|
|
rc_list.clear();
|
|
|
|
|
|
|
|
// Inject Magisk rc scripts
|
2019-07-15 04:56:21 +00:00
|
|
|
char pfd_svc[16], ls_svc[16], bc_svc[16];
|
2019-07-15 00:41:51 +00:00
|
|
|
gen_rand_str(pfd_svc, sizeof(pfd_svc));
|
|
|
|
gen_rand_str(ls_svc, sizeof(ls_svc));
|
|
|
|
gen_rand_str(bc_svc, sizeof(bc_svc));
|
2019-06-26 06:31:59 +00:00
|
|
|
LOGD("Inject magisk services: [%s] [%s] [%s]\n", pfd_svc, ls_svc, bc_svc);
|
|
|
|
fprintf(rc, magiskrc, pfd_svc, pfd_svc, ls_svc, bc_svc, bc_svc);
|
|
|
|
}
|
2019-05-27 07:29:43 +00:00
|
|
|
|
2020-04-01 11:39:28 +00:00
|
|
|
static void load_overlay_rc(const char *overlay) {
|
|
|
|
auto dir = open_dir(overlay);
|
|
|
|
if (!dir) return;
|
|
|
|
|
|
|
|
int dfd = dirfd(dir.get());
|
2019-07-16 08:08:28 +00:00
|
|
|
// Do not allow overwrite init.rc
|
2020-04-01 11:39:28 +00:00
|
|
|
unlinkat(dfd, "init.rc", 0);
|
|
|
|
for (dirent *entry; (entry = readdir(dir.get()));) {
|
2019-07-16 08:08:28 +00:00
|
|
|
if (strend(entry->d_name, ".rc") == 0) {
|
|
|
|
LOGD("Found rc script [%s]\n", entry->d_name);
|
2020-04-01 11:39:28 +00:00
|
|
|
int rc = xopenat(dfd, entry->d_name, O_RDONLY | O_CLOEXEC);
|
2019-07-16 08:08:28 +00:00
|
|
|
raw_data data;
|
|
|
|
fd_full_read(rc, data.buf, data.sz);
|
|
|
|
close(rc);
|
|
|
|
rc_list.push_back(std::move(data));
|
2020-04-01 11:39:28 +00:00
|
|
|
unlinkat(dfd, entry->d_name, 0);
|
2019-07-16 08:08:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-12 08:25:48 +00:00
|
|
|
void RootFSInit::setup_rootfs() {
|
2019-06-24 08:31:42 +00:00
|
|
|
if (patch_sepolicy()) {
|
2019-05-27 07:29:43 +00:00
|
|
|
char *addr;
|
|
|
|
size_t size;
|
|
|
|
mmap_rw("/init", addr, size);
|
|
|
|
for (char *p = addr; p < addr + size; ++p) {
|
|
|
|
if (memcmp(p, SPLIT_PLAT_CIL, sizeof(SPLIT_PLAT_CIL)) == 0) {
|
|
|
|
// Force init to load /sepolicy
|
|
|
|
LOGD("Remove from init: " SPLIT_PLAT_CIL "\n");
|
|
|
|
memset(p, 'x', sizeof(SPLIT_PLAT_CIL) - 1);
|
2019-06-25 09:38:34 +00:00
|
|
|
break;
|
2019-05-27 07:29:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
munmap(addr, size);
|
|
|
|
}
|
|
|
|
|
2019-07-16 08:08:28 +00:00
|
|
|
// Handle overlays
|
2020-04-01 11:39:28 +00:00
|
|
|
if (access("/overlay.d", F_OK) == 0) {
|
2019-07-16 08:08:28 +00:00
|
|
|
LOGD("Merge overlay.d\n");
|
2020-04-01 11:39:28 +00:00
|
|
|
load_overlay_rc("/overlay.d");
|
2020-04-02 09:17:45 +00:00
|
|
|
mv_path("/overlay.d", "/");
|
2019-07-16 08:08:28 +00:00
|
|
|
}
|
|
|
|
|
2019-05-27 07:29:43 +00:00
|
|
|
// Patch init.rc
|
|
|
|
FILE *rc = xfopen("/init.p.rc", "we");
|
2019-06-26 06:31:59 +00:00
|
|
|
patch_init_rc(rc);
|
2019-05-27 07:29:43 +00:00
|
|
|
fclose(rc);
|
|
|
|
clone_attr("/init.rc", "/init.p.rc");
|
|
|
|
rename("/init.p.rc", "/init.rc");
|
|
|
|
|
|
|
|
// Create hardlink mirror of /sbin to /root
|
|
|
|
mkdir("/root", 0750);
|
|
|
|
clone_attr("/sbin", "/root");
|
2020-04-02 09:17:45 +00:00
|
|
|
link_path("/sbin", "/root");
|
2019-05-27 07:29:43 +00:00
|
|
|
|
2019-06-22 10:14:33 +00:00
|
|
|
// Dump magiskinit as magisk
|
2020-04-01 11:39:28 +00:00
|
|
|
int fd = xopen("/sbin/magisk", O_WRONLY | O_CREAT, 0755);
|
2019-05-27 07:29:43 +00:00
|
|
|
write(fd, self.buf, self.sz);
|
|
|
|
close(fd);
|
|
|
|
}
|
|
|
|
|
2019-06-26 04:34:02 +00:00
|
|
|
bool MagiskInit::patch_sepolicy(const char *file) {
|
2019-10-20 11:13:03 +00:00
|
|
|
bool patch_init = false;
|
2019-05-27 07:29:43 +00:00
|
|
|
|
|
|
|
if (access(SPLIT_PLAT_CIL, R_OK) == 0) {
|
|
|
|
LOGD("sepol: split policy\n");
|
2019-10-20 11:13:03 +00:00
|
|
|
patch_init = true;
|
2019-05-27 07:29:43 +00:00
|
|
|
} else if (access("/sepolicy", R_OK) == 0) {
|
|
|
|
LOGD("sepol: monolithic policy\n");
|
|
|
|
load_policydb("/sepolicy");
|
|
|
|
} else {
|
|
|
|
LOGD("sepol: no selinux\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-10-20 11:13:03 +00:00
|
|
|
// Mount selinuxfs to communicate with kernel
|
|
|
|
xmount("selinuxfs", SELINUX_MNT, "selinuxfs", 0, nullptr);
|
2019-11-19 05:16:20 +00:00
|
|
|
mount_list.emplace_back(SELINUX_MNT);
|
2019-10-20 11:13:03 +00:00
|
|
|
|
|
|
|
if (patch_init)
|
|
|
|
load_split_cil();
|
|
|
|
|
2019-05-27 07:29:43 +00:00
|
|
|
sepol_magisk_rules();
|
|
|
|
sepol_allow(SEPOL_PROC_DOMAIN, ALL, ALL, ALL);
|
2019-12-13 11:05:12 +00:00
|
|
|
|
|
|
|
// Custom rules
|
2020-04-12 12:34:56 +00:00
|
|
|
if (auto dir = xopen_dir(persist_dir.data()); dir) {
|
2019-12-13 11:05:12 +00:00
|
|
|
for (dirent *entry; (entry = xreaddir(dir.get()));) {
|
2020-04-12 12:34:56 +00:00
|
|
|
auto rule = persist_dir + "/" + entry->d_name + "/sepolicy.rule";
|
|
|
|
if (access(rule.data(), R_OK) == 0) {
|
|
|
|
LOGD("Loading custom sepolicy patch: %s\n", rule.data());
|
|
|
|
load_rule_file(rule.data());
|
2019-12-13 11:05:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-26 04:34:02 +00:00
|
|
|
dump_policydb(file);
|
2019-12-13 11:05:12 +00:00
|
|
|
destroy_policydb();
|
2019-05-27 07:29:43 +00:00
|
|
|
|
|
|
|
// Remove OnePlus stupid debug sepolicy and use our own
|
|
|
|
if (access("/sepolicy_debug", F_OK) == 0) {
|
|
|
|
unlink("/sepolicy_debug");
|
|
|
|
link("/sepolicy", "/sepolicy_debug");
|
|
|
|
}
|
|
|
|
|
2019-10-20 11:13:03 +00:00
|
|
|
return patch_init;
|
2019-05-27 07:29:43 +00:00
|
|
|
}
|
2019-06-22 10:14:33 +00:00
|
|
|
|
2020-01-09 15:42:27 +00:00
|
|
|
static void recreate_sbin(const char *mirror, bool use_bind_mount) {
|
|
|
|
auto dp = xopen_dir(mirror);
|
|
|
|
int src = dirfd(dp.get());
|
|
|
|
char buf[4096];
|
|
|
|
for (dirent *entry; (entry = xreaddir(dp.get()));) {
|
|
|
|
string sbin_path = "/sbin/"s + entry->d_name;
|
2019-12-06 20:31:49 +00:00
|
|
|
struct stat st;
|
|
|
|
fstatat(src, entry->d_name, &st, AT_SYMLINK_NOFOLLOW);
|
|
|
|
if (S_ISLNK(st.st_mode)) {
|
|
|
|
xreadlinkat(src, entry->d_name, buf, sizeof(buf));
|
2020-01-09 15:42:27 +00:00
|
|
|
xsymlink(buf, sbin_path.data());
|
2019-12-06 20:31:49 +00:00
|
|
|
} else {
|
|
|
|
sprintf(buf, "%s/%s", mirror, entry->d_name);
|
|
|
|
if (use_bind_mount) {
|
2020-01-09 15:42:27 +00:00
|
|
|
auto mode = st.st_mode & 0777;
|
2019-12-06 20:31:49 +00:00
|
|
|
// Create dummy
|
|
|
|
if (S_ISDIR(st.st_mode))
|
2020-01-09 15:42:27 +00:00
|
|
|
xmkdir(sbin_path.data(), mode);
|
2019-12-06 20:31:49 +00:00
|
|
|
else
|
2020-01-09 15:42:27 +00:00
|
|
|
close(xopen(sbin_path.data(), O_CREAT | O_WRONLY | O_CLOEXEC, mode));
|
2019-12-06 20:31:49 +00:00
|
|
|
|
2020-01-09 15:42:27 +00:00
|
|
|
xmount(buf, sbin_path.data(), nullptr, MS_BIND, nullptr);
|
|
|
|
} else {
|
|
|
|
xsymlink(buf, sbin_path.data());
|
|
|
|
}
|
2019-12-06 20:31:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-19 05:16:20 +00:00
|
|
|
static string magic_mount_list;
|
2019-07-17 06:54:52 +00:00
|
|
|
|
2020-02-21 08:49:58 +00:00
|
|
|
static void magic_mount(const string &sdir, const string &ddir = "") {
|
|
|
|
auto dir = xopen_dir(sdir.data());
|
|
|
|
for (dirent *entry; (entry = readdir(dir.get()));) {
|
2019-07-16 08:08:28 +00:00
|
|
|
if (entry->d_name == "."sv || entry->d_name == ".."sv)
|
|
|
|
continue;
|
2020-02-21 08:49:58 +00:00
|
|
|
string src = sdir + "/" + entry->d_name;
|
|
|
|
string dest = ddir + "/" + entry->d_name;
|
2019-07-16 08:08:28 +00:00
|
|
|
if (access(dest.data(), F_OK) == 0) {
|
|
|
|
if (entry->d_type == DT_DIR) {
|
|
|
|
// Recursive
|
2020-02-21 08:49:58 +00:00
|
|
|
magic_mount(src, dest);
|
2019-07-16 08:08:28 +00:00
|
|
|
} else {
|
|
|
|
LOGD("Mount [%s] -> [%s]\n", src.data(), dest.data());
|
|
|
|
xmount(src.data(), dest.data(), nullptr, MS_BIND, nullptr);
|
2019-11-19 05:16:20 +00:00
|
|
|
magic_mount_list += dest;
|
|
|
|
magic_mount_list += '\n';
|
2019-07-16 08:08:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-12 12:34:56 +00:00
|
|
|
#define ROOTMIR MIRRDIR "/system_root"
|
|
|
|
#define ROOTBLK BLOCKDIR "/system_root"
|
|
|
|
#define MONOPOLICY "/sepolicy"
|
|
|
|
#define PATCHPOLICY "/sbin/.se"
|
|
|
|
#define LIBSELINUX "/system/" LIBNAME "/libselinux.so"
|
|
|
|
|
2019-09-22 09:20:51 +00:00
|
|
|
void SARBase::patch_rootdir() {
|
2020-04-12 12:34:56 +00:00
|
|
|
// TODO: dynamic paths
|
|
|
|
tmp_dir = "/sbin";
|
|
|
|
|
|
|
|
setup_tmp(tmp_dir.data(), self, config);
|
|
|
|
persist_dir = tmp_dir + "/" MIRRDIR "/persist";
|
|
|
|
|
|
|
|
chdir(tmp_dir.data());
|
2019-06-24 08:21:33 +00:00
|
|
|
|
|
|
|
// Mount system_root mirror
|
2020-04-01 05:41:25 +00:00
|
|
|
struct stat st;
|
|
|
|
xstat("/", &st);
|
2019-12-09 07:44:49 +00:00
|
|
|
xmkdir(ROOTMIR, 0755);
|
2020-04-01 05:41:25 +00:00
|
|
|
mknod(ROOTBLK, S_IFBLK | 0600, st.st_dev);
|
2019-06-24 08:21:33 +00:00
|
|
|
if (xmount(ROOTBLK, ROOTMIR, "ext4", MS_RDONLY, nullptr))
|
|
|
|
xmount(ROOTBLK, ROOTMIR, "erofs", MS_RDONLY, nullptr);
|
|
|
|
|
2020-04-12 12:34:56 +00:00
|
|
|
// Recreate original sbin structure if necessary
|
|
|
|
if (tmp_dir == "/sbin")
|
|
|
|
recreate_sbin(ROOTMIR "/sbin", true);
|
2019-06-26 04:34:02 +00:00
|
|
|
|
2019-07-16 08:08:28 +00:00
|
|
|
// Patch init
|
|
|
|
raw_data init;
|
2019-06-26 04:34:02 +00:00
|
|
|
file_attr attr;
|
|
|
|
bool redirect = false;
|
2019-12-06 20:31:49 +00:00
|
|
|
int src = xopen("/init", O_RDONLY | O_CLOEXEC);
|
2019-07-16 08:08:28 +00:00
|
|
|
fd_full_read(src, init.buf, init.sz);
|
2019-06-26 04:34:02 +00:00
|
|
|
fgetattr(src, &attr);
|
|
|
|
close(src);
|
2019-07-16 08:08:28 +00:00
|
|
|
uint8_t *eof = init.buf + init.sz;
|
|
|
|
for (uint8_t *p = init.buf; p < eof; ++p) {
|
2019-06-26 04:34:02 +00:00
|
|
|
if (memcmp(p, SPLIT_PLAT_CIL, sizeof(SPLIT_PLAT_CIL)) == 0) {
|
|
|
|
// Force init to load monolithic policy
|
|
|
|
LOGD("Remove from init: " SPLIT_PLAT_CIL "\n");
|
|
|
|
memset(p, 'x', sizeof(SPLIT_PLAT_CIL) - 1);
|
|
|
|
p += sizeof(SPLIT_PLAT_CIL) - 1;
|
|
|
|
} else if (memcmp(p, MONOPOLICY, sizeof(MONOPOLICY)) == 0) {
|
|
|
|
// Redirect /sepolicy to tmpfs
|
|
|
|
LOGD("Patch init [" MONOPOLICY "] -> [" PATCHPOLICY "]\n");
|
|
|
|
memcpy(p, PATCHPOLICY, sizeof(PATCHPOLICY));
|
|
|
|
redirect = true;
|
|
|
|
p += sizeof(MONOPOLICY) - 1;
|
|
|
|
}
|
|
|
|
}
|
2019-07-16 08:08:28 +00:00
|
|
|
xmkdir(ROOTOVL, 0);
|
2019-12-06 20:31:49 +00:00
|
|
|
int dest = xopen(ROOTOVL "/init", O_CREAT | O_WRONLY | O_CLOEXEC);
|
2019-07-16 08:08:28 +00:00
|
|
|
xwrite(dest, init.buf, init.sz);
|
2019-06-26 04:34:02 +00:00
|
|
|
fsetattr(dest, &attr);
|
|
|
|
close(dest);
|
|
|
|
|
2019-07-16 08:08:28 +00:00
|
|
|
// Patch libselinux
|
2019-06-26 04:34:02 +00:00
|
|
|
if (!redirect) {
|
2019-07-16 08:08:28 +00:00
|
|
|
raw_data lib;
|
2019-06-26 04:34:02 +00:00
|
|
|
// init is dynamically linked, need to patch libselinux
|
2019-07-16 08:08:28 +00:00
|
|
|
full_read(LIBSELINUX, lib.buf, lib.sz);
|
2019-06-26 04:34:02 +00:00
|
|
|
getattr(LIBSELINUX, &attr);
|
2019-07-16 08:08:28 +00:00
|
|
|
eof = lib.buf + lib.sz;
|
|
|
|
for (uint8_t *p = lib.buf; p < eof; ++p) {
|
2019-06-26 04:34:02 +00:00
|
|
|
if (memcmp(p, MONOPOLICY, sizeof(MONOPOLICY)) == 0) {
|
|
|
|
// Redirect /sepolicy to tmpfs
|
|
|
|
LOGD("Patch libselinux.so [" MONOPOLICY "] -> [" PATCHPOLICY "]\n");
|
|
|
|
memcpy(p, PATCHPOLICY, sizeof(PATCHPOLICY));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2019-07-16 08:08:28 +00:00
|
|
|
xmkdir(ROOTOVL "/system", 0755);
|
|
|
|
xmkdir(ROOTOVL "/system/" LIBNAME, 0755);
|
|
|
|
dest = xopen(ROOTOVL LIBSELINUX, O_CREAT | O_WRONLY | O_CLOEXEC);
|
|
|
|
xwrite(dest, lib.buf, lib.sz);
|
2019-06-26 04:34:02 +00:00
|
|
|
fsetattr(dest, &attr);
|
|
|
|
close(dest);
|
|
|
|
}
|
|
|
|
|
2019-07-16 08:08:28 +00:00
|
|
|
// sepolicy
|
2019-06-26 04:34:02 +00:00
|
|
|
patch_sepolicy(PATCHPOLICY);
|
2019-06-26 06:31:59 +00:00
|
|
|
|
2019-07-16 08:08:28 +00:00
|
|
|
// Handle overlay
|
2020-04-12 12:34:56 +00:00
|
|
|
struct sockaddr_un sun;
|
|
|
|
int sockfd = xsocket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0);
|
|
|
|
if (connect(sockfd, (struct sockaddr*) &sun, setup_sockaddr(&sun, INIT_SOCKET)) == 0) {
|
2020-04-01 11:39:28 +00:00
|
|
|
LOGD("ACK init tracer to write backup files\n");
|
2020-04-12 12:34:56 +00:00
|
|
|
// Let tracer know where tmp_dir is
|
|
|
|
write_string(sockfd, tmp_dir.data());
|
|
|
|
// Wait for tracer to finish copying files
|
2020-04-01 11:39:28 +00:00
|
|
|
int ack;
|
2020-04-12 12:34:56 +00:00
|
|
|
read(sockfd, &ack, sizeof(ack));
|
2020-04-01 11:39:28 +00:00
|
|
|
} else {
|
|
|
|
LOGD("Restore backup files locally\n");
|
|
|
|
restore_folder(ROOTOVL, overlays);
|
|
|
|
overlays.clear();
|
|
|
|
}
|
2020-04-12 12:34:56 +00:00
|
|
|
close(sockfd);
|
2020-04-01 11:39:28 +00:00
|
|
|
if (access(ROOTOVL "/sbin", F_OK) == 0) {
|
|
|
|
file_attr a;
|
|
|
|
getattr("/sbin", &a);
|
|
|
|
cp_afc(ROOTOVL "/sbin", "/sbin");
|
|
|
|
rm_rf(ROOTOVL "/sbin");
|
|
|
|
setattr("/sbin", &a);
|
2019-07-16 08:08:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Patch init.rc
|
|
|
|
FILE *rc = xfopen(ROOTOVL "/init.rc", "we");
|
2019-06-26 06:31:59 +00:00
|
|
|
patch_init_rc(rc);
|
|
|
|
fclose(rc);
|
2019-07-16 08:08:28 +00:00
|
|
|
clone_attr("/init.rc", ROOTOVL "/init.rc");
|
|
|
|
|
|
|
|
// Mount rootdir
|
2020-02-21 08:49:58 +00:00
|
|
|
magic_mount(ROOTOVL);
|
2020-04-12 12:34:56 +00:00
|
|
|
dest = xopen(ROOTMNT, O_WRONLY | O_CREAT | O_CLOEXEC, 0);
|
2019-11-19 05:16:20 +00:00
|
|
|
write(dest, magic_mount_list.data(), magic_mount_list.length());
|
2019-07-17 06:54:52 +00:00
|
|
|
close(dest);
|
2020-04-12 12:34:56 +00:00
|
|
|
|
|
|
|
chdir("/");
|
2019-06-24 08:21:33 +00:00
|
|
|
}
|
|
|
|
|
2019-06-22 10:14:33 +00:00
|
|
|
int magisk_proxy_main(int argc, char *argv[]) {
|
|
|
|
setup_klog();
|
|
|
|
|
|
|
|
raw_data config;
|
|
|
|
raw_data self;
|
|
|
|
|
2019-07-16 08:08:28 +00:00
|
|
|
full_read("/sbin/magisk", self.buf, self.sz);
|
|
|
|
full_read("/.backup/.magisk", config.buf, config.sz);
|
2019-06-22 10:14:33 +00:00
|
|
|
|
|
|
|
xmount(nullptr, "/", nullptr, MS_REMOUNT, nullptr);
|
|
|
|
|
|
|
|
unlink("/sbin/magisk");
|
|
|
|
rm_rf("/.backup");
|
|
|
|
|
2020-04-12 12:34:56 +00:00
|
|
|
setup_tmp("/sbin", self, config);
|
2019-06-22 10:14:33 +00:00
|
|
|
|
|
|
|
// Create symlinks pointing back to /root
|
2020-01-09 15:42:27 +00:00
|
|
|
recreate_sbin("/root", false);
|
2019-06-22 10:14:33 +00:00
|
|
|
|
|
|
|
setenv("REMOUNT_ROOT", "1", 1);
|
|
|
|
execv("/sbin/magisk", argv);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|