mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-02-21 11:58:29 +00:00
Use magiskd to setup files
This commit is contained in:
parent
003fea52b1
commit
9b3efffba9
@ -68,6 +68,9 @@ static void handle_request_async(int client, int code, ucred cred) {
|
|||||||
close(client);
|
close(client);
|
||||||
reboot();
|
reboot();
|
||||||
break;
|
break;
|
||||||
|
case ZYGISK_REQUEST:
|
||||||
|
zygisk_handler(client, &cred);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
close(client);
|
close(client);
|
||||||
break;
|
break;
|
||||||
@ -116,6 +119,7 @@ static void handle_request(int client) {
|
|||||||
case BOOT_COMPLETE:
|
case BOOT_COMPLETE:
|
||||||
case SQLITE_CMD:
|
case SQLITE_CMD:
|
||||||
case GET_PATH:
|
case GET_PATH:
|
||||||
|
case MAGISKHIDE:
|
||||||
if (!is_root) {
|
if (!is_root) {
|
||||||
write_int(client, ROOT_REQUIRED);
|
write_int(client, ROOT_REQUIRED);
|
||||||
goto done;
|
goto done;
|
||||||
@ -127,9 +131,9 @@ static void handle_request(int client) {
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MAGISKHIDE: // accept hide request from zygote
|
case ZYGISK_REQUEST:
|
||||||
if (!is_root && !is_zygote) {
|
if (!is_zygote) {
|
||||||
write_int(client, ROOT_REQUIRED);
|
write_int(client, DAEMON_ERROR);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -260,7 +264,7 @@ int connect_daemon(bool create) {
|
|||||||
if (connect(fd, (sockaddr*) &sun, len)) {
|
if (connect(fd, (sockaddr*) &sun, len)) {
|
||||||
if (!create || getuid() != UID_ROOT) {
|
if (!create || getuid() != UID_ROOT) {
|
||||||
LOGE("No daemon is currently running!\n");
|
LOGE("No daemon is currently running!\n");
|
||||||
exit(1);
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fork_dont_care() == 0) {
|
if (fork_dont_care() == 0) {
|
||||||
|
@ -158,6 +158,16 @@ void magisk_logging() {
|
|||||||
log_cb.ex = nop_ex;
|
log_cb.ex = nop_ex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define alog(prio) [](auto fmt, auto ap){ \
|
||||||
|
return __android_log_vprint(ANDROID_LOG_##prio, "Magisk", fmt, ap); }
|
||||||
|
void android_logging() {
|
||||||
|
log_cb.d = alog(DEBUG);
|
||||||
|
log_cb.i = alog(INFO);
|
||||||
|
log_cb.w = alog(WARN);
|
||||||
|
log_cb.e = alog(ERROR);
|
||||||
|
log_cb.ex = nop_ex;
|
||||||
|
}
|
||||||
|
|
||||||
void start_log_daemon() {
|
void start_log_daemon() {
|
||||||
int fds[2];
|
int fds[2];
|
||||||
if (pipe2(fds, O_CLOEXEC) == 0) {
|
if (pipe2(fds, O_CLOEXEC) == 0) {
|
||||||
|
@ -25,6 +25,7 @@ enum : int {
|
|||||||
MAGISKHIDE,
|
MAGISKHIDE,
|
||||||
SQLITE_CMD,
|
SQLITE_CMD,
|
||||||
REMOVE_MODULES,
|
REMOVE_MODULES,
|
||||||
|
ZYGISK_REQUEST,
|
||||||
DAEMON_CODE_END,
|
DAEMON_CODE_END,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -47,12 +48,15 @@ enum : int {
|
|||||||
|
|
||||||
int connect_daemon(bool create = false);
|
int connect_daemon(bool create = false);
|
||||||
|
|
||||||
|
void android_logging();
|
||||||
|
|
||||||
// Daemon handlers
|
// Daemon handlers
|
||||||
void post_fs_data(int client);
|
void post_fs_data(int client);
|
||||||
void late_start(int client);
|
void late_start(int client);
|
||||||
void boot_complete(int client);
|
void boot_complete(int client);
|
||||||
void magiskhide_handler(int client, ucred *cred);
|
void magiskhide_handler(int client, ucred *cred);
|
||||||
void su_daemon_handler(int client, ucred *credential);
|
void su_daemon_handler(int client, ucred *credential);
|
||||||
|
void zygisk_handler(int client, ucred *cred);
|
||||||
|
|
||||||
// MagiskHide
|
// MagiskHide
|
||||||
void check_enable_hide();
|
void check_enable_hide();
|
||||||
|
@ -3,9 +3,10 @@
|
|||||||
#include <sys/mount.h>
|
#include <sys/mount.h>
|
||||||
#include <sys/sendfile.h>
|
#include <sys/sendfile.h>
|
||||||
#include <sys/prctl.h>
|
#include <sys/prctl.h>
|
||||||
#include <android/log.h>
|
|
||||||
|
|
||||||
#include <utils.hpp>
|
#include <utils.hpp>
|
||||||
|
#include <daemon.hpp>
|
||||||
|
#include <magisk.hpp>
|
||||||
|
|
||||||
#include "inject.hpp"
|
#include "inject.hpp"
|
||||||
|
|
||||||
@ -14,16 +15,6 @@ using namespace std;
|
|||||||
static void *self_handle = nullptr;
|
static void *self_handle = nullptr;
|
||||||
static atomic<int> active_threads = -1;
|
static atomic<int> active_threads = -1;
|
||||||
|
|
||||||
#define alog(prio) [](auto fmt, auto ap){ \
|
|
||||||
return __android_log_vprint(ANDROID_LOG_##prio, "Magisk", fmt, ap); }
|
|
||||||
static void inject_logging() {
|
|
||||||
log_cb.d = alog(DEBUG);
|
|
||||||
log_cb.i = alog(INFO);
|
|
||||||
log_cb.w = alog(WARN);
|
|
||||||
log_cb.e = alog(ERROR);
|
|
||||||
log_cb.ex = nop_ex;
|
|
||||||
}
|
|
||||||
|
|
||||||
void self_unload() {
|
void self_unload() {
|
||||||
LOGD("hook: Request to self unload\n");
|
LOGD("hook: Request to self unload\n");
|
||||||
// If unhook failed, do not unload or else it will cause SIGSEGV
|
// If unhook failed, do not unload or else it will cause SIGSEGV
|
||||||
@ -33,7 +24,7 @@ void self_unload() {
|
|||||||
active_threads--;
|
active_threads--;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *unload_first_stage(void *) {
|
static void *unload_first_stage(void *v) {
|
||||||
// Setup 1ms
|
// Setup 1ms
|
||||||
timespec ts = { .tv_sec = 0, .tv_nsec = 1000000L };
|
timespec ts = { .tv_sec = 0, .tv_nsec = 1000000L };
|
||||||
|
|
||||||
@ -43,7 +34,8 @@ static void *unload_first_stage(void *) {
|
|||||||
// Wait another 1ms to make sure all threads left our code
|
// Wait another 1ms to make sure all threads left our code
|
||||||
nanosleep(&ts, nullptr);
|
nanosleep(&ts, nullptr);
|
||||||
|
|
||||||
unmap_all(INJECT_LIB_1);
|
char *path = static_cast<char *>(v);
|
||||||
|
unmap_all(path);
|
||||||
active_threads--;
|
active_threads--;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -87,66 +79,108 @@ static void inject_cleanup_wait() {
|
|||||||
|
|
||||||
__attribute__((constructor))
|
__attribute__((constructor))
|
||||||
static void inject_init() {
|
static void inject_init() {
|
||||||
if (getenv(INJECT_ENV_2)) {
|
if (char *env = getenv(INJECT_ENV_2)) {
|
||||||
inject_logging();
|
android_logging();
|
||||||
LOGD("zygote: inject 2nd stage\n");
|
LOGD("zygote: inject 2nd stage\n");
|
||||||
active_threads = 1;
|
active_threads = 1;
|
||||||
unsetenv(INJECT_ENV_2);
|
unsetenv(INJECT_ENV_2);
|
||||||
|
|
||||||
// Get our own handle
|
// Get our own handle
|
||||||
self_handle = dlopen(INJECT_LIB_2, RTLD_LAZY);
|
self_handle = dlopen(env, RTLD_LAZY);
|
||||||
dlclose(self_handle);
|
dlclose(self_handle);
|
||||||
unlink(INJECT_LIB_2);
|
|
||||||
|
|
||||||
hook_functions();
|
hook_functions();
|
||||||
|
|
||||||
|
// Update path to 1st stage lib
|
||||||
|
*(strrchr(env, '.') - 1) = '1';
|
||||||
|
|
||||||
// Some cleanup
|
// Some cleanup
|
||||||
sanitize_environ();
|
sanitize_environ();
|
||||||
active_threads++;
|
active_threads++;
|
||||||
new_daemon_thread(&unload_first_stage);
|
new_daemon_thread(&unload_first_stage, env);
|
||||||
} else if (char *env = getenv(INJECT_ENV_1)) {
|
} else if (getenv(INJECT_ENV_1)) {
|
||||||
inject_logging();
|
android_logging();
|
||||||
LOGD("zygote: inject 1st stage\n");
|
LOGD("zygote: inject 1st stage\n");
|
||||||
|
|
||||||
if (env[0] == '1')
|
char *ld = getenv("LD_PRELOAD");
|
||||||
|
char *path;
|
||||||
|
if (char *c = strrchr(ld, ':')) {
|
||||||
|
*c = '\0';
|
||||||
|
setenv("LD_PRELOAD", ld, 1); // Restore original LD_PRELOAD
|
||||||
|
path = c + 1;
|
||||||
|
} else {
|
||||||
unsetenv("LD_PRELOAD");
|
unsetenv("LD_PRELOAD");
|
||||||
else
|
path = ld;
|
||||||
setenv("LD_PRELOAD", env, 1); // Restore original LD_PRELOAD
|
}
|
||||||
|
|
||||||
|
// Update path to 2nd stage lib
|
||||||
|
*(strrchr(path, '.') - 1) = '2';
|
||||||
|
|
||||||
// Setup second stage
|
// Setup second stage
|
||||||
setenv(INJECT_ENV_2, "1", 1);
|
setenv(INJECT_ENV_2, path, 1);
|
||||||
cp_afc(INJECT_LIB_1, INJECT_LIB_2);
|
dlopen(path, RTLD_LAZY);
|
||||||
dlopen(INJECT_LIB_2, RTLD_LAZY);
|
|
||||||
|
|
||||||
unlink(INJECT_LIB_1);
|
|
||||||
unsetenv(INJECT_ENV_1);
|
unsetenv(INJECT_ENV_1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int app_process_main(int argc, char *argv[]) {
|
int app_process_main(int argc, char *argv[]) {
|
||||||
inject_logging();
|
android_logging();
|
||||||
char buf[4096];
|
|
||||||
if (realpath("/proc/self/exe", buf) == nullptr)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
int in = xopen(buf, O_RDONLY);
|
if (int fd = connect_daemon(); fd >= 0) {
|
||||||
int out = xopen(INJECT_LIB_1, O_WRONLY | O_CREAT, 0644);
|
write_int(fd, ZYGISK_REQUEST);
|
||||||
sendfile(out, in, nullptr, INT_MAX);
|
write_int(fd, ZYGISK_SETUP);
|
||||||
close(in);
|
|
||||||
close(out);
|
|
||||||
|
|
||||||
if (char *ld = getenv("LD_PRELOAD")) {
|
if (read_int(fd) == 0) {
|
||||||
char env[128];
|
string path = read_string(fd);
|
||||||
sprintf(env, "%s:" INJECT_LIB_1, ld);
|
string lib = path + ".1.so";
|
||||||
setenv("LD_PRELOAD", env, 1);
|
if (char *ld = getenv("LD_PRELOAD")) {
|
||||||
setenv(INJECT_ENV_1, ld, 1); // Backup original LD_PRELOAD
|
char env[256];
|
||||||
} else {
|
sprintf(env, "%s:%s", ld, lib.data());
|
||||||
setenv("LD_PRELOAD", INJECT_LIB_1, 1);
|
setenv("LD_PRELOAD", env, 1);
|
||||||
setenv(INJECT_ENV_1, "1", 1);
|
} else {
|
||||||
|
setenv("LD_PRELOAD", lib.data(), 1);
|
||||||
|
}
|
||||||
|
setenv(INJECT_ENV_1, "1", 1);
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute real app_process
|
// Execute real app_process
|
||||||
xumount2(buf, MNT_DETACH);
|
char buf[256];
|
||||||
|
xreadlink("/proc/self/exe", buf, sizeof(buf));
|
||||||
|
xumount2("/proc/self/exe", MNT_DETACH);
|
||||||
execve(buf, argv, environ);
|
execve(buf, argv, environ);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The following code runs in magiskd
|
||||||
|
|
||||||
|
static void setup_files(int client, ucred *cred) {
|
||||||
|
LOGD("zygisk: setup files\n");
|
||||||
|
|
||||||
|
char buf[PATH_MAX];
|
||||||
|
sprintf(buf, "/proc/%d/exe", cred->pid);
|
||||||
|
if (realpath(buf, buf) == nullptr) {
|
||||||
|
write_int(client, 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
write_int(client, 0);
|
||||||
|
|
||||||
|
string path = MAGISKTMP + "/zygisk." + basename(buf);
|
||||||
|
cp_afc(buf, (path + ".1.so").data());
|
||||||
|
cp_afc(buf, (path + ".2.so").data());
|
||||||
|
|
||||||
|
write_string(client, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
void zygisk_handler(int client, ucred *cred) {
|
||||||
|
int code = read_int(client);
|
||||||
|
switch (code) {
|
||||||
|
case ZYGISK_SETUP:
|
||||||
|
setup_files(client, cred);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
close(client);
|
||||||
|
}
|
||||||
|
@ -3,11 +3,13 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
|
|
||||||
#define INJECT_LIB_1 "/dev/tmp/magisk.1.so"
|
|
||||||
#define INJECT_LIB_2 "/dev/tmp/magisk.2.so"
|
|
||||||
#define INJECT_ENV_1 "MAGISK_INJ_1"
|
#define INJECT_ENV_1 "MAGISK_INJ_1"
|
||||||
#define INJECT_ENV_2 "MAGISK_INJ_2"
|
#define INJECT_ENV_2 "MAGISK_INJ_2"
|
||||||
|
|
||||||
|
enum : int {
|
||||||
|
ZYGISK_SETUP,
|
||||||
|
};
|
||||||
|
|
||||||
// Unmap all pages matching the name
|
// Unmap all pages matching the name
|
||||||
void unmap_all(const char *name);
|
void unmap_all(const char *name);
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ abort() {
|
|||||||
|
|
||||||
mount_sbin() {
|
mount_sbin() {
|
||||||
mount -t tmpfs -o 'mode=0755' tmpfs /sbin
|
mount -t tmpfs -o 'mode=0755' tmpfs /sbin
|
||||||
$SELINUX && chcon u:object_r:rootfs:s0 /sbin
|
chcon u:object_r:rootfs:s0 /sbin
|
||||||
}
|
}
|
||||||
|
|
||||||
if [ ! -f /system/build.prop ]; then
|
if [ ! -f /system/build.prop ]; then
|
||||||
@ -56,14 +56,14 @@ fi
|
|||||||
pgrep magiskd >/dev/null && pkill -9 magiskd
|
pgrep magiskd >/dev/null && pkill -9 magiskd
|
||||||
[ -f /sbin/magisk ] && umount -l /sbin
|
[ -f /sbin/magisk ] && umount -l /sbin
|
||||||
[ -f /system/bin/magisk ] && umount -l /system/bin
|
[ -f /system/bin/magisk ] && umount -l /system/bin
|
||||||
|
if [ -d /dev/magisk ]; then
|
||||||
|
umount -l /dev/magisk 2>/dev/null
|
||||||
|
rm -rf /dev/magisk
|
||||||
|
fi
|
||||||
|
|
||||||
# SELinux stuffs
|
# SELinux stuffs
|
||||||
SELINUX=false
|
ln -sf ./magiskinit magiskpolicy
|
||||||
[ -e /sys/fs/selinux ] && SELINUX=true
|
./magiskpolicy --live --magisk
|
||||||
if $SELINUX; then
|
|
||||||
ln -sf ./magiskinit magiskpolicy
|
|
||||||
./magiskpolicy --live --magisk
|
|
||||||
fi
|
|
||||||
|
|
||||||
BINDIR=/sbin
|
BINDIR=/sbin
|
||||||
|
|
||||||
@ -99,12 +99,14 @@ elif [ -e /sbin ]; then
|
|||||||
done
|
done
|
||||||
else
|
else
|
||||||
# Android Q+ without sbin, use overlayfs
|
# Android Q+ without sbin, use overlayfs
|
||||||
BINDIR=/system/bin
|
BINDIR=/dev/magisk/upper
|
||||||
rm -rf /dev/magisk
|
mkdir /dev/magisk
|
||||||
mkdir -p /dev/magisk/upper
|
mount -t tmpfs -o 'mode=0755' tmpfs /dev/magisk
|
||||||
|
chcon u:object_r:system_file:s0 /dev/magisk
|
||||||
|
mkdir /dev/magisk/upper
|
||||||
mkdir /dev/magisk/work
|
mkdir /dev/magisk/work
|
||||||
./magisk --clone-attr /system/bin /dev/magisk/upper
|
./magisk --clone-attr /system/bin /dev/magisk/upper
|
||||||
mount -t overlay overlay -olowerdir=/system/bin,upperdir=/dev/magisk/upper,workdir=/dev/magisk/work /system/bin
|
mount -t overlay overlay -o lowerdir=/system/bin,upperdir=/dev/magisk/upper,workdir=/dev/magisk/work /system/bin
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Magisk stuffs
|
# Magisk stuffs
|
||||||
|
Loading…
x
Reference in New Issue
Block a user