mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-11-23 18:15:30 +00:00
Introduce Invincible Mode: Self recover service
This commit is contained in:
parent
60181c4fcb
commit
03c8d716cc
@ -399,7 +399,45 @@ static void simple_mount(const char *path) {
|
||||
* Miscellaneous *
|
||||
*****************/
|
||||
|
||||
static void mount_mirrors() {
|
||||
// A one time setup
|
||||
void daemon_init() {
|
||||
LOGI("* Creating /sbin overlay");
|
||||
DIR *dir;
|
||||
struct dirent *entry;
|
||||
int root, sbin;
|
||||
char target[PATH_MAX], linkpath[PATH_MAX];
|
||||
// Setup links under /sbin
|
||||
xmount(NULL, "/", NULL, MS_REMOUNT, NULL);
|
||||
xmkdir("/root", 0755);
|
||||
xchmod("/root", 0755);
|
||||
root = xopen("/root", O_RDONLY | O_CLOEXEC);
|
||||
sbin = xopen("/sbin", O_RDONLY | O_CLOEXEC);
|
||||
dir = fdopendir(sbin);
|
||||
while((entry = readdir(dir))) {
|
||||
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue;
|
||||
linkat(sbin, entry->d_name, root, entry->d_name, 0);
|
||||
if (strcmp(entry->d_name, "magisk") == 0)
|
||||
unlinkat(sbin, entry->d_name, 0);
|
||||
}
|
||||
close(sbin);
|
||||
mount("tmpfs", "/sbin", "tmpfs", 0, NULL);
|
||||
sbin = xopen("/sbin", O_RDONLY | O_CLOEXEC);
|
||||
fchmod(sbin, 0755);
|
||||
fsetfilecon(sbin, "u:object_r:rootfs:s0");
|
||||
dir = fdopendir(root);
|
||||
while((entry = readdir(dir))) {
|
||||
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue;
|
||||
snprintf(target, sizeof(target), "/root/%s", entry->d_name);
|
||||
snprintf(linkpath, sizeof(linkpath), "/sbin/%s", entry->d_name);
|
||||
symlink(target, linkpath);
|
||||
}
|
||||
for (int i = 0; applet[i]; ++i) {
|
||||
snprintf(linkpath, sizeof(linkpath), "/sbin/%s", applet[i]);
|
||||
symlink("/root/magisk", linkpath);
|
||||
}
|
||||
xmkdir("/magisk", 0755);
|
||||
xmount(NULL, "/", NULL, MS_REMOUNT | MS_RDONLY, NULL);
|
||||
|
||||
LOGI("* Mounting mirrors");
|
||||
struct vector mounts;
|
||||
vec_init(&mounts);
|
||||
@ -451,9 +489,8 @@ static void mount_mirrors() {
|
||||
}
|
||||
mkdir_p(MIRRDIR "/bin", 0755);
|
||||
bind_mount(DATABIN, MIRRDIR "/bin");
|
||||
}
|
||||
|
||||
static void link_busybox() {
|
||||
LOGI("* Setting up internal busybox");
|
||||
mkdir_p(BBPATH, 0755);
|
||||
exec_command_sync(MIRRDIR "/bin/busybox", "--install", "-s", BBPATH, NULL);
|
||||
symlink(MIRRDIR "/bin/busybox", BBPATH "/busybox");
|
||||
@ -595,9 +632,8 @@ void post_fs_data(int client) {
|
||||
exec_command_sync("sh", "-c", "mv /data/magisk/stock_boot* /data", NULL);
|
||||
}
|
||||
|
||||
// Link busybox
|
||||
mount_mirrors();
|
||||
link_busybox();
|
||||
// Initialize
|
||||
daemon_init();
|
||||
|
||||
// Merge images
|
||||
if (merge_img("/data/magisk_merge.img", MAINIMG)) {
|
||||
|
@ -114,25 +114,7 @@ static void *large_sepol_patch(void *args) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void start_daemon(int client) {
|
||||
// Launch the daemon, create new session, set proper context
|
||||
if (getuid() != UID_ROOT || getgid() != UID_ROOT) {
|
||||
fprintf(stderr, "Starting daemon requires root: %s\n", strerror(errno));
|
||||
PLOGE("start daemon");
|
||||
}
|
||||
|
||||
switch (fork()) {
|
||||
case -1:
|
||||
PLOGE("fork");
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
// First close the client, it's useless for us
|
||||
close(client);
|
||||
xsetsid();
|
||||
void start_daemon() {
|
||||
setcon("u:r:su:s0");
|
||||
umask(0);
|
||||
int fd = xopen("/dev/null", O_RDWR | O_CLOEXEC);
|
||||
@ -166,13 +148,6 @@ void start_daemon(int client) {
|
||||
// Unlock all blocks for rw
|
||||
unlock_blocks();
|
||||
|
||||
// Setup links under /sbin
|
||||
xmount(NULL, "/", NULL, MS_REMOUNT, NULL);
|
||||
create_links(NULL, "/sbin");
|
||||
xchmod("/sbin", 0755);
|
||||
xmkdir("/magisk", 0755);
|
||||
xmount(NULL, "/", NULL, MS_REMOUNT | MS_RDONLY, NULL);
|
||||
|
||||
// Loop forever to listen for requests
|
||||
while(1) {
|
||||
int *client = xmalloc(sizeof(int));
|
||||
@ -189,11 +164,26 @@ int connect_daemon() {
|
||||
struct sockaddr_un sun;
|
||||
int fd = setup_socket(&sun);
|
||||
if (connect(fd, (struct sockaddr*) &sun, sizeof(sun))) {
|
||||
/* If we cannot access the daemon, we start the daemon
|
||||
* since there is no clear entry point when the daemon should be started
|
||||
*/
|
||||
LOGD("client: connect fail, try launching new daemon process\n");
|
||||
start_daemon(fd);
|
||||
// If we cannot access the daemon, we start a daemon in the child process if possible
|
||||
|
||||
if (getuid() != UID_ROOT || getgid() != UID_ROOT) {
|
||||
fprintf(stderr, "Starting daemon requires root: %s\n", strerror(errno));
|
||||
PLOGE("start daemon");
|
||||
}
|
||||
|
||||
switch (fork()) {
|
||||
case -1:
|
||||
PLOGE("fork");
|
||||
case 0:
|
||||
LOGD("client: connect fail, try launching new daemon process\n");
|
||||
close(fd);
|
||||
xsetsid();
|
||||
start_daemon();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
do {
|
||||
// Wait for 10ms
|
||||
usleep(10);
|
||||
|
@ -54,11 +54,11 @@ static void usage() {
|
||||
" --resizeimg IMG SIZE resize ext4 image. SIZE is interpreted in MB\n"
|
||||
" --mountimg IMG PATH mount IMG to PATH and prints the loop device\n"
|
||||
" --umountimg PATH LOOP unmount PATH and delete LOOP device\n"
|
||||
" --[boot stage] start boot stage service\n"
|
||||
" --[init service] start init service\n"
|
||||
" --unlock-blocks set BLKROSET flag to OFF for all block devices\n"
|
||||
"\n"
|
||||
"Supported boot stages:\n"
|
||||
" post-fs, post-fs-data, service\n"
|
||||
"Supported init services:\n"
|
||||
" daemon post-fs, post-fs-data, service\n"
|
||||
"\n"
|
||||
"Supported applets:\n"
|
||||
, argv0, argv0);
|
||||
@ -146,6 +146,9 @@ int main(int argc, char *argv[]) {
|
||||
} else if (strcmp(argv[1], "--unlock-blocks") == 0) {
|
||||
unlock_blocks();
|
||||
return 0;
|
||||
} else if (strcmp(argv[1], "--daemon") == 0) {
|
||||
// Start daemon, this process won't return
|
||||
start_daemon();
|
||||
} else if (strcmp(argv[1], "--post-fs") == 0) {
|
||||
int fd = connect_daemon();
|
||||
write_int(fd, POST_FS);
|
||||
|
@ -38,7 +38,7 @@ typedef enum {
|
||||
|
||||
// daemon.c
|
||||
|
||||
void start_daemon(int client);
|
||||
void start_daemon();
|
||||
int connect_daemon();
|
||||
|
||||
// socket_trans.c
|
||||
|
@ -69,42 +69,6 @@ void clean_magisk_props() {
|
||||
getprop_all(rm_magisk_prop);
|
||||
}
|
||||
|
||||
void relink_sbin() {
|
||||
struct stat st;
|
||||
if (stat("/sbin_orig", &st) == -1 && errno == ENOENT) {
|
||||
// Re-link all binaries and bind mount
|
||||
DIR *dir;
|
||||
struct dirent *entry;
|
||||
char from[PATH_MAX], to[PATH_MAX];
|
||||
|
||||
LOGI("hide_utils: Re-linking /sbin\n");
|
||||
|
||||
xmount(NULL, "/", NULL, MS_REMOUNT, NULL);
|
||||
xrename("/sbin", "/sbin_orig");
|
||||
xmkdir("/sbin", 0755);
|
||||
xchmod("/sbin", 0755);
|
||||
xmount(NULL, "/", NULL, MS_REMOUNT | MS_RDONLY, NULL);
|
||||
xmkdir("/dev/sbin_bind", 0755);
|
||||
xchmod("/dev/sbin_bind", 0755);
|
||||
dir = xopendir("/sbin_orig");
|
||||
|
||||
while ((entry = xreaddir(dir))) {
|
||||
if (strcmp(entry->d_name, "..") == 0)
|
||||
continue;
|
||||
snprintf(from, sizeof(from), "/sbin_orig/%s", entry->d_name);
|
||||
if (entry->d_type == DT_LNK)
|
||||
xreadlink(from, from, sizeof(from));
|
||||
snprintf(to, sizeof(to), "/dev/sbin_bind/%s", entry->d_name);
|
||||
symlink(from, to);
|
||||
lsetfilecon(to, "u:object_r:rootfs:s0");
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
|
||||
xmount("/dev/sbin_bind", "/sbin", NULL, MS_BIND, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
int add_list(char *proc) {
|
||||
if (!hideEnabled) {
|
||||
free(proc);
|
||||
|
@ -12,7 +12,6 @@ void proc_monitor();
|
||||
// Utility functions
|
||||
void manage_selinux();
|
||||
void hide_sensitive_props();
|
||||
void relink_sbin();
|
||||
void clean_magisk_props();
|
||||
|
||||
// List managements
|
||||
|
@ -90,7 +90,6 @@ static void hide_daemon(int pid) {
|
||||
struct vector mount_list;
|
||||
|
||||
manage_selinux();
|
||||
relink_sbin();
|
||||
clean_magisk_props();
|
||||
|
||||
if (switch_mnt_ns(pid))
|
||||
|
@ -51,20 +51,13 @@ static char *loopsetup(const char *img) {
|
||||
int create_img(const char *img, int size) {
|
||||
unlink(img);
|
||||
LOGI("Create %s with size %dM\n", img, size);
|
||||
// Create a temp file with the file contexts
|
||||
char file_contexts[] = "/magisk(/.*)? u:object_r:system_file:s0\n";
|
||||
// If not root, attempt to create in current diretory
|
||||
char *filename = getuid() == UID_ROOT ? "/dev/file_contexts_image" : "file_contexts_image";
|
||||
int ret, fd = xopen(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||
xwrite(fd, file_contexts, sizeof(file_contexts));
|
||||
close(fd);
|
||||
int ret;
|
||||
|
||||
char buffer[16];
|
||||
snprintf(buffer, sizeof(buffer), "%dM", size);
|
||||
ret = exec_command_sync("make_ext4fs", "-l", buffer, "-a", "/magisk", "-S", filename, img, NULL);
|
||||
ret = exec_command_sync("make_ext4fs", "-l", buffer, img, NULL);
|
||||
if (ret < 0)
|
||||
return 1;
|
||||
unlink(filename);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -167,32 +167,25 @@ void ps_filter_proc_name(const char *pattern, void (*func)(int)) {
|
||||
ps(proc_name_filter);
|
||||
}
|
||||
|
||||
#define DEV_BLOCK "/dev/block"
|
||||
|
||||
void unlock_blocks() {
|
||||
char path[PATH_MAX];
|
||||
DIR *dir;
|
||||
struct dirent *entry;
|
||||
int fd, OFF = 0;
|
||||
int fd, dev, OFF = 0;
|
||||
|
||||
if (!(dir = xopendir(DEV_BLOCK)))
|
||||
if ((dev = xopen("/dev/block", O_RDONLY | O_CLOEXEC)) < 0)
|
||||
return;
|
||||
dir = fdopendir(dev);
|
||||
|
||||
while((entry = readdir(dir))) {
|
||||
if (entry->d_type == DT_BLK &&
|
||||
strstr(entry->d_name, "ram") == NULL &&
|
||||
strstr(entry->d_name, "loop") == NULL) {
|
||||
snprintf(path, sizeof(path), "%s/%s", DEV_BLOCK, entry->d_name);
|
||||
if ((fd = xopen(path, O_RDONLY)) < 0)
|
||||
if (entry->d_type == DT_BLK) {
|
||||
if ((fd = openat(dev, entry->d_name, O_RDONLY)) < 0)
|
||||
continue;
|
||||
|
||||
if (ioctl(fd, BLKROSET, &OFF) == -1)
|
||||
PLOGE("unlock %s", path);
|
||||
PLOGE("unlock %s", entry->d_name);
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
close(dev);
|
||||
}
|
||||
|
||||
void setup_sighandlers(void (*handler)(int)) {
|
||||
|
@ -2,20 +2,24 @@
|
||||
|
||||
on post-fs
|
||||
start logd
|
||||
start magisk_daemon
|
||||
wait /dev/.magisk.unblock 1
|
||||
start magisk_pfs
|
||||
wait /dev/.magisk.unblock 20
|
||||
wait /dev/.magisk.unblock 5
|
||||
|
||||
on post-fs-data
|
||||
rm /dev/.magisk.unblock
|
||||
load_persist_props
|
||||
start magisk_pfsd
|
||||
wait /dev/.magisk.unblock 60
|
||||
|
||||
on property:magisk.restart_pfsd=1
|
||||
trigger post-fs-data
|
||||
wait /dev/.magisk.unblock 10
|
||||
|
||||
# Services
|
||||
|
||||
# Self recoverable service
|
||||
service magisk_daemon /sbin/magisk --daemon
|
||||
user root
|
||||
seclabel u:r:su:s0
|
||||
|
||||
# launch post-fs script
|
||||
service magisk_pfs /sbin/magisk --post-fs
|
||||
user root
|
||||
|
Loading…
Reference in New Issue
Block a user