From 91818cfa1a5043aec71ddc1caef708eab7ac094f Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Sat, 21 Jul 2018 05:12:22 +0800 Subject: [PATCH] Support compiling split cils via magiskpolicy CLI --- native/jni/core/magiskinit.c | 71 +-------------------- native/jni/include/magisk.h | 8 --- native/jni/include/utils.h | 1 + native/jni/magiskpolicy/magiskpolicy.c | 74 +++++++++++++--------- native/jni/magiskpolicy/magiskpolicy.h | 9 +++ native/jni/magiskpolicy/sepolicy.c | 87 ++++++++++++++++++++++++++ native/jni/magiskpolicy/sepolicy.h | 25 +------- native/jni/utils/misc.c | 6 ++ 8 files changed, 151 insertions(+), 130 deletions(-) diff --git a/native/jni/core/magiskinit.c b/native/jni/core/magiskinit.c index 820dab8c8..de4eaa997 100644 --- a/native/jni/core/magiskinit.c +++ b/native/jni/core/magiskinit.c @@ -37,7 +37,6 @@ #include #include -#include #include "binaries_xz.h" #include "binaries_arch_xz.h" @@ -50,14 +49,13 @@ #include "magisk.h" #ifdef MAGISK_DEBUG -#define VLOG(fmt, ...) printf(fmt, __VA_ARGS__) +#define VLOG(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__) #else #define VLOG(fmt, ...) #endif #define DEFAULT_DT_DIR "/proc/device-tree/firmware/android" -extern policydb_t *policydb; int (*init_applet_main[]) (int, char *[]) = { magiskpolicy_main, magiskpolicy_main, NULL }; struct cmdline { @@ -149,12 +147,6 @@ static int setup_block(struct device *dev, const char *partname) { return 0; } -static int strend(const char *s1, const char *s2) { - size_t l1 = strlen(s1); - size_t l2 = strlen(s2); - return strcmp(s1 + l1 - l2, s2); -} - static int read_fstab_dt(const struct cmdline *cmd, const char *mnt_point, char *partname) { char buf[128]; struct stat st; @@ -175,65 +167,6 @@ static int read_fstab_dt(const struct cmdline *cmd, const char *mnt_point, char return 1; } -static int compile_cil() { - DIR *dir; - struct dirent *entry; - char path[128]; - - 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_multiple_decls(db, 1); - cil_set_disable_neverallow(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); - - // plat - mmap_ro(SPLIT_PLAT_CIL, &addr, &size); - VLOG("cil_add[%s]\n", SPLIT_PLAT_CIL); - cil_add_file(db, SPLIT_PLAT_CIL, addr, size); - munmap(addr, size); - - // mapping - char plat[10]; - int fd = open(SPLIT_NONPLAT_VER, O_RDONLY | O_CLOEXEC); - plat[read(fd, plat, sizeof(plat)) - 1] = '\0'; - sprintf(path, SPLIT_PLAT_MAPPING, plat); - mmap_ro(path, &addr, &size); - VLOG("cil_add[%s]\n", path); - cil_add_file(db, path, addr, size); - munmap(addr, size); - close(fd); - - // nonplat - dir = opendir(NONPLAT_POLICY_DIR); - while ((entry = readdir(dir))) { - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) - continue; - if (strend(entry->d_name, ".cil") == 0) { - sprintf(path, NONPLAT_POLICY_DIR "%s", entry->d_name); - mmap_ro(path, &addr, &size); - VLOG("cil_add[%s]\n", path); - 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; - - return 0; -} - static int verify_precompiled() { DIR *dir; struct dirent *entry; @@ -279,7 +212,7 @@ static int patch_sepolicy() { load_policydb(SPLIT_PRECOMPILE); } else if (access(SPLIT_PLAT_CIL, R_OK) == 0) { init_patch = 1; - compile_cil(); + compile_split_cil(); } else if (access("/sepolicy", R_OK) == 0) { load_policydb("/sepolicy"); } else { diff --git a/native/jni/include/magisk.h b/native/jni/include/magisk.h index 10e418f18..f44431be2 100644 --- a/native/jni/include/magisk.h +++ b/native/jni/include/magisk.h @@ -42,14 +42,6 @@ #define SELINUX_LOAD SELINUX_PATH "/load" #define SELINUX_CONTEXT SELINUX_PATH "/context" -// split policy paths -#define PLAT_POLICY_DIR "/system/etc/selinux/" -#define NONPLAT_POLICY_DIR "/vendor/etc/selinux/" -#define SPLIT_PLAT_CIL PLAT_POLICY_DIR "plat_sepolicy.cil" -#define SPLIT_PLAT_MAPPING PLAT_POLICY_DIR "mapping/%s.cil" -#define SPLIT_PRECOMPILE NONPLAT_POLICY_DIR "precompiled_sepolicy" -#define SPLIT_NONPLAT_VER NONPLAT_POLICY_DIR "plat_sepolicy_vers.txt" - #define MAGISKHIDE_PROP "persist.magisk.hide" extern char *argv0; /* For changing process name */ diff --git a/native/jni/include/utils.h b/native/jni/include/utils.h index 07d5f2dfe..8135d3a24 100644 --- a/native/jni/include/utils.h +++ b/native/jni/include/utils.h @@ -107,6 +107,7 @@ int switch_mnt_ns(int pid); int fork_dont_care(); void wait_till_exists(const char *target); void gen_rand_str(char *buf, int len); +int strend(const char *s1, const char *s2); // file.c diff --git a/native/jni/magiskpolicy/magiskpolicy.c b/native/jni/magiskpolicy/magiskpolicy.c index f5fdbd761..621f8fb2c 100644 --- a/native/jni/magiskpolicy/magiskpolicy.c +++ b/native/jni/magiskpolicy/magiskpolicy.c @@ -3,8 +3,11 @@ * Includes all the parsing logic for the policy statements */ -#include "magiskpolicy.h" +#include + #include "sepolicy.h" +#include "vector.h" +#include "magiskpolicy.h" #include "magisk.h" static int syntax_err = 0; @@ -59,14 +62,20 @@ static void statements() { static void usage(char *arg0) { fprintf(stderr, "MagiskPolicy v" xstr(MAGISK_VERSION) "(" xstr(MAGISK_VER_CODE) ") (by topjohnwu)\n\n" - "Usage: %s [--options...] [policystatements...]\n\n" + "Usage: %s [--options...] [policy statements...]\n" + "\n" "Options:\n" - " --live directly apply patched policy live\n" - " --magisk built-in rules for a Magisk selinux environment\n" - " --load FILE load policies from \n" - " --save FILE save policies to \n\n" - "If no input file is specified, it will load from current policies\n" - "If neither --live nor --save is specified, nothing will happen\n\n" + " --live directly apply sepolicy live\n" + " --magisk inject built-in rules for a Magisk\n" + " selinux environment\n" + " --load FILE load policies from FILE\n" + " --compile-split compile and load split cil policies\n" + " from system and vendor just like init\n" + " --save FILE save policies to FILE\n" + "\n" + "If neither --load or --compile-split is specified, it will load\n" + "from current live policies (" SELINUX_POLICY ")\n" + "\n" , arg0); statements(); exit(1); @@ -381,8 +390,8 @@ static void syntax_error_msg() { } int magiskpolicy_main(int argc, char *argv[]) { - char *infile = NULL, *outfile = NULL, *tok, *saveptr; - int live = 0, magisk = 0; + char *outfile = NULL, *tok, *saveptr; + int magisk = 0; struct vector rules; vec_init(&rules); @@ -390,31 +399,39 @@ int magiskpolicy_main(int argc, char *argv[]) { if (argc < 2) usage(argv[0]); for (int i = 1; i < argc; ++i) { if (argv[i][0] == '-' && argv[i][1] == '-') { - if (strcmp(argv[i], "--live") == 0) - live = 1; - else if (strcmp(argv[i], "--magisk") == 0) + if (strcmp(argv[i] + 2, "live") == 0) + outfile = SELINUX_LOAD; + else if (strcmp(argv[i] + 2, "magisk") == 0) magisk = 1; - else if (strcmp(argv[i], "--load") == 0) { - if (i + 1 >= argc) usage(argv[0]); - infile = argv[i + 1]; - i += 1; - } else if (strcmp(argv[i], "--save") == 0) { - if (i + 1 >= argc) usage(argv[0]); + else if (strcmp(argv[i] + 2, "load") == 0) { + if (i + 1 >= argc) + usage(argv[0]); + if (load_policydb(argv[i + 1])) { + fprintf(stderr, "Cannot load policy from %s\n", argv[i + 1]); + return 1; + } + ++i; + } else if (strcmp(argv[i] + 2, "compile-split") == 0) { + if (compile_split_cil()) { + fprintf(stderr, "Cannot compile split cil\n"); + return 1; + } + } else if (strcmp(argv[i] + 2, "save") == 0) { + if (i + 1 >= argc) + usage(argv[0]); outfile = argv[i + 1]; - i += 1; - } else + ++i; + } else { usage(argv[0]); + } } else { vec_push_back(&rules, argv[i]); } } - // Use current policy if not specified - if(!infile) - infile = SELINUX_POLICY; - - if (load_policydb(infile)) { - fprintf(stderr, "Cannot load policy from %s\n", infile); + // Use current policy if nothing is loaded + if(policydb == NULL && load_policydb(SELINUX_POLICY)) { + fprintf(stderr, "Cannot load policy from " SELINUX_POLICY "\n"); return 1; } @@ -471,9 +488,6 @@ int magiskpolicy_main(int argc, char *argv[]) { vec_destroy(&rules); - if (live) - outfile = SELINUX_LOAD; - if (outfile && dump_policydb(outfile)) { fprintf(stderr, "Cannot dump policy to %s\n", outfile); return 1; diff --git a/native/jni/magiskpolicy/magiskpolicy.h b/native/jni/magiskpolicy/magiskpolicy.h index 1f4b700fb..6df3ec0f7 100644 --- a/native/jni/magiskpolicy/magiskpolicy.h +++ b/native/jni/magiskpolicy/magiskpolicy.h @@ -10,8 +10,17 @@ #define SEPOL_PROC_DOMAIN "magisk" #define SEPOL_FILE_DOMAIN "magisk_file" +// split policy paths +#define PLAT_POLICY_DIR "/system/etc/selinux/" +#define NONPLAT_POLICY_DIR "/vendor/etc/selinux/" +#define SPLIT_PLAT_CIL PLAT_POLICY_DIR "plat_sepolicy.cil" +#define SPLIT_PLAT_MAPPING PLAT_POLICY_DIR "mapping/%s.cil" +#define SPLIT_PRECOMPILE NONPLAT_POLICY_DIR "precompiled_sepolicy" +#define SPLIT_NONPLAT_VER NONPLAT_POLICY_DIR "plat_sepolicy_vers.txt" + // policydb functions int load_policydb(const char *filename); +int compile_split_cil(); int dump_policydb(const char *filename); void destroy_policydb(); diff --git a/native/jni/magiskpolicy/sepolicy.c b/native/jni/magiskpolicy/sepolicy.c index cda8fac33..b04f73bdb 100644 --- a/native/jni/magiskpolicy/sepolicy.c +++ b/native/jni/magiskpolicy/sepolicy.c @@ -1,7 +1,31 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "utils.h" #include "magiskpolicy.h" #include "sepolicy.h" +#include "vector.h" policydb_t *policydb = NULL; +extern int policydb_index_decls(sepol_handle_t * handle, policydb_t * p); static void *cmalloc(size_t s) { void *t = calloc(s, 1); @@ -245,6 +269,69 @@ int load_policydb(const char *filename) { return 0; } +int compile_split_cil() { + DIR *dir; + struct dirent *entry; + char path[128]; + + 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_multiple_decls(db, 1); + cil_set_disable_neverallow(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); + + // plat + mmap_ro(SPLIT_PLAT_CIL, &addr, &size); + if (cil_add_file(db, SPLIT_PLAT_CIL, addr, size)) + return 1; + fprintf(stderr, "cil_add[%s]\n", SPLIT_PLAT_CIL); + munmap(addr, size); + + // mapping + char plat[10]; + int fd = open(SPLIT_NONPLAT_VER, O_RDONLY | O_CLOEXEC); + plat[read(fd, plat, sizeof(plat)) - 1] = '\0'; + sprintf(path, SPLIT_PLAT_MAPPING, plat); + mmap_ro(path, &addr, &size); + if (cil_add_file(db, path, addr, size)) + return 1; + fprintf(stderr, "cil_add[%s]\n", path); + munmap(addr, size); + close(fd); + + // nonplat + dir = opendir(NONPLAT_POLICY_DIR); + while ((entry = readdir(dir))) { + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + continue; + if (strend(entry->d_name, ".cil") == 0) { + sprintf(path, NONPLAT_POLICY_DIR "%s", entry->d_name); + mmap_ro(path, &addr, &size); + if (cil_add_file(db, path, addr, size)) + return 1; + fprintf(stderr, "cil_add[%s]\n", path); + munmap(addr, size); + } + } + closedir(dir); + + if (cil_compile(db)) + return 1; + if (cil_build_policydb(db, &pdb)) + return 1; + + cil_db_destroy(&db); + policydb = &pdb->p; + return 0; +} + int dump_policydb(const char *filename) { int fd, ret; void *data = NULL; diff --git a/native/jni/magiskpolicy/sepolicy.h b/native/jni/magiskpolicy/sepolicy.h index fd5d10d10..82c52c3e6 100644 --- a/native/jni/magiskpolicy/sepolicy.h +++ b/native/jni/magiskpolicy/sepolicy.h @@ -4,35 +4,16 @@ #ifndef _SEPOLICY_H #define _SEPOLICY_H -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include -#include -#include "vector.h" +// Global policydb +extern policydb_t *policydb; // hashtab traversal macro #define hashtab_for_each(table, ptr) \ for (int _i = 0; _i < table->size; ++_i) \ for (*ptr = table->htable[_i]; *ptr != NULL; *ptr = (*ptr)->next) -// Global policydb -extern policydb_t *policydb; - // sepolicy manipulation functions int create_domain(char *d); int set_domain_state(char* s, int state); @@ -42,6 +23,4 @@ int add_typeattribute(char *domainS, char *attr); int add_rule(char *s, char *t, char *c, char *p, int effect, int not); int add_xperm_rule(char *s, char *t, char *c, char *range, int effect, int not); -extern int policydb_index_decls(sepol_handle_t * handle, policydb_t * p); - #endif diff --git a/native/jni/utils/misc.c b/native/jni/utils/misc.c index 58f121646..b57ad392d 100644 --- a/native/jni/utils/misc.c +++ b/native/jni/utils/misc.c @@ -477,3 +477,9 @@ void gen_rand_str(char *buf, int len) { } buf[len - 1] = '\0'; } + +int strend(const char *s1, const char *s2) { + size_t l1 = strlen(s1); + size_t l2 = strlen(s2); + return strcmp(s1 + l1 - l2, s2); +}