From a1a2c52409eb1fd88a7ba9221121c82ef2c8caff Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Sat, 16 Sep 2017 01:32:09 +0800 Subject: [PATCH] Patch sepolicy at boot time --- jni/Android.mk | 9 ++-- jni/daemon/magisk.c | 4 +- jni/include/magisk.h | 1 - jni/magiskinit.c | 116 +++++++++++++++++++++++++++++++++++++++++- jni/magiskpolicy | 2 +- scripts/boot_patch.sh | 28 ++-------- 6 files changed, 127 insertions(+), 33 deletions(-) diff --git a/jni/Android.mk b/jni/Android.mk index fbcb71591..41c0f66c5 100644 --- a/jni/Android.mk +++ b/jni/Android.mk @@ -46,7 +46,6 @@ LOCAL_SRC_FILES := \ magiskpolicy/magiskpolicy.c \ magiskpolicy/rules.c \ magiskpolicy/sepolicy.c \ - magiskpolicy/secilc.c \ magiskpolicy/api.c \ resetprop/resetprop.cpp \ resetprop/system_properties.cpp \ @@ -93,11 +92,15 @@ include $(BUILD_EXECUTABLE) ifeq ($(TARGET_ARCH_ABI), arm64-v8a) include $(CLEAR_VARS) LOCAL_MODULE := magiskinit -LOCAL_C_INCLUDES := jni/include +LOCAL_STATIC_LIBRARIES := libsepol +LOCAL_C_INCLUDES := jni/include $(LIBSEPOL) LOCAL_SRC_FILES := \ magiskinit.c \ magiskboot/boot_utils.c \ - utils/xwrap.c + utils/xwrap.c \ + magiskpolicy/rules.c \ + magiskpolicy/sepolicy.c \ + magiskpolicy/api.c LOCAL_LDFLAGS := -static include $(BUILD_EXECUTABLE) endif diff --git a/jni/daemon/magisk.c b/jni/daemon/magisk.c index 5ff2356f1..f087deea2 100644 --- a/jni/daemon/magisk.c +++ b/jni/daemon/magisk.c @@ -12,10 +12,10 @@ char *argv0; char *applet[] = - { "su", "resetprop", "magisksecilc", "magiskpolicy", "supolicy", "sepolicy-inject", "magiskhide", NULL }; + { "su", "resetprop", "magiskpolicy", "supolicy", "sepolicy-inject", "magiskhide", NULL }; int (*applet_main[]) (int, char *[]) = - { su_client_main, resetprop_main, secilc_main, magiskpolicy_main, magiskpolicy_main, magiskpolicy_main, magiskhide_main, NULL }; + { su_client_main, resetprop_main, magiskpolicy_main, magiskpolicy_main, magiskpolicy_main, magiskhide_main, NULL }; int create_links(const char *bin, const char *path) { char self[PATH_MAX], linkpath[PATH_MAX]; diff --git a/jni/include/magisk.h b/jni/include/magisk.h index 4f4465ba6..5ba82bfda 100644 --- a/jni/include/magisk.h +++ b/jni/include/magisk.h @@ -53,7 +53,6 @@ int create_links(const char *bin, const char *path); int magiskhide_main(int argc, char *argv[]); int magiskpolicy_main(int argc, char *argv[]); int su_client_main(int argc, char *argv[]); -int secilc_main(int argc, char *argv[]); #ifdef __cplusplus extern "C" { diff --git a/jni/magiskinit.c b/jni/magiskinit.c index 367f90599..35f7948a6 100644 --- a/jni/magiskinit.c +++ b/jni/magiskinit.c @@ -5,7 +5,8 @@ * Magiskinit will mount sysfs, parse through uevent files to make the system block device, * then it'll mount the system partition and clone rootfs except files under /system. * Folders placed in "overlay" will then be overlayed to the root. - * Lastly before giving control back to the real init, it'll patch the root files to load Magisk. + * Lastly, before giving control back to the real init, it'll patch the root files, + * extract (or compile if needed) sepolicy and patch it to load Magisk. */ @@ -22,6 +23,10 @@ #include #include +#include + +#include "magiskpolicy.h" + struct cmdline { int skip_initramfs; char slot[3]; @@ -35,6 +40,8 @@ struct device { char path[64]; }; +extern policydb_t *policydb; + extern void mmap_ro(const char *filename, void **buf, size_t *size); extern void mmap_rw(const char *filename, void **buf, size_t *size); extern void *patch_init_rc(char *data, uint32_t *size); @@ -244,6 +251,107 @@ static void patch_ramdisk() { free(init_rc); } +static int strend(const char *s1, const char *s2) { + int l1 = strlen(s1); + int l2 = strlen(s2); + return strcmp(s1 + l1 - l2, s2); +} + +static void patch_sepolicy() { + DIR *dir; + struct dirent *entry; + char *sepolicy = NULL, path[128]; + if (access("/system_root/sepolicy", R_OK) == 0) + sepolicy = "/system_root/sepolicy"; + if (sepolicy == NULL && access("/vendor/etc/selinux/precompiled_sepolicy", R_OK) == 0) { + void *sys_sha = NULL, *ven_sha = NULL; + size_t sys_size = 0, ven_size = 0; + dir = opendir("/vendor/etc/selinux"); + while ((entry = readdir(dir))) { + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + continue; + if (strend(entry->d_name, ".sha256") == 0) { + snprintf(path, sizeof(path), "/vendor/etc/selinux/%s", entry->d_name); + mmap_ro(path, &ven_sha, &ven_size); + break; + } + } + closedir(dir); + dir = opendir("/system/etc/selinux"); + while ((entry = readdir(dir))) { + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + continue; + if (strend(entry->d_name, ".sha256") == 0) { + snprintf(path, sizeof(path), "/system/etc/selinux/%s", entry->d_name); + mmap_ro(path, &sys_sha, &sys_size); + break; + } + } + closedir(dir); + if (sys_size == ven_size && memcmp(sys_sha, ven_sha, sys_size) == 0) + sepolicy = "/vendor/etc/selinux/precompiled_sepolicy"; + munmap(sys_sha, sys_size); + munmap(ven_sha, ven_size); + } + + if (sepolicy) { + load_policydb(sepolicy); + } else { + // Compile cil + struct cil_db *db = NULL; + sepol_policydb_t *pdb = NULL; + void *addr; + size_t size; + + cil_db_init(&db); + cil_set_mls(db, 1); + cil_set_target_platform(db, SEPOL_TARGET_SELINUX); + cil_set_policy_version(db, POLICYDB_VERSION_XPERMS_IOCTL); + cil_set_attrs_expand_generated(db, 0); + + mmap_ro("/system/etc/selinux/plat_sepolicy.cil", &addr, &size); + cil_add_file(db, "/system/etc/selinux/plat_sepolicy.cil", addr, size); + munmap(addr, size); + + dir = opendir("/system/etc/selinux/mapping"); + while ((entry = readdir(dir))) { + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + continue; + if (strend(entry->d_name, ".cil") == 0) { + snprintf(path, sizeof(path), "/system/etc/selinux/mapping/%s", entry->d_name); + mmap_ro(path, &addr, &size); + cil_add_file(db, path, addr, size); + munmap(addr, size); + } + } + closedir(dir); + + dir = opendir("/vendor/etc/selinux"); + while ((entry = readdir(dir))) { + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + continue; + if (strend(entry->d_name, ".cil") == 0) { + snprintf(path, sizeof(path), "/vendor/etc/selinux/%s", entry->d_name); + mmap_ro(path, &addr, &size); + cil_add_file(db, path, addr, size); + munmap(addr, size); + } + } + closedir(dir); + + cil_compile(db); + cil_build_policydb(db, &pdb); + cil_db_destroy(&db); + + policydb = &pdb->p; + } + + // Magisk patches + sepol_min_rules(); + dump_policydb("/sepolicy"); + destroy_policydb(); +} + int main(int argc, char *argv[]) { umask(0); @@ -272,12 +380,18 @@ int main(int argc, char *argv[]) { if (overlay > 0) mv_dir(overlay, root); + snprintf(partname, sizeof(partname), "vendor%s", cmd.slot); + setup_block(&dev, partname); + mount(dev.path, "/vendor", "ext4", MS_RDONLY, NULL); + patch_ramdisk(); + patch_sepolicy(); close(root); close(system_root); close(overlay); rmdir("/overlay"); + umount("/vendor"); } else { // Recovery mode // Revert original init binary diff --git a/jni/magiskpolicy b/jni/magiskpolicy index 6600772dc..3c6a17013 160000 --- a/jni/magiskpolicy +++ b/jni/magiskpolicy @@ -1 +1 @@ -Subproject commit 6600772dca2c02a2528429759aeb7856361bfcb4 +Subproject commit 3c6a170138cacb1f817c65181bd6e3ef15cfca9e diff --git a/scripts/boot_patch.sh b/scripts/boot_patch.sh index c49000707..8c902bca4 100644 --- a/scripts/boot_patch.sh +++ b/scripts/boot_patch.sh @@ -213,26 +213,6 @@ if [ ! -z $SHA1 ]; then fi if $SKIP_INITRAMFS; then - # First check precompiled ones - [ -f /system_root/sepolicy ] && cp /system_root/sepolicy sepolicy - if [ ! -f sepolicy -a -f /vendor/etc/selinux/precompiled_sepolicy ]; then - # Check SHA256 - SYSTEMSHA256=`find /system/etc/selinux -name '*.sha256' -exec cat {} \; 2>/dev/null` - VENDORSHA256=`find /vendor/etc/selinux -name '*.sha256' -exec cat {} \; 2>/dev/null` - [ "$SYSTEMSHA256" = "$VENDORSHA256" ] && cp /vendor/etc/selinux/precompiled_sepolicy sepolicy - fi - if [ ! -f sepolicy ]; then - ui_print_wrap "- Compiling split cil policies" - # Compile the split policies - POLICY_VER=`cat /sys/fs/selinux/policyvers` - PLAT_CIL=/system/etc/selinux/plat_sepolicy.cil - NONPLAT_CIL=`find /vendor/etc/selinux -name '*.cil' 2>/dev/null` - VENDOR_PLAT_VER=`cat /vendor/etc/selinux/plat_sepolicy_vers.txt` - MAPPING_CIL=/system/etc/selinux/mapping/${VENDOR_PLAT_VER}.cil - ./magisk magisksecilc -M true -c $POLICY_VER -o sepolicy -f /dev/null $PLAT_CIL $NONPLAT_CIL $MAPPING_CIL - fi - [ -f sepolicy ] || abort_wrap "! Cannot get sepolicy" - cpio_add 750 init ./magiskinit cpio_mkdir 000 overlay cpio_add 750 overlay/init.magisk.rc init.magisk.rc @@ -242,6 +222,9 @@ else ./magiskboot --cpio-patch ramdisk.cpio $KEEPVERITY $KEEPFORCEENCRYPT cpio_extract sepolicy sepolicy + ./magisk magiskpolicy --load sepolicy --save sepolicy --minimal + cpio_add 644 sepolicy sepolicy + rm -f sepolicy cpio_add 750 init.magisk.rc init.magisk.rc cpio_add 755 sbin/magisk magisk @@ -249,11 +232,6 @@ fi mv init.magisk.rc.bak init.magisk.rc 2>/dev/null -# sepolicy patches -./magisk magiskpolicy --load sepolicy --save sepolicy --minimal -$SKIP_INITRAMFS && cpio_add 644 overlay/sepolicy sepolicy || cpio_add 644 sepolicy sepolicy -rm -f sepolicy - # Create ramdisk backups ./magiskboot --cpio-backup ramdisk.cpio ramdisk.cpio.orig