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 <lzma.h>
#include <cil/cil.h>
#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 {

View File

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

View File

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

View File

@ -3,8 +3,11 @@
* Includes all the parsing logic for the policy statements
*/
#include "magiskpolicy.h"
#include <stdio.h>
#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 <infile>\n"
" --save FILE save policies to <outfile>\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;

View File

@ -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();

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 "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;

View File

@ -4,35 +4,16 @@
#ifndef _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/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
#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

View File

@ -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);
}