mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-08-14 17:27:24 +00:00
Hijack another binary for 2nd stage
Instead of using ptrace hacks, use another hack instead :D
This commit is contained in:
@@ -101,7 +101,7 @@ public:
|
|||||||
|
|
||||||
class SARFirstStageInit : public SARBase {
|
class SARFirstStageInit : public SARBase {
|
||||||
private:
|
private:
|
||||||
void traced_exec_init();
|
void prepare();
|
||||||
protected:
|
protected:
|
||||||
void early_mount() override;
|
void early_mount() override;
|
||||||
public:
|
public:
|
||||||
@@ -110,7 +110,8 @@ public:
|
|||||||
};
|
};
|
||||||
void start() override {
|
void start() override {
|
||||||
early_mount();
|
early_mount();
|
||||||
traced_exec_init();
|
prepare();
|
||||||
|
exec_init();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -195,7 +195,8 @@ void SARBase::backup_files() {
|
|||||||
backup_folder("/overlay.d", overlays);
|
backup_folder("/overlay.d", overlays);
|
||||||
|
|
||||||
full_read("/proc/self/exe", self.buf, self.sz);
|
full_read("/proc/self/exe", self.buf, self.sz);
|
||||||
full_read("/.backup/.magisk", config.buf, config.sz);
|
if (access("/.backup/.magisk", R_OK) == 0)
|
||||||
|
full_read("/.backup/.magisk", config.buf, config.sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SARBase::mount_system_root() {
|
void SARBase::mount_system_root() {
|
||||||
@@ -242,11 +243,9 @@ void SARFirstStageInit::early_mount() {
|
|||||||
|
|
||||||
void SecondStageInit::early_mount() {
|
void SecondStageInit::early_mount() {
|
||||||
backup_files();
|
backup_files();
|
||||||
rm_rf("/system");
|
|
||||||
rm_rf("/.backup");
|
|
||||||
rm_rf("/overlay.d");
|
|
||||||
|
|
||||||
umount2("/system/bin/init", MNT_DETACH);
|
umount2("/init", MNT_DETACH);
|
||||||
|
umount2("/proc/self/exe", MNT_DETACH);
|
||||||
|
|
||||||
if (access("/system_root", F_OK) == 0)
|
if (access("/system_root", F_OK) == 0)
|
||||||
switch_root("/system_root");
|
switch_root("/system_root");
|
||||||
|
@@ -131,9 +131,11 @@ bool MagiskInit::patch_sepolicy(const char *file) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mount selinuxfs to communicate with kernel
|
if (access(SELINUX_VERSION, F_OK) != 0) {
|
||||||
xmount("selinuxfs", SELINUX_MNT, "selinuxfs", 0, nullptr);
|
// Mount selinuxfs to communicate with kernel
|
||||||
mount_list.emplace_back(SELINUX_MNT);
|
xmount("selinuxfs", SELINUX_MNT, "selinuxfs", 0, nullptr);
|
||||||
|
mount_list.emplace_back(SELINUX_MNT);
|
||||||
|
}
|
||||||
|
|
||||||
if (patch_init)
|
if (patch_init)
|
||||||
load_split_cil();
|
load_split_cil();
|
||||||
@@ -307,10 +309,10 @@ void SARBase::patch_rootdir() {
|
|||||||
struct sockaddr_un sun;
|
struct sockaddr_un sun;
|
||||||
int sockfd = xsocket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0);
|
int sockfd = xsocket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0);
|
||||||
if (connect(sockfd, (struct sockaddr*) &sun, setup_sockaddr(&sun, INIT_SOCKET)) == 0) {
|
if (connect(sockfd, (struct sockaddr*) &sun, setup_sockaddr(&sun, INIT_SOCKET)) == 0) {
|
||||||
LOGD("ACK init tracer to write backup files\n");
|
LOGD("ACK init daemon to write backup files\n");
|
||||||
// Let tracer know where tmp_dir is
|
// Let daemon know where tmp_dir is
|
||||||
write_string(sockfd, tmp_dir);
|
write_string(sockfd, tmp_dir);
|
||||||
// Wait for tracer to finish copying files
|
// Wait for daemon to finish restoring files
|
||||||
int ack;
|
int ack;
|
||||||
read(sockfd, &ack, sizeof(ack));
|
read(sockfd, &ack, sizeof(ack));
|
||||||
} else {
|
} else {
|
||||||
|
@@ -1,6 +1,3 @@
|
|||||||
#include <sys/ptrace.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
|
|
||||||
#include <magisk.hpp>
|
#include <magisk.hpp>
|
||||||
#include <utils.hpp>
|
#include <utils.hpp>
|
||||||
#include <logging.hpp>
|
#include <logging.hpp>
|
||||||
@@ -76,20 +73,41 @@ void FirstStageInit::prepare() {
|
|||||||
chdir("/");
|
chdir("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline long xptrace(int request, pid_t pid, void *addr, void *data) {
|
#define INIT_PATH "/system/bin/init"
|
||||||
long ret = ptrace(request, pid, addr, data);
|
#define REDIR_PATH "/system/bin/adbd"
|
||||||
if (ret < 0)
|
|
||||||
PLOGE("ptrace %d", pid);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline long xptrace(int request, pid_t pid, void *addr = nullptr, intptr_t data = 0) {
|
void SARFirstStageInit::prepare() {
|
||||||
return xptrace(request, pid, addr, reinterpret_cast<void *>(data));
|
|
||||||
}
|
|
||||||
|
|
||||||
void SARFirstStageInit::traced_exec_init() {
|
|
||||||
int pid = getpid();
|
int pid = getpid();
|
||||||
|
|
||||||
|
xmount("tmpfs", "/dev", "tmpfs", 0, "mode=755");
|
||||||
|
|
||||||
|
// Patch init binary
|
||||||
|
raw_data init;
|
||||||
|
int src = xopen("/init", O_RDONLY);
|
||||||
|
fd_full_read(src, init.buf, init.sz);
|
||||||
|
for (uint8_t *p = init.buf, *eof = init.buf + init.sz; p < eof; ++p) {
|
||||||
|
if (memcmp(p, INIT_PATH, sizeof(INIT_PATH)) == 0) {
|
||||||
|
LOGD("Patch init [" INIT_PATH "] -> [" REDIR_PATH "]\n");
|
||||||
|
memcpy(p, REDIR_PATH, sizeof(REDIR_PATH));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int dest = xopen("/dev/init", O_CREAT | O_WRONLY, 0);
|
||||||
|
write(dest, init.buf, init.sz);
|
||||||
|
fclone_attr(src, dest);
|
||||||
|
close(dest);
|
||||||
|
|
||||||
|
// Replace redirect init with magiskinit
|
||||||
|
dest = xopen("/dev/magiskinit", O_CREAT | O_WRONLY, 0);
|
||||||
|
write(dest, self.buf, self.sz);
|
||||||
|
fclone_attr(src, dest);
|
||||||
|
close(src);
|
||||||
|
close(dest);
|
||||||
|
|
||||||
|
xmount("/dev/init", "/init", nullptr, MS_BIND, nullptr);
|
||||||
|
xmount("/dev/magiskinit", REDIR_PATH, nullptr, MS_BIND, nullptr);
|
||||||
|
xumount2("/dev", MNT_DETACH);
|
||||||
|
|
||||||
// Block SIGUSR1
|
// Block SIGUSR1
|
||||||
sigset_t block, old;
|
sigset_t block, old;
|
||||||
sigemptyset(&block);
|
sigemptyset(&block);
|
||||||
@@ -97,42 +115,22 @@ void SARFirstStageInit::traced_exec_init() {
|
|||||||
sigprocmask(SIG_BLOCK, &block, &old);
|
sigprocmask(SIG_BLOCK, &block, &old);
|
||||||
|
|
||||||
if (int child = xfork(); child) {
|
if (int child = xfork(); child) {
|
||||||
LOGD("init tracer [%d]\n", child);
|
LOGD("init daemon [%d]\n", child);
|
||||||
// Wait for children to attach
|
// Wait for children signal
|
||||||
int sig;
|
int sig;
|
||||||
sigwait(&block, &sig);
|
sigwait(&block, &sig);
|
||||||
|
|
||||||
// Restore sigmask
|
// Restore sigmask
|
||||||
sigprocmask(SIG_BLOCK, &old, nullptr);
|
sigprocmask(SIG_SETMASK, &old, nullptr);
|
||||||
|
|
||||||
// Re-exec init
|
|
||||||
exec_init();
|
|
||||||
} else {
|
} else {
|
||||||
// Attach to parent to trace exec
|
|
||||||
xptrace(PTRACE_ATTACH, pid);
|
|
||||||
waitpid(pid, nullptr, __WALL | __WNOTHREAD);
|
|
||||||
xptrace(PTRACE_SETOPTIONS, pid, nullptr, PTRACE_O_TRACEEXEC);
|
|
||||||
xptrace(PTRACE_CONT, pid, 0, SIGUSR1);
|
|
||||||
|
|
||||||
// Wait for execve
|
|
||||||
waitpid(pid, nullptr, __WALL | __WNOTHREAD);
|
|
||||||
|
|
||||||
// Swap out init with bind mount
|
|
||||||
xmount("tmpfs", "/dev", "tmpfs", 0, "mode=755");
|
|
||||||
int init = xopen("/dev/magiskinit", O_CREAT | O_WRONLY, 0750);
|
|
||||||
write(init, self.buf, self.sz);
|
|
||||||
close(init);
|
|
||||||
xmount("/dev/magiskinit", "/init", nullptr, MS_BIND, nullptr);
|
|
||||||
xumount2("/dev", MNT_DETACH);
|
|
||||||
|
|
||||||
// Establish socket for 2nd stage ack
|
// Establish socket for 2nd stage ack
|
||||||
struct sockaddr_un sun;
|
struct sockaddr_un sun;
|
||||||
int sockfd = xsocket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0);
|
int sockfd = xsocket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0);
|
||||||
xbind(sockfd, (struct sockaddr*) &sun, setup_sockaddr(&sun, INIT_SOCKET));
|
xbind(sockfd, (struct sockaddr*) &sun, setup_sockaddr(&sun, INIT_SOCKET));
|
||||||
xlisten(sockfd, 1);
|
xlisten(sockfd, 1);
|
||||||
|
|
||||||
// Resume init
|
// Resume parent
|
||||||
xptrace(PTRACE_DETACH, pid);
|
kill(pid, SIGUSR1);
|
||||||
|
|
||||||
// Wait for second stage ack
|
// Wait for second stage ack
|
||||||
int client = xaccept4(sockfd, nullptr, nullptr, SOCK_CLOEXEC);
|
int client = xaccept4(sockfd, nullptr, nullptr, SOCK_CLOEXEC);
|
||||||
|
Reference in New Issue
Block a user