Support compiling split cils via magiskpolicy CLI

This commit is contained in:
topjohnwu 2018-07-21 05:12:22 +08:00
parent 6263d684d9
commit 91818cfa1a
8 changed files with 151 additions and 130 deletions

View File

@ -37,7 +37,6 @@
#include <sys/sysmacros.h> #include <sys/sysmacros.h>
#include <lzma.h> #include <lzma.h>
#include <cil/cil.h>
#include "binaries_xz.h" #include "binaries_xz.h"
#include "binaries_arch_xz.h" #include "binaries_arch_xz.h"
@ -50,14 +49,13 @@
#include "magisk.h" #include "magisk.h"
#ifdef MAGISK_DEBUG #ifdef MAGISK_DEBUG
#define VLOG(fmt, ...) printf(fmt, __VA_ARGS__) #define VLOG(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__)
#else #else
#define VLOG(fmt, ...) #define VLOG(fmt, ...)
#endif #endif
#define DEFAULT_DT_DIR "/proc/device-tree/firmware/android" #define DEFAULT_DT_DIR "/proc/device-tree/firmware/android"
extern policydb_t *policydb;
int (*init_applet_main[]) (int, char *[]) = { magiskpolicy_main, magiskpolicy_main, NULL }; int (*init_applet_main[]) (int, char *[]) = { magiskpolicy_main, magiskpolicy_main, NULL };
struct cmdline { struct cmdline {
@ -149,12 +147,6 @@ static int setup_block(struct device *dev, const char *partname) {
return 0; 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) { static int read_fstab_dt(const struct cmdline *cmd, const char *mnt_point, char *partname) {
char buf[128]; char buf[128];
struct stat st; struct stat st;
@ -175,65 +167,6 @@ static int read_fstab_dt(const struct cmdline *cmd, const char *mnt_point, char
return 1; 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() { static int verify_precompiled() {
DIR *dir; DIR *dir;
struct dirent *entry; struct dirent *entry;
@ -279,7 +212,7 @@ static int patch_sepolicy() {
load_policydb(SPLIT_PRECOMPILE); load_policydb(SPLIT_PRECOMPILE);
} else if (access(SPLIT_PLAT_CIL, R_OK) == 0) { } else if (access(SPLIT_PLAT_CIL, R_OK) == 0) {
init_patch = 1; init_patch = 1;
compile_cil(); compile_split_cil();
} else if (access("/sepolicy", R_OK) == 0) { } else if (access("/sepolicy", R_OK) == 0) {
load_policydb("/sepolicy"); load_policydb("/sepolicy");
} else { } else {

View File

@ -42,14 +42,6 @@
#define SELINUX_LOAD SELINUX_PATH "/load" #define SELINUX_LOAD SELINUX_PATH "/load"
#define SELINUX_CONTEXT SELINUX_PATH "/context" #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" #define MAGISKHIDE_PROP "persist.magisk.hide"
extern char *argv0; /* For changing process name */ extern char *argv0; /* For changing process name */

View File

@ -107,6 +107,7 @@ int switch_mnt_ns(int pid);
int fork_dont_care(); int fork_dont_care();
void wait_till_exists(const char *target); void wait_till_exists(const char *target);
void gen_rand_str(char *buf, int len); void gen_rand_str(char *buf, int len);
int strend(const char *s1, const char *s2);
// file.c // file.c

View File

@ -3,8 +3,11 @@
* Includes all the parsing logic for the policy statements * Includes all the parsing logic for the policy statements
*/ */
#include "magiskpolicy.h" #include <stdio.h>
#include "sepolicy.h" #include "sepolicy.h"
#include "vector.h"
#include "magiskpolicy.h"
#include "magisk.h" #include "magisk.h"
static int syntax_err = 0; static int syntax_err = 0;
@ -59,14 +62,20 @@ static void statements() {
static void usage(char *arg0) { static void usage(char *arg0) {
fprintf(stderr, fprintf(stderr,
"MagiskPolicy v" xstr(MAGISK_VERSION) "(" xstr(MAGISK_VER_CODE) ") (by topjohnwu)\n\n" "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" "Options:\n"
" --live directly apply patched policy live\n" " --live directly apply sepolicy live\n"
" --magisk built-in rules for a Magisk selinux environment\n" " --magisk inject built-in rules for a Magisk\n"
" --load FILE load policies from <infile>\n" " selinux environment\n"
" --save FILE save policies to <outfile>\n\n" " --load FILE load policies from FILE\n"
"If no input file is specified, it will load from current policies\n" " --compile-split compile and load split cil policies\n"
"If neither --live nor --save is specified, nothing will happen\n\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); , arg0);
statements(); statements();
exit(1); exit(1);
@ -381,8 +390,8 @@ static void syntax_error_msg() {
} }
int magiskpolicy_main(int argc, char *argv[]) { int magiskpolicy_main(int argc, char *argv[]) {
char *infile = NULL, *outfile = NULL, *tok, *saveptr; char *outfile = NULL, *tok, *saveptr;
int live = 0, magisk = 0; int magisk = 0;
struct vector rules; struct vector rules;
vec_init(&rules); vec_init(&rules);
@ -390,31 +399,39 @@ int magiskpolicy_main(int argc, char *argv[]) {
if (argc < 2) usage(argv[0]); if (argc < 2) usage(argv[0]);
for (int i = 1; i < argc; ++i) { for (int i = 1; i < argc; ++i) {
if (argv[i][0] == '-' && argv[i][1] == '-') { if (argv[i][0] == '-' && argv[i][1] == '-') {
if (strcmp(argv[i], "--live") == 0) if (strcmp(argv[i] + 2, "live") == 0)
live = 1; outfile = SELINUX_LOAD;
else if (strcmp(argv[i], "--magisk") == 0) else if (strcmp(argv[i] + 2, "magisk") == 0)
magisk = 1; magisk = 1;
else if (strcmp(argv[i], "--load") == 0) { else if (strcmp(argv[i] + 2, "load") == 0) {
if (i + 1 >= argc) usage(argv[0]); if (i + 1 >= argc)
infile = argv[i + 1]; usage(argv[0]);
i += 1; if (load_policydb(argv[i + 1])) {
} else if (strcmp(argv[i], "--save") == 0) { fprintf(stderr, "Cannot load policy from %s\n", argv[i + 1]);
if (i + 1 >= argc) usage(argv[0]); 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]; outfile = argv[i + 1];
i += 1; ++i;
} else } else {
usage(argv[0]); usage(argv[0]);
}
} else { } else {
vec_push_back(&rules, argv[i]); vec_push_back(&rules, argv[i]);
} }
} }
// Use current policy if not specified // Use current policy if nothing is loaded
if(!infile) if(policydb == NULL && load_policydb(SELINUX_POLICY)) {
infile = SELINUX_POLICY; fprintf(stderr, "Cannot load policy from " SELINUX_POLICY "\n");
if (load_policydb(infile)) {
fprintf(stderr, "Cannot load policy from %s\n", infile);
return 1; return 1;
} }
@ -471,9 +488,6 @@ int magiskpolicy_main(int argc, char *argv[]) {
vec_destroy(&rules); vec_destroy(&rules);
if (live)
outfile = SELINUX_LOAD;
if (outfile && dump_policydb(outfile)) { if (outfile && dump_policydb(outfile)) {
fprintf(stderr, "Cannot dump policy to %s\n", outfile); fprintf(stderr, "Cannot dump policy to %s\n", outfile);
return 1; return 1;

View File

@ -10,8 +10,17 @@
#define SEPOL_PROC_DOMAIN "magisk" #define SEPOL_PROC_DOMAIN "magisk"
#define SEPOL_FILE_DOMAIN "magisk_file" #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 // policydb functions
int load_policydb(const char *filename); int load_policydb(const char *filename);
int compile_split_cil();
int dump_policydb(const char *filename); int dump_policydb(const char *filename);
void destroy_policydb(); void destroy_policydb();

View File

@ -1,7 +1,31 @@
#include <dirent.h>
#include <getopt.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <limits.h>
#include <string.h>
#include <cil/cil.h>
#include <sepol/debug.h>
#include <sepol/policydb/policydb.h>
#include <sepol/policydb/expand.h>
#include <sepol/policydb/link.h>
#include <sepol/policydb/services.h>
#include <sepol/policydb/avrule_block.h>
#include <sepol/policydb/conditional.h>
#include <sepol/policydb/constraint.h>
#include "utils.h"
#include "magiskpolicy.h" #include "magiskpolicy.h"
#include "sepolicy.h" #include "sepolicy.h"
#include "vector.h"
policydb_t *policydb = NULL; policydb_t *policydb = NULL;
extern int policydb_index_decls(sepol_handle_t * handle, policydb_t * p);
static void *cmalloc(size_t s) { static void *cmalloc(size_t s) {
void *t = calloc(s, 1); void *t = calloc(s, 1);
@ -245,6 +269,69 @@ int load_policydb(const char *filename) {
return 0; 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 dump_policydb(const char *filename) {
int fd, ret; int fd, ret;
void *data = NULL; void *data = NULL;

View File

@ -4,35 +4,16 @@
#ifndef _SEPOLICY_H #ifndef _SEPOLICY_H
#define _SEPOLICY_H #define _SEPOLICY_H
#include <getopt.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <limits.h>
#include <string.h>
#include <sepol/debug.h>
#include <sepol/policydb/policydb.h> #include <sepol/policydb/policydb.h>
#include <sepol/policydb/expand.h>
#include <sepol/policydb/link.h>
#include <sepol/policydb/services.h>
#include <sepol/policydb/avrule_block.h>
#include <sepol/policydb/conditional.h>
#include <sepol/policydb/constraint.h>
#include "vector.h" // Global policydb
extern policydb_t *policydb;
// hashtab traversal macro // hashtab traversal macro
#define hashtab_for_each(table, ptr) \ #define hashtab_for_each(table, ptr) \
for (int _i = 0; _i < table->size; ++_i) \ for (int _i = 0; _i < table->size; ++_i) \
for (*ptr = table->htable[_i]; *ptr != NULL; *ptr = (*ptr)->next) for (*ptr = table->htable[_i]; *ptr != NULL; *ptr = (*ptr)->next)
// Global policydb
extern policydb_t *policydb;
// sepolicy manipulation functions // sepolicy manipulation functions
int create_domain(char *d); int create_domain(char *d);
int set_domain_state(char* s, int state); 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_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); 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 #endif

View File

@ -477,3 +477,9 @@ void gen_rand_str(char *buf, int len) {
} }
buf[len - 1] = '\0'; 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);
}