mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-11-27 20:15:29 +00:00
Support Android Q new split sepolicy setup
This commit is contained in:
parent
e476c18c99
commit
f0240b1f06
@ -83,6 +83,7 @@ LOCAL_SRC_FILES := \
|
|||||||
magiskpolicy/api.cpp \
|
magiskpolicy/api.cpp \
|
||||||
magiskpolicy/magiskpolicy.cpp \
|
magiskpolicy/magiskpolicy.cpp \
|
||||||
magiskpolicy/rules.cpp \
|
magiskpolicy/rules.cpp \
|
||||||
|
magiskpolicy/policydb.cpp \
|
||||||
magiskpolicy/sepolicy.c
|
magiskpolicy/sepolicy.c
|
||||||
|
|
||||||
LOCAL_LDFLAGS := -static
|
LOCAL_LDFLAGS := -static
|
||||||
|
@ -57,6 +57,8 @@ int (*init_applet_main[]) (int, char *[]) = { magiskpolicy_main, magiskpolicy_ma
|
|||||||
|
|
||||||
static bool mnt_system = false;
|
static bool mnt_system = false;
|
||||||
static bool mnt_vendor = false;
|
static bool mnt_vendor = false;
|
||||||
|
static bool mnt_product = false;
|
||||||
|
static bool mnt_odm = false;
|
||||||
static bool kirin = false;
|
static bool kirin = false;
|
||||||
|
|
||||||
static void *self, *config;
|
static void *self, *config;
|
||||||
@ -196,13 +198,18 @@ static bool setup_block(struct device *dev, const char *partname) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool is_lnk(const char *name) {
|
||||||
|
struct stat st;
|
||||||
|
if (lstat(name, &st))
|
||||||
|
return false;
|
||||||
|
return S_ISLNK(st.st_mode);
|
||||||
|
}
|
||||||
|
|
||||||
static bool read_fstab_dt(const struct cmdline *cmd, const char *mnt_point, char *partname, char *partfs) {
|
static bool read_fstab_dt(const struct cmdline *cmd, const char *mnt_point, char *partname, char *partfs) {
|
||||||
char buf[128];
|
char buf[128];
|
||||||
struct stat st;
|
struct stat st;
|
||||||
sprintf(buf, "/%s", mnt_point);
|
sprintf(buf, "/%s", mnt_point);
|
||||||
lstat(buf, &st);
|
if (is_lnk(buf))
|
||||||
// Don't early mount if the mount point is symlink
|
|
||||||
if (S_ISLNK(st.st_mode))
|
|
||||||
return false;
|
return false;
|
||||||
int fd;
|
int fd;
|
||||||
sprintf(buf, "%s/fstab/%s/dev", cmd->dt_dir, mnt_point);
|
sprintf(buf, "%s/fstab/%s/dev", cmd->dt_dir, mnt_point);
|
||||||
@ -222,68 +229,29 @@ static bool read_fstab_dt(const struct cmdline *cmd, const char *mnt_point, char
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool verify_precompiled() {
|
|
||||||
DIR *dir;
|
|
||||||
struct dirent *entry;
|
|
||||||
int fd;
|
|
||||||
char sys_sha[64], ven_sha[64];
|
|
||||||
|
|
||||||
// init the strings with different value
|
|
||||||
sys_sha[0] = 0;
|
|
||||||
ven_sha[0] = 1;
|
|
||||||
|
|
||||||
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, ".sha256") == 0) {
|
|
||||||
fd = openat(dirfd(dir), entry->d_name, O_RDONLY | O_CLOEXEC);
|
|
||||||
read(fd, ven_sha, sizeof(ven_sha));
|
|
||||||
close(fd);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
closedir(dir);
|
|
||||||
dir = opendir(PLAT_POLICY_DIR);
|
|
||||||
while ((entry = readdir(dir))) {
|
|
||||||
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
|
|
||||||
continue;
|
|
||||||
if (strend(entry->d_name, ".sha256") == 0) {
|
|
||||||
fd = openat(dirfd(dir), entry->d_name, O_RDONLY | O_CLOEXEC);
|
|
||||||
read(fd, sys_sha, sizeof(sys_sha));
|
|
||||||
close(fd);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
closedir(dir);
|
|
||||||
LOGD("sys_sha[%.*s]\nven_sha[%.*s]\n", sizeof(sys_sha), sys_sha, sizeof(ven_sha), ven_sha);
|
|
||||||
return memcmp(sys_sha, ven_sha, sizeof(sys_sha)) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool patch_sepolicy() {
|
static bool patch_sepolicy() {
|
||||||
bool patch_init = false;
|
bool patch_init = false;
|
||||||
if (access(SPLIT_PRECOMPILE, R_OK) == 0 && verify_precompiled()) {
|
|
||||||
patch_init = true;
|
if (access(SPLIT_PLAT_CIL, R_OK) == 0)
|
||||||
load_policydb(SPLIT_PRECOMPILE);
|
patch_init = true; /* Split sepolicy */
|
||||||
} else if (access(SPLIT_PLAT_CIL, R_OK) == 0) {
|
else if (access("/sepolicy", R_OK) == 0)
|
||||||
patch_init = true;
|
load_policydb("/sepolicy"); /* Monolithic sepolicy */
|
||||||
compile_split_cil();
|
else
|
||||||
} else if (access("/sepolicy", R_OK) == 0) {
|
return false; /* No SELinux */
|
||||||
load_policydb("/sepolicy");
|
|
||||||
} else {
|
// Mount selinuxfs to communicate with kernel
|
||||||
// No selinux in this ROM
|
xmount("selinuxfs", SELINUX_MNT, "selinuxfs", 0, nullptr);
|
||||||
return false;
|
|
||||||
}
|
if (patch_init)
|
||||||
|
load_split_cil();
|
||||||
|
|
||||||
sepol_magisk_rules();
|
sepol_magisk_rules();
|
||||||
sepol_allow(SEPOL_PROC_DOMAIN, ALL, ALL, ALL);
|
sepol_allow(SEPOL_PROC_DOMAIN, ALL, ALL, ALL);
|
||||||
dump_policydb("/sepolicy");
|
dump_policydb("/sepolicy");
|
||||||
|
|
||||||
if (!kirin) {
|
|
||||||
// Load policy to kernel so we can label rootfs
|
// Load policy to kernel so we can label rootfs
|
||||||
xmount("selinuxfs", SELINUX_MNT, "selinuxfs", 0, nullptr);
|
if (!kirin)
|
||||||
dump_policydb(SELINUX_LOAD);
|
dump_policydb(SELINUX_LOAD);
|
||||||
}
|
|
||||||
|
|
||||||
// Remove OnePlus stupid debug sepolicy and use our own
|
// Remove OnePlus stupid debug sepolicy and use our own
|
||||||
if (access("/sepolicy_debug", F_OK) == 0) {
|
if (access("/sepolicy_debug", F_OK) == 0) {
|
||||||
@ -453,6 +421,10 @@ static void setup_overlay() {
|
|||||||
umount("/system");
|
umount("/system");
|
||||||
if (mnt_vendor)
|
if (mnt_vendor)
|
||||||
umount("/vendor");
|
umount("/vendor");
|
||||||
|
if (mnt_product)
|
||||||
|
umount("/product");
|
||||||
|
if (mnt_odm)
|
||||||
|
umount("/odm");
|
||||||
|
|
||||||
execv("/init", argv);
|
execv("/init", argv);
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -537,6 +509,15 @@ int main(int argc, char *argv[]) {
|
|||||||
xmount(dev.path, "/system_root", "ext4", MS_RDONLY, nullptr);
|
xmount(dev.path, "/system_root", "ext4", MS_RDONLY, nullptr);
|
||||||
xmkdir("/system", 0755);
|
xmkdir("/system", 0755);
|
||||||
xmount("/system_root/system", "/system", nullptr, MS_BIND, nullptr);
|
xmount("/system_root/system", "/system", nullptr, MS_BIND, nullptr);
|
||||||
|
|
||||||
|
// Copy if these partitions are symlinks
|
||||||
|
if (is_lnk("/system_root/vendor"))
|
||||||
|
cp_afc("/system_root/vendor", "/vendor");
|
||||||
|
if (is_lnk("/system_root/product"))
|
||||||
|
cp_afc("/system_root/product", "/product");
|
||||||
|
if (is_lnk("/system_root/odm"))
|
||||||
|
cp_afc("/system_root/odm", "/odm");
|
||||||
|
|
||||||
} else if (read_fstab_dt(&cmd, "system", partname, partfs)) {
|
} else if (read_fstab_dt(&cmd, "system", partname, partfs)) {
|
||||||
setup_block(&dev, partname);
|
setup_block(&dev, partname);
|
||||||
xmount(dev.path, "/system", partfs, MS_RDONLY, nullptr);
|
xmount(dev.path, "/system", partfs, MS_RDONLY, nullptr);
|
||||||
@ -550,6 +531,20 @@ int main(int argc, char *argv[]) {
|
|||||||
mnt_vendor = true;
|
mnt_vendor = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (read_fstab_dt(&cmd, "product", partname, partfs)) {
|
||||||
|
setup_block(&dev, partname);
|
||||||
|
xmkdir("/product", 0755);
|
||||||
|
xmount(dev.path, "/product", partfs, MS_RDONLY, nullptr);
|
||||||
|
mnt_product = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (read_fstab_dt(&cmd, "odm", partname, partfs)) {
|
||||||
|
setup_block(&dev, partname);
|
||||||
|
xmkdir("/odm", 0755);
|
||||||
|
xmount(dev.path, "/odm", partfs, MS_RDONLY, nullptr);
|
||||||
|
mnt_odm = true;
|
||||||
|
}
|
||||||
|
|
||||||
/***************
|
/***************
|
||||||
* Setup Rootfs
|
* Setup Rootfs
|
||||||
***************/
|
***************/
|
||||||
|
@ -1,8 +1,4 @@
|
|||||||
/* magisk.h - Top header
|
#pragma once
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _MAGISK_H_
|
|
||||||
#define _MAGISK_H_
|
|
||||||
|
|
||||||
#include <logging.h>
|
#include <logging.h>
|
||||||
|
|
||||||
@ -30,15 +26,6 @@
|
|||||||
// Legacy crap
|
// Legacy crap
|
||||||
#define LEGACYCORE MODULEROOT "/.core"
|
#define LEGACYCORE MODULEROOT "/.core"
|
||||||
|
|
||||||
// selinux consts
|
|
||||||
#define SELINUX_MNT "/sys/fs/selinux"
|
|
||||||
#define SELINUX_ENFORCE SELINUX_MNT "/enforce"
|
|
||||||
#define SELINUX_POLICY SELINUX_MNT "/policy"
|
|
||||||
#define SELINUX_LOAD SELINUX_MNT "/load"
|
|
||||||
#define SELINUX_CONTEXT SELINUX_MNT "/context"
|
|
||||||
#define SEPOL_PROC_DOMAIN "magisk"
|
|
||||||
#define SEPOL_FILE_DOMAIN "magisk_file"
|
|
||||||
|
|
||||||
extern int SDK_INT;
|
extern int SDK_INT;
|
||||||
|
|
||||||
constexpr const char *applet_names[] = { "magisk", "su", "resetprop", "magiskhide", nullptr };
|
constexpr const char *applet_names[] = { "magisk", "su", "resetprop", "magiskhide", nullptr };
|
||||||
@ -50,5 +37,3 @@ int magiskhide_main(int argc, char *argv[]);
|
|||||||
int magiskpolicy_main(int argc, char *argv[]);
|
int magiskpolicy_main(int argc, char *argv[]);
|
||||||
int su_client_main(int argc, char *argv[]);
|
int su_client_main(int argc, char *argv[]);
|
||||||
int resetprop_main(int argc, char *argv[]);
|
int resetprop_main(int argc, char *argv[]);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include <utils.h>
|
#include <utils.h>
|
||||||
#include <resetprop.h>
|
#include <resetprop.h>
|
||||||
#include <db.h>
|
#include <db.h>
|
||||||
|
#include <selinux.h>
|
||||||
|
|
||||||
#include "magiskhide.h"
|
#include "magiskhide.h"
|
||||||
|
|
||||||
|
@ -92,8 +92,9 @@ static const char *type_msg_6 =
|
|||||||
"Options:\n"
|
"Options:\n"
|
||||||
" --help show help message for policy statements\n"
|
" --help show help message for policy statements\n"
|
||||||
" --load FILE load policies from FILE\n"
|
" --load FILE load policies from FILE\n"
|
||||||
" --compile-split compile and load split cil policies\n"
|
" --load-split load from preloaded sepolicy or compile\n"
|
||||||
" from system and vendor just like init\n"
|
" split policies\n"
|
||||||
|
" --compile-split compile split cil policies\n"
|
||||||
" --save FILE save policies to FILE\n"
|
" --save FILE save policies to FILE\n"
|
||||||
" --live directly apply sepolicy live\n"
|
" --live directly apply sepolicy live\n"
|
||||||
" --magisk inject built-in rules for a minimal\n"
|
" --magisk inject built-in rules for a minimal\n"
|
||||||
@ -460,6 +461,11 @@ int magiskpolicy_main(int argc, char *argv[]) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
++i;
|
++i;
|
||||||
|
} else if (strcmp(argv[i] + 2, "load-split") == 0) {
|
||||||
|
if (load_split_cil()) {
|
||||||
|
fprintf(stderr, "Cannot load split cil\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
} else if (strcmp(argv[i] + 2, "compile-split") == 0) {
|
} else if (strcmp(argv[i] + 2, "compile-split") == 0) {
|
||||||
if (compile_split_cil()) {
|
if (compile_split_cil()) {
|
||||||
fprintf(stderr, "Cannot compile split cil\n");
|
fprintf(stderr, "Cannot compile split cil\n");
|
||||||
@ -486,12 +492,12 @@ int magiskpolicy_main(int argc, char *argv[]) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (; i < argc; ++i)
|
|
||||||
parse_statement(argv[i]);
|
|
||||||
|
|
||||||
if (magisk)
|
if (magisk)
|
||||||
sepol_magisk_rules();
|
sepol_magisk_rules();
|
||||||
|
|
||||||
|
for (; i < argc; ++i)
|
||||||
|
parse_statement(argv[i]);
|
||||||
|
|
||||||
if (live && dump_policydb(SELINUX_LOAD)) {
|
if (live && dump_policydb(SELINUX_LOAD)) {
|
||||||
fprintf(stderr, "Cannot apply policy\n");
|
fprintf(stderr, "Cannot apply policy\n");
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -5,25 +5,19 @@
|
|||||||
#define _MAGISKPOLICY_H
|
#define _MAGISKPOLICY_H
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <selinux.h>
|
||||||
|
|
||||||
#define ALL NULL
|
#define ALL NULL
|
||||||
|
|
||||||
// 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"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// policydb functions
|
// policydb functions
|
||||||
int load_policydb(const char *filename);
|
int load_policydb(const char *file);
|
||||||
|
int load_split_cil();
|
||||||
int compile_split_cil();
|
int compile_split_cil();
|
||||||
int dump_policydb(const char *filename);
|
int dump_policydb(const char *file);
|
||||||
void destroy_policydb();
|
void destroy_policydb();
|
||||||
|
|
||||||
// Handy functions
|
// Handy functions
|
||||||
|
201
native/jni/magiskpolicy/policydb.cpp
Normal file
201
native/jni/magiskpolicy/policydb.cpp
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <cil/cil.h>
|
||||||
|
|
||||||
|
#include <utils.h>
|
||||||
|
#include <logging.h>
|
||||||
|
|
||||||
|
#include "magiskpolicy.h"
|
||||||
|
#include "sepolicy.h"
|
||||||
|
|
||||||
|
policydb_t *policydb = nullptr;
|
||||||
|
|
||||||
|
int load_policydb(const char *file) {
|
||||||
|
if (policydb)
|
||||||
|
destroy_policydb();
|
||||||
|
|
||||||
|
struct policy_file pf;
|
||||||
|
policy_file_init(&pf);
|
||||||
|
pf.fp = xfopen(file, "re");
|
||||||
|
pf.type = PF_USE_STDIO;
|
||||||
|
|
||||||
|
policydb = new policydb_t();
|
||||||
|
if (policydb_init(policydb) || policydb_read(policydb, &pf, 0))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
fclose(pf.fp);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SHALEN 64
|
||||||
|
static bool cmp_sha256(const char *a, const char *b) {
|
||||||
|
char id_a[SHALEN] = {0};
|
||||||
|
char id_b[SHALEN] = {0};
|
||||||
|
if (int fd = xopen(a, O_RDONLY | O_CLOEXEC); fd >= 0) {
|
||||||
|
xread(fd, id_a, SHALEN);
|
||||||
|
close(fd);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (int fd = xopen(b, O_RDONLY | O_CLOEXEC); fd >= 0) {
|
||||||
|
xread(fd, id_b, SHALEN);
|
||||||
|
close(fd);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
LOGD("%s=[%.*s]\n%s=[%.*s]\n", a, SHALEN, id_a, b, SHALEN, id_b);
|
||||||
|
return memcmp(id_a, id_b, SHALEN) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool check_precompiled(const char *precompiled) {
|
||||||
|
bool ok = false;
|
||||||
|
const char *actual_sha;
|
||||||
|
char compiled_sha[128];
|
||||||
|
|
||||||
|
actual_sha = PLAT_POLICY_DIR "plat_and_mapping_sepolicy.cil.sha256";
|
||||||
|
if (access(actual_sha, R_OK) == 0) {
|
||||||
|
ok = true;
|
||||||
|
sprintf(compiled_sha, "%s.plat_and_mapping.sha256", precompiled);
|
||||||
|
if (!cmp_sha256(actual_sha, compiled_sha))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
actual_sha = PLAT_POLICY_DIR "plat_sepolicy_and_mapping.sha256";
|
||||||
|
if (access(actual_sha, R_OK) == 0) {
|
||||||
|
ok = true;
|
||||||
|
sprintf(compiled_sha, "%s.plat_sepolicy_and_mapping.sha256", precompiled);
|
||||||
|
if (!cmp_sha256(actual_sha, compiled_sha))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
actual_sha = PROD_POLICY_DIR "product_sepolicy_and_mapping.sha256";
|
||||||
|
if (access(actual_sha, R_OK) == 0) {
|
||||||
|
ok = true;
|
||||||
|
sprintf(compiled_sha, "%s.product_sepolicy_and_mapping.sha256", precompiled);
|
||||||
|
if (!cmp_sha256(actual_sha, compiled_sha) != 0)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
int load_split_cil() {
|
||||||
|
const char *odm_pre = ODM_POLICY_DIR "precompiled_sepolicy";
|
||||||
|
const char *vend_pre = VEND_POLICY_DIR "precompiled_sepolicy";
|
||||||
|
if (access(odm_pre, R_OK) == 0 && check_precompiled(odm_pre))
|
||||||
|
return load_policydb(odm_pre);
|
||||||
|
else if (access(vend_pre, R_OK) == 0 && check_precompiled(vend_pre))
|
||||||
|
return load_policydb(vend_pre);
|
||||||
|
else
|
||||||
|
return compile_split_cil();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void load_cil(struct cil_db *db, const char *file) {
|
||||||
|
char *addr;
|
||||||
|
size_t size;
|
||||||
|
mmap_ro(file, addr, size);
|
||||||
|
cil_add_file(db, (char *) file, addr, size);
|
||||||
|
LOGD("cil_add[%s]\n", file);
|
||||||
|
munmap(addr, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int compile_split_cil() {
|
||||||
|
char path[128], plat_ver[10];
|
||||||
|
struct cil_db *db = nullptr;
|
||||||
|
sepol_policydb_t *pdb = nullptr;
|
||||||
|
FILE *f;
|
||||||
|
int policy_ver;
|
||||||
|
const char *cil_file;
|
||||||
|
|
||||||
|
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_attrs_expand_generated(db, 0);
|
||||||
|
|
||||||
|
f = xfopen(SELINUX_VERSION, "re");
|
||||||
|
fscanf(f, "%d", &policy_ver);
|
||||||
|
fclose(f);
|
||||||
|
cil_set_policy_version(db, policy_ver);
|
||||||
|
|
||||||
|
// Get mapping version
|
||||||
|
f = xfopen(VEND_POLICY_DIR "plat_sepolicy_vers.txt", "re");
|
||||||
|
fscanf(f, "%s", plat_ver);
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
// plat
|
||||||
|
load_cil(db, SPLIT_PLAT_CIL);
|
||||||
|
|
||||||
|
sprintf(path, PLAT_POLICY_DIR "mapping/%s.cil", plat_ver);
|
||||||
|
load_cil(db, path);
|
||||||
|
|
||||||
|
// product
|
||||||
|
sprintf(path, PROD_POLICY_DIR "mapping/%s.cil", plat_ver);
|
||||||
|
if (access(path, R_OK) == 0)
|
||||||
|
load_cil(db, path);
|
||||||
|
|
||||||
|
cil_file = PROD_POLICY_DIR "product_sepolicy.cil";
|
||||||
|
if (access(cil_file, R_OK) == 0)
|
||||||
|
load_cil(db, cil_file);
|
||||||
|
|
||||||
|
// vendor
|
||||||
|
cil_file = VEND_POLICY_DIR "nonplat_sepolicy.cil";
|
||||||
|
if (access(cil_file, R_OK) == 0)
|
||||||
|
load_cil(db, cil_file);
|
||||||
|
|
||||||
|
cil_file = VEND_POLICY_DIR "plat_pub_versioned.cil";
|
||||||
|
if (access(cil_file, R_OK) == 0)
|
||||||
|
load_cil(db, cil_file);
|
||||||
|
|
||||||
|
cil_file = VEND_POLICY_DIR "vendor_sepolicy.cil";
|
||||||
|
if (access(cil_file, R_OK) == 0)
|
||||||
|
load_cil(db, cil_file);
|
||||||
|
|
||||||
|
// odm
|
||||||
|
cil_file = ODM_POLICY_DIR "odm_sepolicy.cil";
|
||||||
|
if (access(cil_file, R_OK) == 0)
|
||||||
|
load_cil(db, cil_file);
|
||||||
|
|
||||||
|
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 *file) {
|
||||||
|
int fd, ret;
|
||||||
|
void *data = nullptr;
|
||||||
|
size_t len;
|
||||||
|
policydb_to_image(nullptr, policydb, &data, &len);
|
||||||
|
if (data == nullptr) {
|
||||||
|
LOGE("Fail to dump policy image!\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fd = xopen(file, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0644);
|
||||||
|
if (fd < 0)
|
||||||
|
return 1;
|
||||||
|
ret = xwrite(fd, data, len);
|
||||||
|
close(fd);
|
||||||
|
if (ret < 0)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void destroy_policydb() {
|
||||||
|
if (policydb) {
|
||||||
|
policydb_destroy(policydb);
|
||||||
|
delete policydb;
|
||||||
|
policydb = nullptr;
|
||||||
|
}
|
||||||
|
}
|
@ -1,23 +1,5 @@
|
|||||||
#include <dirent.h>
|
|
||||||
#include <getopt.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdlib.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/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 <utils.h>
|
||||||
#include <logging.h>
|
#include <logging.h>
|
||||||
@ -25,7 +7,6 @@
|
|||||||
#include "magiskpolicy.h"
|
#include "magiskpolicy.h"
|
||||||
#include "sepolicy.h"
|
#include "sepolicy.h"
|
||||||
|
|
||||||
policydb_t *policydb = NULL;
|
|
||||||
extern int policydb_index_decls(sepol_handle_t * handle, policydb_t * p);
|
extern int policydb_index_decls(sepol_handle_t * handle, policydb_t * p);
|
||||||
|
|
||||||
static int get_attr(const char *type, int value) {
|
static int get_attr(const char *type, int value) {
|
||||||
@ -235,129 +216,6 @@ static int add_xperm_rule_auto(type_datum_t *src, type_datum_t *tgt, class_datum
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int load_policydb(const char *filename) {
|
|
||||||
struct policy_file pf;
|
|
||||||
void *map;
|
|
||||||
size_t size;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (policydb)
|
|
||||||
destroy_policydb();
|
|
||||||
|
|
||||||
policydb = xcalloc(sizeof(*policydb), 1);
|
|
||||||
|
|
||||||
mmap_ro(filename, &map, &size);
|
|
||||||
|
|
||||||
policy_file_init(&pf);
|
|
||||||
pf.type = PF_USE_MEMORY;
|
|
||||||
pf.data = map;
|
|
||||||
pf.len = size;
|
|
||||||
if (policydb_init(policydb)) {
|
|
||||||
LOGE("policydb_init: Out of memory!\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
ret = policydb_read(policydb, &pf, 0);
|
|
||||||
if (ret) {
|
|
||||||
LOGE("error(s) encountered while parsing configuration\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
munmap(map, size);
|
|
||||||
|
|
||||||
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;
|
|
||||||
LOGD("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;
|
|
||||||
LOGD("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;
|
|
||||||
LOGD("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;
|
|
||||||
size_t len;
|
|
||||||
policydb_to_image(NULL, policydb, &data, &len);
|
|
||||||
if (data == NULL) {
|
|
||||||
LOGE("Fail to dump policy image!\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
fd = creat(filename, 0644);
|
|
||||||
if (fd < 0) {
|
|
||||||
LOGE("Can't open '%s': %s\n", filename, strerror(errno));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
ret = xwrite(fd, data, len);
|
|
||||||
close(fd);
|
|
||||||
if (ret < 0)
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void destroy_policydb() {
|
|
||||||
policydb_destroy(policydb);
|
|
||||||
free(policydb);
|
|
||||||
policydb = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int create_domain(const char *d) {
|
int create_domain(const char *d) {
|
||||||
symtab_datum_t *src = hashtab_search(policydb->p_types.table, d);
|
symtab_datum_t *src = hashtab_search(policydb->p_types.table, d);
|
||||||
if(src) {
|
if(src) {
|
||||||
|
@ -1,5 +1,23 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
// selinuxfs paths
|
||||||
|
#define SELINUX_MNT "/sys/fs/selinux"
|
||||||
|
#define SELINUX_ENFORCE SELINUX_MNT "/enforce"
|
||||||
|
#define SELINUX_POLICY SELINUX_MNT "/policy"
|
||||||
|
#define SELINUX_LOAD SELINUX_MNT "/load"
|
||||||
|
#define SELINUX_CONTEXT SELINUX_MNT "/context"
|
||||||
|
#define SELINUX_VERSION SELINUX_MNT "/policyvers"
|
||||||
|
|
||||||
|
// sepolicy paths
|
||||||
|
#define PLAT_POLICY_DIR "/system/etc/selinux/"
|
||||||
|
#define VEND_POLICY_DIR "/vendor/etc/selinux/"
|
||||||
|
#define PROD_POLICY_DIR "/product/etc/selinux/"
|
||||||
|
#define ODM_POLICY_DIR "/odm/etc/selinux/"
|
||||||
|
#define SPLIT_PLAT_CIL PLAT_POLICY_DIR "plat_sepolicy.cil"
|
||||||
|
|
||||||
|
#define SEPOL_PROC_DOMAIN "magisk"
|
||||||
|
#define SEPOL_FILE_DOMAIN "magisk_file"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user