diff --git a/native/jni/Android.mk b/native/jni/Android.mk index 263317ed9..eecb402d7 100644 --- a/native/jni/Android.mk +++ b/native/jni/Android.mk @@ -16,6 +16,7 @@ COMMON_UTILS := \ utils/list.c \ utils/misc.c \ utils/vector.c \ + utils/selinux.c \ utils/xwrap.c ######################## @@ -27,13 +28,12 @@ ifdef B_MAGISK # magisk main binary include $(CLEAR_VARS) LOCAL_MODULE := magisk -LOCAL_SHARED_LIBRARIES := libsqlite libselinux +LOCAL_SHARED_LIBRARIES := libsqlite LOCAL_STATIC_LIBRARIES := libnanopb libsystemproperties LOCAL_C_INCLUDES := \ jni/include \ jni/magiskpolicy \ $(EXT_PATH)/include \ - $(LIBSELINUX) \ $(LIBNANOPB) \ $(LIBSYSTEMPROPERTIES) diff --git a/native/jni/core/bootstages.c b/native/jni/core/bootstages.c index b1c599842..e718dddbc 100644 --- a/native/jni/core/bootstages.c +++ b/native/jni/core/bootstages.c @@ -13,7 +13,6 @@ #include #include #include -#include #include "magisk.h" #include "db.h" @@ -21,7 +20,7 @@ #include "img.h" #include "daemon.h" #include "resetprop.h" -#include "magiskpolicy.h" +#include "selinux.h" static char buf[PATH_MAX], buf2[PATH_MAX]; static struct vector module_list; diff --git a/native/jni/core/daemon.c b/native/jni/core/daemon.c index 9560b40a6..5677f713e 100644 --- a/native/jni/core/daemon.c +++ b/native/jni/core/daemon.c @@ -13,13 +13,12 @@ #include #include #include -#include #include "magisk.h" #include "utils.h" #include "daemon.h" #include "resetprop.h" -#include "magiskpolicy.h" +#include "selinux.h" int setup_done = 0; int seperate_vendor = 0; diff --git a/native/jni/core/magisk.c b/native/jni/core/magisk.c index 24956bb7f..8587db8c8 100644 --- a/native/jni/core/magisk.c +++ b/native/jni/core/magisk.c @@ -9,6 +9,7 @@ #include "utils.h" #include "magisk.h" #include "daemon.h" +#include "selinux.h" char *argv0; @@ -134,6 +135,8 @@ int magisk_main(int argc, char *argv[]) { int main(int argc, char *argv[]) { umask(0); argv0 = argv[0]; + setup_selinux(); + if (strcmp(basename(argv0), "magisk.bin") == 0) { if (argc >= 2) { // It's calling applets diff --git a/native/jni/core/magiskinit.c b/native/jni/core/magiskinit.c index 1bb8564bf..ba9598af8 100644 --- a/native/jni/core/magiskinit.c +++ b/native/jni/core/magiskinit.c @@ -43,7 +43,6 @@ #include "magiskrc.h" #include "utils.h" -#include "magiskpolicy.h" #include "daemon.h" #include "magisk.h" diff --git a/native/jni/external/Android.mk b/native/jni/external/Android.mk index a63bd7196..25b61d7d4 100644 --- a/native/jni/external/Android.mk +++ b/native/jni/external/Android.mk @@ -8,11 +8,11 @@ LOCAL_SRC_FILES := stubs/sqlite3_stub.c include $(BUILD_SHARED_LIBRARY) # libselinux.so (stub) -include $(CLEAR_VARS) -LOCAL_MODULE:= libselinux -LOCAL_C_INCLUDES := $(LIBSELINUX) -LOCAL_SRC_FILES := stubs/selinux_stub.c -include $(BUILD_SHARED_LIBRARY) +#include $(CLEAR_VARS) +#LOCAL_MODULE:= libselinux +#LOCAL_C_INCLUDES := $(LIBSELINUX) +#LOCAL_SRC_FILES := stubs/selinux_stub.c +#include $(BUILD_SHARED_LIBRARY) # libxz.a include $(CLEAR_VARS) diff --git a/native/jni/include/magisk.h b/native/jni/include/magisk.h index 752c27b85..c39b151ca 100644 --- a/native/jni/include/magisk.h +++ b/native/jni/include/magisk.h @@ -10,14 +10,8 @@ #define MAIN_SOCKET "d30138f2310a9fb9c54a3e0c21f58591" #define LOG_SOCKET "5864cd77f2f8c59b3882e2d35dbf51e4" #define JAVA_PACKAGE_NAME "com.topjohnwu.magisk" - -#ifndef ARG_MAX -#define ARG_MAX 4096 -#endif - #define LOGFILE "/cache/magisk.log" #define UNBLOCKFILE "/dev/.magisk.unblock" -#define TMPSEPOLICY "/dev/.tmp_sepolicy" #define DISABLEFILE "/cache/.disable_magisk" #define MAGISKTMP "/sbin/.core" #define BLOCKDIR MAGISKTMP "/block" @@ -36,13 +30,14 @@ #define MANAGERAPK DATABIN "/magisk.apk" #define MAGISKRC "/init.magisk.rc" - -// selinuxfs paths +// selinux consts #define SELINUX_PATH "/sys/fs/selinux" #define SELINUX_ENFORCE SELINUX_PATH "/enforce" #define SELINUX_POLICY SELINUX_PATH "/policy" #define SELINUX_LOAD SELINUX_PATH "/load" #define SELINUX_CONTEXT SELINUX_PATH "/context" +#define SEPOL_PROC_DOMAIN "magisk" +#define SEPOL_FILE_DOMAIN "magisk_file" #define MAGISKHIDE_PROP "persist.magisk.hide" diff --git a/native/jni/include/selinux.h b/native/jni/include/selinux.h new file mode 100644 index 000000000..f6f8b608f --- /dev/null +++ b/native/jni/include/selinux.h @@ -0,0 +1,12 @@ + +#pragma once + +extern void (*freecon)(char * con); +extern int (*setcon)(const char * con); +extern int (*getfilecon)(const char *path, char ** con); +extern int (*lgetfilecon)(const char *path, char ** con); +extern int (*setfilecon)(const char *path, const char * con); +extern int (*lsetfilecon)(const char *path, const char * con); + +void setup_selinux(); +void restorecon(); diff --git a/native/jni/include/utils.h b/native/jni/include/utils.h index fd9db3086..6f4efc488 100644 --- a/native/jni/include/utils.h +++ b/native/jni/include/utils.h @@ -125,6 +125,8 @@ struct file_attr { char con[128]; }; +int fd_getpath(int fd, char *path, size_t size); +int fd_getpathat(int dirfd, const char *name, char *path, size_t size); int mkdirs(const char *pathname, mode_t mode); void in_order_walk(int dirfd, void (*callback)(int, struct dirent*)); void rm_rf(const char *path); @@ -142,7 +144,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(); + void mmap_ro(const char *filename, void **buf, size_t *size); void mmap_rw(const char *filename, void **buf, size_t *size); void fd_full_read(int fd, void **buf, size_t *size); diff --git a/native/jni/magiskhide/hide_utils.c b/native/jni/magiskhide/hide_utils.c index f9105f372..7caffaa3c 100644 --- a/native/jni/magiskhide/hide_utils.c +++ b/native/jni/magiskhide/hide_utils.c @@ -9,13 +9,13 @@ #include #include #include -#include #include "magisk.h" #include "utils.h" #include "resetprop.h" #include "magiskhide.h" #include "daemon.h" +#include "selinux.h" static char *prop_key[] = { "ro.boot.vbmeta.device_state", "ro.boot.verifiedbootstate", "ro.boot.flash.locked", "ro.boot.veritymode", diff --git a/native/jni/magiskpolicy/magiskpolicy.c b/native/jni/magiskpolicy/magiskpolicy.c index 75221cfa8..0d489d47b 100644 --- a/native/jni/magiskpolicy/magiskpolicy.c +++ b/native/jni/magiskpolicy/magiskpolicy.c @@ -4,6 +4,7 @@ */ #include +#include #include "sepolicy.h" #include "vector.h" diff --git a/native/jni/magiskpolicy/magiskpolicy.h b/native/jni/magiskpolicy/magiskpolicy.h index 6df3ec0f7..a78426d9d 100644 --- a/native/jni/magiskpolicy/magiskpolicy.h +++ b/native/jni/magiskpolicy/magiskpolicy.h @@ -7,8 +7,6 @@ #include #define ALL NULL -#define SEPOL_PROC_DOMAIN "magisk" -#define SEPOL_FILE_DOMAIN "magisk_file" // split policy paths #define PLAT_POLICY_DIR "/system/etc/selinux/" diff --git a/native/jni/magiskpolicy/rules.c b/native/jni/magiskpolicy/rules.c index 67aaca8a7..5f2747e3c 100644 --- a/native/jni/magiskpolicy/rules.c +++ b/native/jni/magiskpolicy/rules.c @@ -1,3 +1,4 @@ +#include "magisk.h" #include "magiskpolicy.h" #include "sepolicy.h" diff --git a/native/jni/su/su.c b/native/jni/su/su.c index 44439e8a1..d35dd30cc 100644 --- a/native/jni/su/su.c +++ b/native/jni/su/su.c @@ -22,12 +22,12 @@ #include #include #include -#include #include "magisk.h" #include "daemon.h" #include "utils.h" #include "su.h" +#include "selinux.h" struct su_context *su_ctx; diff --git a/native/jni/su/su_daemon.c b/native/jni/su/su_daemon.c index 7b5b7c9d8..5242f9584 100644 --- a/native/jni/su/su_daemon.c +++ b/native/jni/su/su_daemon.c @@ -13,7 +13,6 @@ #include #include #include -#include #include "magisk.h" #include "daemon.h" @@ -21,6 +20,7 @@ #include "su.h" #include "pts.h" #include "list.h" +#include "selinux.h" // Constants for the atty bitfield #define ATTY_IN 1 diff --git a/native/jni/utils/file.c b/native/jni/utils/file.c index 0209599f2..086353bfc 100644 --- a/native/jni/utils/file.c +++ b/native/jni/utils/file.c @@ -11,12 +11,9 @@ #include #include -#ifdef SELINUX -#include -#endif - #include "magisk.h" #include "utils.h" +#include "selinux.h" char **excl_list = NULL; @@ -28,16 +25,16 @@ static int is_excl(const char *name) { return 0; } -static int fd_getpath(int fd, char *path, size_t size) { +int fd_getpath(int fd, char *path, size_t size) { snprintf(path, size, "/proc/self/fd/%d", fd); - return xreadlink(path, path, size) == -1; + return xreadlink(path, path, size) == -1; } -static int fd_getpathat(int dirfd, const char *name, char *path, size_t size) { - if (fd_getpath(dirfd, path, size)) - return 1; - snprintf(path, size, "%s/%s", path, name); - return 0; +int fd_getpathat(int dirfd, const char *name, char *path, size_t size) { + if (fd_getpath(dirfd, path, size)) + return 1; + snprintf(path, size, "%s/%s", path, name); + return 0; } int mkdirs(const char *pathname, mode_t mode) { @@ -262,15 +259,11 @@ void link_dir(int src, int dest) { int getattr(const char *path, struct file_attr *a) { if (xlstat(path, &a->st) == -1) return -1; -#ifdef SELINUX - char *con = ""; + char *con; if (lgetfilecon(path, &con) == -1) return -1; strcpy(a->con, con); freecon(con); -#else - a->con[0] = '\0'; -#endif return 0; } @@ -281,16 +274,9 @@ int getattrat(int dirfd, const char *pathname, struct file_attr *a) { } int fgetattr(int fd, struct file_attr *a) { -#ifdef SELINUX char path[PATH_MAX]; fd_getpath(fd, path, sizeof(path)); return getattr(path, a); -#else - if (fstat(fd, &a->st) == -1) - return -1; - a->con[0] = '\0'; - return 0; -#endif } int setattr(const char *path, struct file_attr *a) { @@ -298,10 +284,8 @@ int setattr(const char *path, struct file_attr *a) { return -1; if (chown(path, a->st.st_uid, a->st.st_gid) < 0) return -1; -#ifdef SELINUX if (strlen(a->con) && lsetfilecon(path, a->con) < 0) return -1; -#endif return 0; } @@ -312,17 +296,9 @@ int setattrat(int dirfd, const char *pathname, struct file_attr *a) { } int fsetattr(int fd, struct file_attr *a) { -#ifdef SELINUX char path[PATH_MAX]; fd_getpath(fd, path, sizeof(path)); return setattr(path, a); -#else - if (fchmod(fd, a->st.st_mode & 0777) < 0) - return -1; - if (fchown(fd, a->st.st_uid, a->st.st_gid) < 0) - return -1; - return 0; -#endif } void clone_attr(const char *source, const char *target) { @@ -337,94 +313,6 @@ void fclone_attr(const int sourcefd, const int targetfd) { fsetattr(targetfd, &a); } -#ifdef SELINUX - -#include "magiskpolicy.h" - -#define UNLABEL_CON "u:object_r:unlabeled:s0" -#define SYSTEM_CON "u:object_r:system_file:s0" -#define ADB_CON "u:object_r:adb_data_file:s0" -#define MAGISK_CON "u:object_r:"SEPOL_FILE_DOMAIN":s0" - -static void restore_syscon(int dirfd) { - struct dirent *entry; - DIR *dir; - - char path[PATH_MAX], *con; - - fd_getpath(dirfd, path, sizeof(path)); - size_t len = strlen(path); - getfilecon(path, &con); - if (strlen(con) == 0 || strcmp(con, UNLABEL_CON) == 0) - lsetfilecon(path, SYSTEM_CON); - freecon(con); - - dir = xfdopendir(dirfd); - while ((entry = xreaddir(dir))) { - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) - continue; - if (entry->d_type == DT_DIR) { - int fd = xopenat(dirfd, entry->d_name, O_RDONLY | O_CLOEXEC); - restore_syscon(fd); - close(fd); - } else { - path[len] = '/'; - strcpy(path + len + 1, entry->d_name); - lgetfilecon(path, &con); - if (strlen(con) == 0 || strcmp(con, UNLABEL_CON) == 0) - lsetfilecon(path, SYSTEM_CON); - freecon(con); - path[len] = '\0'; - } - } -} - -static void restore_magiskcon(int dirfd) { - struct dirent *entry; - DIR *dir; - - char path[PATH_MAX]; - - fd_getpath(dirfd, path, sizeof(path)); - size_t len = strlen(path); - lsetfilecon(path, MAGISK_CON); - lchown(path, 0, 0); - - dir = xfdopendir(dirfd); - while ((entry = xreaddir(dir))) { - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) - continue; - if (entry->d_type == DT_DIR) { - int fd = xopenat(dirfd, entry->d_name, O_RDONLY | O_CLOEXEC); - restore_magiskcon(fd); - close(fd); - } else { - path[len] = '/'; - strcpy(path + len + 1, entry->d_name); - lsetfilecon(path, MAGISK_CON); - lchown(path, 0, 0); - path[len] = '\0'; - } - } -} - -void restorecon() { - int fd; - fd = xopen(SELINUX_CONTEXT, O_WRONLY | O_CLOEXEC); - if (write(fd, ADB_CON, sizeof(ADB_CON)) >= 0) { - lsetfilecon(SECURE_DIR, ADB_CON); - } - close(fd); - fd = xopen(MOUNTPOINT, O_RDONLY | O_CLOEXEC); - restore_syscon(fd); - close(fd); - fd = xopen(DATABIN, O_RDONLY | O_CLOEXEC); - restore_magiskcon(fd); - close(fd); -} - -#endif // SELINUX - static void _mmap(int rw, const char *filename, void **buf, size_t *size) { struct stat st; int fd = xopen(filename, (rw ? O_RDWR : O_RDONLY) | O_CLOEXEC); diff --git a/native/jni/utils/selinux.c b/native/jni/utils/selinux.c new file mode 100644 index 000000000..f25a4fd08 --- /dev/null +++ b/native/jni/utils/selinux.c @@ -0,0 +1,125 @@ +#include +#include + +#include "magisk.h" +#include "utils.h" +#include "logging.h" +#include "selinux.h" + +#define UNLABEL_CON "u:object_r:unlabeled:s0" +#define SYSTEM_CON "u:object_r:system_file:s0" +#define ADB_CON "u:object_r:adb_data_file:s0" +#define MAGISK_CON "u:object_r:"SEPOL_FILE_DOMAIN":s0" + +// Stub implementations + +static char *empty_str = ""; + +static void v_s(char *s) {} + +static int i_s(const char *s) { return 0; } + +static int i_ss(const char *s, const char * ss) { return 0; } + +static int i_ssp(const char *s, char ** sp) { + *sp = empty_str; + return 0; +} + +// Function pointers + +void (*freecon)(char * con) = v_s; +int (*setcon)(const char * con) = i_s; +int (*getfilecon)(const char *path, char ** con) = i_ssp; +int (*lgetfilecon)(const char *path, char ** con) = i_ssp; +int (*setfilecon)(const char *path, const char * con) = i_ss; +int (*lsetfilecon)(const char *path, const char * con) = i_ss; + +void setup_selinux() { + void *handle = dlopen("libselinux.so", RTLD_LAZY); + if (handle == NULL) + return; + freecon = dlsym(handle, "freecon"); + setcon = dlsym(handle, "setcon"); + getfilecon = dlsym(handle, "getfilecon"); + lgetfilecon = dlsym(handle, "lgetfilecon"); + setfilecon = dlsym(handle, "setfilecon"); + lsetfilecon = dlsym(handle, "lsetfilecon"); +} + +static void restore_syscon(int dirfd) { + struct dirent *entry; + DIR *dir; + + char path[PATH_MAX], *con; + + fd_getpath(dirfd, path, sizeof(path)); + size_t len = strlen(path); + getfilecon(path, &con); + if (strlen(con) == 0 || strcmp(con, UNLABEL_CON) == 0) + lsetfilecon(path, SYSTEM_CON); + freecon(con); + + dir = xfdopendir(dirfd); + while ((entry = xreaddir(dir))) { + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + continue; + if (entry->d_type == DT_DIR) { + int fd = xopenat(dirfd, entry->d_name, O_RDONLY | O_CLOEXEC); + restore_syscon(fd); + close(fd); + } else { + path[len] = '/'; + strcpy(path + len + 1, entry->d_name); + lgetfilecon(path, &con); + if (strlen(con) == 0 || strcmp(con, UNLABEL_CON) == 0) + lsetfilecon(path, SYSTEM_CON); + freecon(con); + path[len] = '\0'; + } + } +} + +static void restore_magiskcon(int dirfd) { + struct dirent *entry; + DIR *dir; + + char path[PATH_MAX]; + + fd_getpath(dirfd, path, sizeof(path)); + size_t len = strlen(path); + lsetfilecon(path, MAGISK_CON); + lchown(path, 0, 0); + + dir = xfdopendir(dirfd); + while ((entry = xreaddir(dir))) { + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + continue; + if (entry->d_type == DT_DIR) { + int fd = xopenat(dirfd, entry->d_name, O_RDONLY | O_CLOEXEC); + restore_magiskcon(fd); + close(fd); + } else { + path[len] = '/'; + strcpy(path + len + 1, entry->d_name); + lsetfilecon(path, MAGISK_CON); + lchown(path, 0, 0); + path[len] = '\0'; + } + } +} + +void restorecon() { + int fd; + fd = xopen(SELINUX_CONTEXT, O_WRONLY | O_CLOEXEC); + if (write(fd, ADB_CON, sizeof(ADB_CON)) >= 0) { + lsetfilecon(SECURE_DIR, ADB_CON); + } + close(fd); + fd = xopen(MOUNTPOINT, O_RDONLY | O_CLOEXEC); + restore_syscon(fd); + close(fd); + fd = xopen(DATABIN, O_RDONLY | O_CLOEXEC); + restore_magiskcon(fd); + close(fd); +} \ No newline at end of file