From fe4b3df7e9e341c76cc130d82dfb5d2965195767 Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Thu, 12 Oct 2017 03:39:39 +0800 Subject: [PATCH] Fix selinux context on Magisk files --- jni/daemon/bootstages.c | 27 +++++++++++++++++++-------- jni/daemon/magisk.c | 4 ++++ jni/include/daemon.h | 1 + jni/include/utils.h | 1 + jni/utils/file.c | 32 ++++++++++++++++++++++++++++++++ 5 files changed, 57 insertions(+), 8 deletions(-) diff --git a/jni/daemon/bootstages.c b/jni/daemon/bootstages.c index d2c8d3ca1..dcb3c748d 100644 --- a/jni/daemon/bootstages.c +++ b/jni/daemon/bootstages.c @@ -396,7 +396,7 @@ static void simple_mount(const char *path) { *****************/ // A one time setup -void daemon_init() { +static void daemon_init() { LOGI("* Creating /sbin overlay"); DIR *dir; struct dirent *entry; @@ -493,6 +493,12 @@ void daemon_init() { } static int prepare_img() { + // First merge images + if (merge_img("/data/magisk_merge.img", MAINIMG)) { + LOGE("Image merge %s -> %s failed!\n", "/data/magisk_merge.img", MAINIMG); + return 1; + } + if (access(MAINIMG, F_OK) == -1) { if (create_img(MAINIMG, 64)) return 1; @@ -544,9 +550,20 @@ static int prepare_img() { magiskloop = mount_image(MAINIMG, MOUNTPOINT); free(magiskloop); + // Fix file seliux contexts + fix_filecon(); return 0; } +void fix_filecon() { + int dirfd = xopen(MOUNTPOINT, O_RDONLY | O_CLOEXEC); + restorecon(dirfd, 0); + close(dirfd); + dirfd = xopen(DATABIN, O_RDONLY | O_CLOEXEC); + restorecon(dirfd, 1); + close(dirfd); +} + /**************** * Entry points * ****************/ @@ -618,12 +635,6 @@ void post_fs_data(int client) { // Initialize daemon_init(); - // Merge images - if (merge_img("/data/magisk_merge.img", MAINIMG)) { - LOGE("Image merge %s -> %s failed!\n", "/data/magisk_merge.img", MAINIMG); - goto unblock; - } - // uninstaller if (access(UNINSTALLER, F_OK) == 0) { close(open(UNBLOCKFILE, O_RDONLY | O_CREAT)); @@ -632,7 +643,7 @@ void post_fs_data(int client) { return; } - // Trim, mount magisk.img, which will also travel through the modules + // Merge, trim, mount magisk.img, which will also travel through the modules // After this, it will create the module list if (prepare_img()) goto core_only; // Mounting fails, we can only do core only stuffs diff --git a/jni/daemon/magisk.c b/jni/daemon/magisk.c index 3e27c1de4..e33dfa685 100644 --- a/jni/daemon/magisk.c +++ b/jni/daemon/magisk.c @@ -56,6 +56,7 @@ static void usage() { " --umountimg PATH LOOP unmount PATH and delete LOOP device\n" " --[init service] start init service\n" " --unlock-blocks set BLKROSET flag to OFF for all block devices\n" + " --restorecon fix selinux context on Magisk files and folders\n" "\n" "Supported init services:\n" " daemon post-fs, post-fs-data, service\n" @@ -146,6 +147,9 @@ int main(int argc, char *argv[]) { } else if (strcmp(argv[1], "--unlock-blocks") == 0) { unlock_blocks(); return 0; + } else if (strcmp(argv[1], "--restorecon") == 0) { + fix_filecon(); + return 0; } else if (strcmp(argv[1], "--daemon") == 0) { // Start daemon, this process won't return start_daemon(); diff --git a/jni/include/daemon.h b/jni/include/daemon.h index 74a21b8de..ab5cea0d3 100644 --- a/jni/include/daemon.h +++ b/jni/include/daemon.h @@ -59,6 +59,7 @@ void write_string(int fd, const char* val); void post_fs(int client); void post_fs_data(int client); void late_start(int client); +void fix_filecon(); /************** * MagiskHide * diff --git a/jni/include/utils.h b/jni/include/utils.h index eacb28aa9..b79eed609 100644 --- a/jni/include/utils.h +++ b/jni/include/utils.h @@ -110,6 +110,7 @@ int setattrat(int dirfd, const char *pathname, struct file_attr *a); int fsetattr(int fd, struct file_attr *a); void fclone_attr(const int sourcefd, const int targetfd); void clone_attr(const char *source, const char *target); +void restorecon(int dirfd, int force); // img.c diff --git a/jni/utils/file.c b/jni/utils/file.c index 163abb5ae..88d573f1d 100644 --- a/jni/utils/file.c +++ b/jni/utils/file.c @@ -270,3 +270,35 @@ void fclone_attr(const int sourcefd, const int targetfd) { fgetattr(sourcefd, &a); fsetattr(targetfd, &a); } + +#define UNLABEL_CON "u:object_r:unlabeled:s0" +#define SYSTEM_CON "u:object_r:system_file:s0" + +void restorecon(int dirfd, int force) { + struct dirent *entry; + DIR *dir; + int fd; + char *con; + + fgetfilecon(dirfd, &con); + if (force || strlen(con) == 0 || strcmp(con, UNLABEL_CON) == 0) + fsetfilecon(dirfd, SYSTEM_CON); + freecon(con); + + dir = fdopendir(dirfd); + while ((entry = readdir(dir))) { + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + continue; + if (entry->d_type == DT_DIR) { + fd = openat(dirfd, entry->d_name, O_RDONLY | O_CLOEXEC); + restorecon(fd, force); + } else { + fd = openat(dirfd, entry->d_name, O_PATH | O_NOFOLLOW | O_CLOEXEC); + fgetfilecon(fd, &con); + if (force || strlen(con) == 0 || strcmp(con, UNLABEL_CON) == 0) + fsetfilecon(fd, SYSTEM_CON); + freecon(con); + } + close(fd); + } +}