mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-11-24 02:25:28 +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 *
|
* 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");
|
LOGI("* Mounting mirrors");
|
||||||
struct vector mounts;
|
struct vector mounts;
|
||||||
vec_init(&mounts);
|
vec_init(&mounts);
|
||||||
@ -451,9 +489,8 @@ static void mount_mirrors() {
|
|||||||
}
|
}
|
||||||
mkdir_p(MIRRDIR "/bin", 0755);
|
mkdir_p(MIRRDIR "/bin", 0755);
|
||||||
bind_mount(DATABIN, MIRRDIR "/bin");
|
bind_mount(DATABIN, MIRRDIR "/bin");
|
||||||
}
|
|
||||||
|
|
||||||
static void link_busybox() {
|
LOGI("* Setting up internal busybox");
|
||||||
mkdir_p(BBPATH, 0755);
|
mkdir_p(BBPATH, 0755);
|
||||||
exec_command_sync(MIRRDIR "/bin/busybox", "--install", "-s", BBPATH, NULL);
|
exec_command_sync(MIRRDIR "/bin/busybox", "--install", "-s", BBPATH, NULL);
|
||||||
symlink(MIRRDIR "/bin/busybox", BBPATH "/busybox");
|
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);
|
exec_command_sync("sh", "-c", "mv /data/magisk/stock_boot* /data", NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Link busybox
|
// Initialize
|
||||||
mount_mirrors();
|
daemon_init();
|
||||||
link_busybox();
|
|
||||||
|
|
||||||
// Merge images
|
// Merge images
|
||||||
if (merge_img("/data/magisk_merge.img", MAINIMG)) {
|
if (merge_img("/data/magisk_merge.img", MAINIMG)) {
|
||||||
|
@ -114,25 +114,7 @@ static void *large_sepol_patch(void *args) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void start_daemon(int client) {
|
void start_daemon() {
|
||||||
// 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();
|
|
||||||
setcon("u:r:su:s0");
|
setcon("u:r:su:s0");
|
||||||
umask(0);
|
umask(0);
|
||||||
int fd = xopen("/dev/null", O_RDWR | O_CLOEXEC);
|
int fd = xopen("/dev/null", O_RDWR | O_CLOEXEC);
|
||||||
@ -166,13 +148,6 @@ void start_daemon(int client) {
|
|||||||
// Unlock all blocks for rw
|
// Unlock all blocks for rw
|
||||||
unlock_blocks();
|
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
|
// Loop forever to listen for requests
|
||||||
while(1) {
|
while(1) {
|
||||||
int *client = xmalloc(sizeof(int));
|
int *client = xmalloc(sizeof(int));
|
||||||
@ -189,11 +164,26 @@ int connect_daemon() {
|
|||||||
struct sockaddr_un sun;
|
struct sockaddr_un sun;
|
||||||
int fd = setup_socket(&sun);
|
int fd = setup_socket(&sun);
|
||||||
if (connect(fd, (struct sockaddr*) &sun, sizeof(sun))) {
|
if (connect(fd, (struct sockaddr*) &sun, sizeof(sun))) {
|
||||||
/* If we cannot access the daemon, we start the daemon
|
// If we cannot access the daemon, we start a daemon in the child process if possible
|
||||||
* since there is no clear entry point when the daemon should be started
|
|
||||||
*/
|
if (getuid() != UID_ROOT || getgid() != UID_ROOT) {
|
||||||
LOGD("client: connect fail, try launching new daemon process\n");
|
fprintf(stderr, "Starting daemon requires root: %s\n", strerror(errno));
|
||||||
start_daemon(fd);
|
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 {
|
do {
|
||||||
// Wait for 10ms
|
// Wait for 10ms
|
||||||
usleep(10);
|
usleep(10);
|
||||||
|
@ -54,11 +54,11 @@ static void usage() {
|
|||||||
" --resizeimg IMG SIZE resize ext4 image. SIZE is interpreted in MB\n"
|
" --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"
|
" --mountimg IMG PATH mount IMG to PATH and prints the loop device\n"
|
||||||
" --umountimg PATH LOOP unmount PATH and delete 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"
|
" --unlock-blocks set BLKROSET flag to OFF for all block devices\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Supported boot stages:\n"
|
"Supported init services:\n"
|
||||||
" post-fs, post-fs-data, service\n"
|
" daemon post-fs, post-fs-data, service\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Supported applets:\n"
|
"Supported applets:\n"
|
||||||
, argv0, argv0);
|
, argv0, argv0);
|
||||||
@ -146,6 +146,9 @@ int main(int argc, char *argv[]) {
|
|||||||
} else if (strcmp(argv[1], "--unlock-blocks") == 0) {
|
} else if (strcmp(argv[1], "--unlock-blocks") == 0) {
|
||||||
unlock_blocks();
|
unlock_blocks();
|
||||||
return 0;
|
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) {
|
} else if (strcmp(argv[1], "--post-fs") == 0) {
|
||||||
int fd = connect_daemon();
|
int fd = connect_daemon();
|
||||||
write_int(fd, POST_FS);
|
write_int(fd, POST_FS);
|
||||||
|
@ -38,7 +38,7 @@ typedef enum {
|
|||||||
|
|
||||||
// daemon.c
|
// daemon.c
|
||||||
|
|
||||||
void start_daemon(int client);
|
void start_daemon();
|
||||||
int connect_daemon();
|
int connect_daemon();
|
||||||
|
|
||||||
// socket_trans.c
|
// socket_trans.c
|
||||||
|
@ -69,42 +69,6 @@ void clean_magisk_props() {
|
|||||||
getprop_all(rm_magisk_prop);
|
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) {
|
int add_list(char *proc) {
|
||||||
if (!hideEnabled) {
|
if (!hideEnabled) {
|
||||||
free(proc);
|
free(proc);
|
||||||
|
@ -12,7 +12,6 @@ void proc_monitor();
|
|||||||
// Utility functions
|
// Utility functions
|
||||||
void manage_selinux();
|
void manage_selinux();
|
||||||
void hide_sensitive_props();
|
void hide_sensitive_props();
|
||||||
void relink_sbin();
|
|
||||||
void clean_magisk_props();
|
void clean_magisk_props();
|
||||||
|
|
||||||
// List managements
|
// List managements
|
||||||
|
@ -90,7 +90,6 @@ static void hide_daemon(int pid) {
|
|||||||
struct vector mount_list;
|
struct vector mount_list;
|
||||||
|
|
||||||
manage_selinux();
|
manage_selinux();
|
||||||
relink_sbin();
|
|
||||||
clean_magisk_props();
|
clean_magisk_props();
|
||||||
|
|
||||||
if (switch_mnt_ns(pid))
|
if (switch_mnt_ns(pid))
|
||||||
|
@ -51,20 +51,13 @@ static char *loopsetup(const char *img) {
|
|||||||
int create_img(const char *img, int size) {
|
int create_img(const char *img, int size) {
|
||||||
unlink(img);
|
unlink(img);
|
||||||
LOGI("Create %s with size %dM\n", img, size);
|
LOGI("Create %s with size %dM\n", img, size);
|
||||||
// Create a temp file with the file contexts
|
int ret;
|
||||||
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);
|
|
||||||
|
|
||||||
char buffer[16];
|
char buffer[16];
|
||||||
snprintf(buffer, sizeof(buffer), "%dM", size);
|
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)
|
if (ret < 0)
|
||||||
return 1;
|
return 1;
|
||||||
unlink(filename);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,32 +167,25 @@ void ps_filter_proc_name(const char *pattern, void (*func)(int)) {
|
|||||||
ps(proc_name_filter);
|
ps(proc_name_filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DEV_BLOCK "/dev/block"
|
|
||||||
|
|
||||||
void unlock_blocks() {
|
void unlock_blocks() {
|
||||||
char path[PATH_MAX];
|
|
||||||
DIR *dir;
|
DIR *dir;
|
||||||
struct dirent *entry;
|
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;
|
return;
|
||||||
|
dir = fdopendir(dev);
|
||||||
|
|
||||||
while((entry = readdir(dir))) {
|
while((entry = readdir(dir))) {
|
||||||
if (entry->d_type == DT_BLK &&
|
if (entry->d_type == DT_BLK) {
|
||||||
strstr(entry->d_name, "ram") == NULL &&
|
if ((fd = openat(dev, entry->d_name, O_RDONLY)) < 0)
|
||||||
strstr(entry->d_name, "loop") == NULL) {
|
|
||||||
snprintf(path, sizeof(path), "%s/%s", DEV_BLOCK, entry->d_name);
|
|
||||||
if ((fd = xopen(path, O_RDONLY)) < 0)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (ioctl(fd, BLKROSET, &OFF) == -1)
|
if (ioctl(fd, BLKROSET, &OFF) == -1)
|
||||||
PLOGE("unlock %s", path);
|
PLOGE("unlock %s", entry->d_name);
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
close(dev);
|
||||||
closedir(dir);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup_sighandlers(void (*handler)(int)) {
|
void setup_sighandlers(void (*handler)(int)) {
|
||||||
|
@ -2,20 +2,24 @@
|
|||||||
|
|
||||||
on post-fs
|
on post-fs
|
||||||
start logd
|
start logd
|
||||||
|
start magisk_daemon
|
||||||
|
wait /dev/.magisk.unblock 1
|
||||||
start magisk_pfs
|
start magisk_pfs
|
||||||
wait /dev/.magisk.unblock 20
|
wait /dev/.magisk.unblock 5
|
||||||
|
|
||||||
on post-fs-data
|
on post-fs-data
|
||||||
rm /dev/.magisk.unblock
|
rm /dev/.magisk.unblock
|
||||||
load_persist_props
|
load_persist_props
|
||||||
start magisk_pfsd
|
start magisk_pfsd
|
||||||
wait /dev/.magisk.unblock 60
|
wait /dev/.magisk.unblock 10
|
||||||
|
|
||||||
on property:magisk.restart_pfsd=1
|
|
||||||
trigger post-fs-data
|
|
||||||
|
|
||||||
# Services
|
# Services
|
||||||
|
|
||||||
|
# Self recoverable service
|
||||||
|
service magisk_daemon /sbin/magisk --daemon
|
||||||
|
user root
|
||||||
|
seclabel u:r:su:s0
|
||||||
|
|
||||||
# launch post-fs script
|
# launch post-fs script
|
||||||
service magisk_pfs /sbin/magisk --post-fs
|
service magisk_pfs /sbin/magisk --post-fs
|
||||||
user root
|
user root
|
||||||
|
Loading…
Reference in New Issue
Block a user