Patch sepolicy at boot time

This commit is contained in:
topjohnwu 2017-09-16 01:32:09 +08:00
parent 9a0b26e0b0
commit a1a2c52409
6 changed files with 127 additions and 33 deletions

View File

@ -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

View File

@ -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];

View File

@ -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" {

View File

@ -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 <sys/sendfile.h>
#include <sys/sysmacros.h>
#include <cil/cil.h>
#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

@ -1 +1 @@
Subproject commit 6600772dca2c02a2528429759aeb7856361bfcb4
Subproject commit 3c6a170138cacb1f817c65181bd6e3ef15cfca9e

View File

@ -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