mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-01-12 02:33:38 +00:00
Hijack another binary for 2nd stage
Instead of using ptrace hacks, use another hack instead :D
This commit is contained in:
parent
765d5d9729
commit
e219867cdf
@ -101,7 +101,7 @@ public:
|
||||
|
||||
class SARFirstStageInit : public SARBase {
|
||||
private:
|
||||
void traced_exec_init();
|
||||
void prepare();
|
||||
protected:
|
||||
void early_mount() override;
|
||||
public:
|
||||
@ -110,7 +110,8 @@ public:
|
||||
};
|
||||
void start() override {
|
||||
early_mount();
|
||||
traced_exec_init();
|
||||
prepare();
|
||||
exec_init();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -195,6 +195,7 @@ void SARBase::backup_files() {
|
||||
backup_folder("/overlay.d", overlays);
|
||||
|
||||
full_read("/proc/self/exe", self.buf, self.sz);
|
||||
if (access("/.backup/.magisk", R_OK) == 0)
|
||||
full_read("/.backup/.magisk", config.buf, config.sz);
|
||||
}
|
||||
|
||||
@ -242,11 +243,9 @@ void SARFirstStageInit::early_mount() {
|
||||
|
||||
void SecondStageInit::early_mount() {
|
||||
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)
|
||||
switch_root("/system_root");
|
||||
|
@ -131,9 +131,11 @@ bool MagiskInit::patch_sepolicy(const char *file) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (access(SELINUX_VERSION, F_OK) != 0) {
|
||||
// Mount selinuxfs to communicate with kernel
|
||||
xmount("selinuxfs", SELINUX_MNT, "selinuxfs", 0, nullptr);
|
||||
mount_list.emplace_back(SELINUX_MNT);
|
||||
}
|
||||
|
||||
if (patch_init)
|
||||
load_split_cil();
|
||||
@ -307,10 +309,10 @@ void SARBase::patch_rootdir() {
|
||||
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) {
|
||||
LOGD("ACK init tracer to write backup files\n");
|
||||
// Let tracer know where tmp_dir is
|
||||
LOGD("ACK init daemon to write backup files\n");
|
||||
// Let daemon know where tmp_dir is
|
||||
write_string(sockfd, tmp_dir);
|
||||
// Wait for tracer to finish copying files
|
||||
// Wait for daemon to finish restoring files
|
||||
int ack;
|
||||
read(sockfd, &ack, sizeof(ack));
|
||||
} else {
|
||||
|
@ -1,6 +1,3 @@
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <magisk.hpp>
|
||||
#include <utils.hpp>
|
||||
#include <logging.hpp>
|
||||
@ -76,20 +73,41 @@ void FirstStageInit::prepare() {
|
||||
chdir("/");
|
||||
}
|
||||
|
||||
static inline long xptrace(int request, pid_t pid, void *addr, void *data) {
|
||||
long ret = ptrace(request, pid, addr, data);
|
||||
if (ret < 0)
|
||||
PLOGE("ptrace %d", pid);
|
||||
return ret;
|
||||
}
|
||||
#define INIT_PATH "/system/bin/init"
|
||||
#define REDIR_PATH "/system/bin/adbd"
|
||||
|
||||
static inline long xptrace(int request, pid_t pid, void *addr = nullptr, intptr_t data = 0) {
|
||||
return xptrace(request, pid, addr, reinterpret_cast<void *>(data));
|
||||
}
|
||||
|
||||
void SARFirstStageInit::traced_exec_init() {
|
||||
void SARFirstStageInit::prepare() {
|
||||
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
|
||||
sigset_t block, old;
|
||||
sigemptyset(&block);
|
||||
@ -97,42 +115,22 @@ void SARFirstStageInit::traced_exec_init() {
|
||||
sigprocmask(SIG_BLOCK, &block, &old);
|
||||
|
||||
if (int child = xfork(); child) {
|
||||
LOGD("init tracer [%d]\n", child);
|
||||
// Wait for children to attach
|
||||
LOGD("init daemon [%d]\n", child);
|
||||
// Wait for children signal
|
||||
int sig;
|
||||
sigwait(&block, &sig);
|
||||
|
||||
// Restore sigmask
|
||||
sigprocmask(SIG_BLOCK, &old, nullptr);
|
||||
|
||||
// Re-exec init
|
||||
exec_init();
|
||||
sigprocmask(SIG_SETMASK, &old, nullptr);
|
||||
} 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
|
||||
struct sockaddr_un sun;
|
||||
int sockfd = xsocket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0);
|
||||
xbind(sockfd, (struct sockaddr*) &sun, setup_sockaddr(&sun, INIT_SOCKET));
|
||||
xlisten(sockfd, 1);
|
||||
|
||||
// Resume init
|
||||
xptrace(PTRACE_DETACH, pid);
|
||||
// Resume parent
|
||||
kill(pid, SIGUSR1);
|
||||
|
||||
// Wait for second stage ack
|
||||
int client = xaccept4(sockfd, nullptr, nullptr, SOCK_CLOEXEC);
|
||||
|
Loading…
x
Reference in New Issue
Block a user