mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-11-24 02:25:28 +00:00
Modernize magiskpolicy
This commit is contained in:
parent
e02e46d0fc
commit
d4baae411b
@ -3,38 +3,55 @@
|
||||
#include <stdlib.h>
|
||||
#include <selinux.hpp>
|
||||
|
||||
#define ALL NULL
|
||||
#define ALL nullptr
|
||||
|
||||
// policydb functions
|
||||
int load_policydb(const char *file);
|
||||
int load_split_cil();
|
||||
int compile_split_cil();
|
||||
int dump_policydb(const char *file);
|
||||
void destroy_policydb();
|
||||
struct policydb;
|
||||
|
||||
// Handy functions
|
||||
int sepol_allow(const char *s, const char *t, const char *c, const char *p);
|
||||
int sepol_deny(const char *s, const char *t, const char *c, const char *p);
|
||||
int sepol_auditallow(const char *s, const char *t, const char *c, const char *p);
|
||||
int sepol_dontaudit(const char *s, const char *t, const char *c, const char *p);
|
||||
int sepol_typetrans(const char *s, const char *t, const char *c, const char *d);
|
||||
int sepol_typechange(const char *s, const char *t, const char *c, const char *d);
|
||||
int sepol_typemember(const char *s, const char *t, const char *c, const char *d);
|
||||
int sepol_nametrans(const char *s, const char *t, const char *c, const char *d, const char *o);
|
||||
int sepol_allowxperm(const char *s, const char *t, const char *c, const char *range);
|
||||
int sepol_auditallowxperm(const char *s, const char *t, const char *c, const char *range);
|
||||
int sepol_dontauditxperm(const char *s, const char *t, const char *c, const char *range);
|
||||
int sepol_create(const char *s);
|
||||
int sepol_permissive(const char *s);
|
||||
int sepol_enforce(const char *s);
|
||||
int sepol_attradd(const char *s, const char *a);
|
||||
int sepol_genfscon(const char *name, const char *path, const char *context);
|
||||
int sepol_exists(const char *source);
|
||||
class sepolicy {
|
||||
public:
|
||||
typedef const char * c_str;
|
||||
~sepolicy();
|
||||
|
||||
// Built in rules
|
||||
void sepol_magisk_rules();
|
||||
// Public static factory functions
|
||||
static sepolicy *from_file(c_str file);
|
||||
static sepolicy *from_split();
|
||||
static sepolicy *compile_split();
|
||||
|
||||
// Statement parsing
|
||||
void parse_statement(const char *statement);
|
||||
void load_rule_file(const char *file);
|
||||
void statement_help();
|
||||
// External APIs
|
||||
int to_file(c_str file);
|
||||
void parse_statement(c_str stmt);
|
||||
void load_rule_file(c_str file);
|
||||
|
||||
// Operation on types
|
||||
int create(c_str type);
|
||||
int permissive(c_str type);
|
||||
int enforce(c_str type);
|
||||
int typeattribute(c_str type, c_str attr);
|
||||
int exists(c_str type);
|
||||
|
||||
// Access vector rules
|
||||
int allow(c_str src, c_str tgt, c_str cls, c_str perm);
|
||||
int deny(c_str src, c_str tgt, c_str cls, c_str perm);
|
||||
int auditallow(c_str src, c_str tgt, c_str cls, c_str perm);
|
||||
int dontaudit(c_str src, c_str tgt, c_str cls, c_str perm);
|
||||
|
||||
// Extended permissions access vector rules
|
||||
int allowxperm(c_str src, c_str tgt, c_str cls, c_str range);
|
||||
int auditallowxperm(c_str src, c_str tgt, c_str cls, c_str range);
|
||||
int dontauditxperm(c_str src, c_str tgt, c_str cls, c_str range);
|
||||
|
||||
// Type rules
|
||||
int type_transition(c_str src, c_str tgt, c_str cls, c_str def, c_str obj = nullptr);
|
||||
int type_change(c_str src, c_str tgt, c_str cls, c_str def);
|
||||
int type_member(c_str src, c_str tgt, c_str cls, c_str def);
|
||||
|
||||
// File system labeling
|
||||
int genfscon(c_str fs_name, c_str path, c_str ctx);
|
||||
|
||||
// Magisk
|
||||
void magisk_rules();
|
||||
void allow_su_client(c_str type);
|
||||
|
||||
private:
|
||||
policydb *db;
|
||||
};
|
||||
|
@ -129,13 +129,14 @@ void RootFSInit::setup_rootfs() {
|
||||
|
||||
bool MagiskInit::patch_sepolicy(const char *file) {
|
||||
bool patch_init = false;
|
||||
sepolicy *sepol = nullptr;
|
||||
|
||||
if (access(SPLIT_PLAT_CIL, R_OK) == 0) {
|
||||
LOGD("sepol: split policy\n");
|
||||
patch_init = true;
|
||||
} else if (access("/sepolicy", R_OK) == 0) {
|
||||
LOGD("sepol: monolithic policy\n");
|
||||
load_policydb("/sepolicy");
|
||||
sepol = sepolicy::from_file("/sepolicy");
|
||||
} else {
|
||||
LOGD("sepol: no selinux\n");
|
||||
return false;
|
||||
@ -148,10 +149,10 @@ bool MagiskInit::patch_sepolicy(const char *file) {
|
||||
}
|
||||
|
||||
if (patch_init)
|
||||
load_split_cil();
|
||||
sepol = sepolicy::from_split();
|
||||
|
||||
sepol_magisk_rules();
|
||||
sepol_allow(SEPOL_PROC_DOMAIN, ALL, ALL, ALL);
|
||||
sepol->magisk_rules();
|
||||
sepol->allow(SEPOL_PROC_DOMAIN, ALL, ALL, ALL);
|
||||
|
||||
// Custom rules
|
||||
if (auto dir = open_dir(persist_dir.data()); dir) {
|
||||
@ -159,13 +160,13 @@ bool MagiskInit::patch_sepolicy(const char *file) {
|
||||
auto rule = persist_dir + "/" + entry->d_name + "/sepolicy.rule";
|
||||
if (access(rule.data(), R_OK) == 0) {
|
||||
LOGD("Loading custom sepolicy patch: %s\n", rule.data());
|
||||
load_rule_file(rule.data());
|
||||
sepol->load_rule_file(rule.data());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dump_policydb(file);
|
||||
destroy_policydb();
|
||||
sepol->to_file(file);
|
||||
delete sepol;
|
||||
|
||||
// Remove OnePlus stupid debug sepolicy and use our own
|
||||
if (access("/sepolicy_debug", F_OK) == 0) {
|
||||
|
@ -5,86 +5,86 @@
|
||||
//#define vprint(fmt, ...) printf(fmt, __VA_ARGS__)
|
||||
#define vprint(...)
|
||||
|
||||
int sepol_allow(const char *s, const char *t, const char *c, const char *p) {
|
||||
int sepolicy::allow(const char *s, const char *t, const char *c, const char *p) {
|
||||
vprint("allow %s %s %s %s\n", s, t, c, p);
|
||||
return add_rule(s, t, c, p, AVTAB_ALLOWED, 0);
|
||||
return add_rule(db, s, t, c, p, AVTAB_ALLOWED, 0);
|
||||
}
|
||||
|
||||
int sepol_deny(const char *s, const char *t, const char *c, const char *p) {
|
||||
int sepolicy::deny(const char *s, const char *t, const char *c, const char *p) {
|
||||
vprint("deny %s %s %s %s\n", s, t, c, p);
|
||||
return add_rule(s, t, c, p, AVTAB_ALLOWED, 1);
|
||||
return add_rule(db, s, t, c, p, AVTAB_ALLOWED, 1);
|
||||
}
|
||||
|
||||
int sepol_auditallow(const char *s, const char *t, const char *c, const char *p) {
|
||||
int sepolicy::auditallow(const char *s, const char *t, const char *c, const char *p) {
|
||||
vprint("auditallow %s %s %s %s\n", s, t, c, p);
|
||||
return add_rule(s, t, c, p, AVTAB_AUDITALLOW, 0);
|
||||
return add_rule(db, s, t, c, p, AVTAB_AUDITALLOW, 0);
|
||||
}
|
||||
|
||||
int sepol_dontaudit(const char *s, const char *t, const char *c, const char *p) {
|
||||
int sepolicy::dontaudit(const char *s, const char *t, const char *c, const char *p) {
|
||||
vprint("dontaudit %s %s %s %s\n", s, t, c, p);
|
||||
return add_rule(s, t, c, p, AVTAB_AUDITDENY, 1);
|
||||
return add_rule(db, s, t, c, p, AVTAB_AUDITDENY, 1);
|
||||
}
|
||||
|
||||
int sepol_allowxperm(const char *s, const char *t, const char *c, const char *range) {
|
||||
int sepolicy::allowxperm(const char *s, const char *t, const char *c, const char *range) {
|
||||
vprint("allowxperm %s %s %s %s\n", s, t, c, range);
|
||||
return add_xperm_rule(s, t, c, range, AVTAB_XPERMS_ALLOWED, 0);
|
||||
return add_xperm_rule(db, s, t, c, range, AVTAB_XPERMS_ALLOWED, 0);
|
||||
}
|
||||
|
||||
int sepol_auditallowxperm(const char *s, const char *t, const char *c, const char *range) {
|
||||
int sepolicy::auditallowxperm(const char *s, const char *t, const char *c, const char *range) {
|
||||
vprint("auditallowxperm %s %s %s %s\n", s, t, c, range);
|
||||
return add_xperm_rule(s, t, c, range, AVTAB_XPERMS_AUDITALLOW, 0);
|
||||
return add_xperm_rule(db, s, t, c, range, AVTAB_XPERMS_AUDITALLOW, 0);
|
||||
}
|
||||
|
||||
int sepol_dontauditxperm(const char *s, const char *t, const char *c, const char *range) {
|
||||
int sepolicy::dontauditxperm(const char *s, const char *t, const char *c, const char *range) {
|
||||
vprint("dontauditxperm %s %s %s %s\n", s, t, c, range);
|
||||
return add_xperm_rule(s, t, c, range, AVTAB_XPERMS_DONTAUDIT, 0);
|
||||
return add_xperm_rule(db, s, t, c, range, AVTAB_XPERMS_DONTAUDIT, 0);
|
||||
}
|
||||
|
||||
int sepol_typetrans(const char *s, const char *t, const char *c, const char *d) {
|
||||
vprint("type_transition %s %s %s %s\n", s, t, c, d);
|
||||
return add_type_rule(s, t, c, d, AVTAB_TRANSITION);
|
||||
}
|
||||
|
||||
int sepol_typechange(const char *s, const char *t, const char *c, const char *d) {
|
||||
int sepolicy::type_change(const char *s, const char *t, const char *c, const char *d) {
|
||||
vprint("type_change %s %s %s %s\n", s, t, c, d);
|
||||
return add_type_rule(s, t, c, d, AVTAB_CHANGE);
|
||||
return add_type_rule(db, s, t, c, d, AVTAB_CHANGE);
|
||||
}
|
||||
|
||||
int sepol_typemember(const char *s, const char *t, const char *c, const char *d) {
|
||||
int sepolicy::type_member(const char *s, const char *t, const char *c, const char *d) {
|
||||
vprint("type_member %s %s %s %s\n", s, t, c, d);
|
||||
return add_type_rule(s, t, c, d, AVTAB_MEMBER);
|
||||
return add_type_rule(db, s, t, c, d, AVTAB_MEMBER);
|
||||
}
|
||||
|
||||
int sepol_nametrans(const char *s, const char *t, const char *c, const char *d, const char *o) {
|
||||
vprint("name_trans %s %s %s %s %s\n", s, t, c, d, o);
|
||||
return add_filename_trans(s, t, c, d, o);
|
||||
int sepolicy::type_transition(const char *src, const char *tgt, const char *cls, const char *def, const char *obj) {
|
||||
if (obj) {
|
||||
vprint("type_transition %s %s %s %s\n", src, tgt, cls, def);
|
||||
return add_type_rule(db, src, tgt, cls, def, AVTAB_TRANSITION);
|
||||
} else {
|
||||
vprint("type_transition %s %s %s %s %s\n", src, tgt, cls, def, obj);
|
||||
return add_filename_trans(db, src, tgt, cls, def, obj);
|
||||
}
|
||||
}
|
||||
|
||||
int sepol_permissive(const char *s) {
|
||||
int sepolicy::permissive(const char *s) {
|
||||
vprint("permissive %s\n", s);
|
||||
return set_domain_state(s, 1);
|
||||
return set_domain_state(db, s, 1);
|
||||
}
|
||||
|
||||
int sepol_enforce(const char *s) {
|
||||
int sepolicy::enforce(const char *s) {
|
||||
vprint("enforce %s\n", s);
|
||||
return set_domain_state(s, 0);
|
||||
return set_domain_state(db, s, 0);
|
||||
}
|
||||
|
||||
int sepol_create(const char *s) {
|
||||
int sepolicy::create(const char *s) {
|
||||
vprint("create %s\n", s);
|
||||
return create_domain(s);
|
||||
return create_domain(db, s);
|
||||
}
|
||||
|
||||
int sepol_attradd(const char *s, const char *a) {
|
||||
vprint("attradd %s %s\n", s, a);
|
||||
return add_typeattribute(s, a);
|
||||
int sepolicy::typeattribute(const char *type, const char *attr) {
|
||||
vprint("typeattribute %s %s\n", type, attr);
|
||||
return add_typeattribute(db, type, attr);
|
||||
}
|
||||
|
||||
int sepol_genfscon(const char *name, const char *path, const char *context) {
|
||||
vprint("genfscon %s %s %s\n", name, path, context);
|
||||
return add_genfscon(name, path, context);
|
||||
int sepolicy::genfscon(const char *fs_name, const char *path, const char *ctx) {
|
||||
vprint("genfscon %s %s %s\n", fs_name, path, ctx);
|
||||
return add_genfscon(db, fs_name, path, ctx);
|
||||
}
|
||||
|
||||
int sepol_exists(const char *source) {
|
||||
return hashtab_search(magisk_policydb->p_types.table, source) != nullptr;
|
||||
int sepolicy::exists(const char *source) {
|
||||
return hashtab_search(db->p_types.table, source) != nullptr;
|
||||
}
|
||||
|
@ -40,6 +40,7 @@ int magiskpolicy_main(int argc, char *argv[]) {
|
||||
cmdline_logging();
|
||||
const char *out_file = nullptr;
|
||||
const char *rule_file = nullptr;
|
||||
sepolicy *sepol = nullptr;
|
||||
bool magisk = false;
|
||||
bool live = false;
|
||||
|
||||
@ -56,18 +57,21 @@ int magiskpolicy_main(int argc, char *argv[]) {
|
||||
else if (option == "load"sv) {
|
||||
if (argv[i + 1] == nullptr)
|
||||
usage(argv[0]);
|
||||
if (load_policydb(argv[i + 1])) {
|
||||
sepol = sepolicy::from_file(argv[i + 1]);
|
||||
if (!sepol) {
|
||||
fprintf(stderr, "Cannot load policy from %s\n", argv[i + 1]);
|
||||
return 1;
|
||||
}
|
||||
++i;
|
||||
} else if (option == "load-split"sv) {
|
||||
if (load_split_cil()) {
|
||||
sepol = sepolicy::from_split();
|
||||
if (!sepol) {
|
||||
fprintf(stderr, "Cannot load split cil\n");
|
||||
return 1;
|
||||
}
|
||||
} else if (option == "compile-split"sv) {
|
||||
if (compile_split_cil()) {
|
||||
sepol = sepolicy::compile_split();
|
||||
if (!sepol) {
|
||||
fprintf(stderr, "Cannot compile split cil\n");
|
||||
return 1;
|
||||
}
|
||||
@ -92,30 +96,30 @@ int magiskpolicy_main(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
// Use current policy if nothing is loaded
|
||||
if (magisk_policydb == nullptr && load_policydb(SELINUX_POLICY)) {
|
||||
if (sepol == nullptr && !(sepol = sepolicy::from_file(SELINUX_POLICY))) {
|
||||
fprintf(stderr, "Cannot load policy from " SELINUX_POLICY "\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (magisk)
|
||||
sepol_magisk_rules();
|
||||
sepol->magisk_rules();
|
||||
|
||||
if (rule_file)
|
||||
load_rule_file(rule_file);
|
||||
sepol->load_rule_file(rule_file);
|
||||
|
||||
for (; i < argc; ++i)
|
||||
parse_statement(argv[i]);
|
||||
sepol->parse_statement(argv[i]);
|
||||
|
||||
if (live && dump_policydb(SELINUX_LOAD)) {
|
||||
if (live && sepol->to_file(SELINUX_LOAD)) {
|
||||
fprintf(stderr, "Cannot apply policy\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (out_file && dump_policydb(out_file)) {
|
||||
if (out_file && sepol->to_file(out_file)) {
|
||||
fprintf(stderr, "Cannot dump policy to %s\n", out_file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
destroy_policydb();
|
||||
delete sepol;
|
||||
return 0;
|
||||
}
|
||||
|
@ -12,26 +12,6 @@
|
||||
|
||||
#include "sepolicy.h"
|
||||
|
||||
int load_policydb(const char *file) {
|
||||
LOGD("Load policy from: %s\n", file);
|
||||
if (magisk_policydb)
|
||||
destroy_policydb();
|
||||
|
||||
struct policy_file pf;
|
||||
policy_file_init(&pf);
|
||||
pf.fp = xfopen(file, "re");
|
||||
pf.type = PF_USE_STDIO;
|
||||
|
||||
magisk_policydb = static_cast<policydb_t *>(xmalloc(sizeof(policydb_t)));
|
||||
if (policydb_init(magisk_policydb) || policydb_read(magisk_policydb, &pf, 0)) {
|
||||
LOGE("Fail to load policy from %s\n", file);
|
||||
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};
|
||||
@ -94,17 +74,6 @@ static bool check_precompiled(const char *precompiled) {
|
||||
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;
|
||||
@ -114,15 +83,37 @@ static void load_cil(struct cil_db *db, const char *file) {
|
||||
munmap(addr, size);
|
||||
}
|
||||
|
||||
int compile_split_cil() {
|
||||
sepolicy *sepolicy::from_file(const char *file) {
|
||||
LOGD("Load policy from: %s\n", file);
|
||||
|
||||
policy_file_t pf;
|
||||
policy_file_init(&pf);
|
||||
auto fp = xopen_file(file, "re");
|
||||
pf.fp = fp.get();
|
||||
pf.type = PF_USE_STDIO;
|
||||
|
||||
auto db = static_cast<policydb_t *>(xmalloc(sizeof(policydb_t)));
|
||||
if (policydb_init(db) || policydb_read(db, &pf, 0)) {
|
||||
LOGE("Fail to load policy from %s\n", file);
|
||||
free(db);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto sepol = new sepolicy();
|
||||
sepol->db = db;
|
||||
return sepol;
|
||||
}
|
||||
|
||||
sepolicy *sepolicy::compile_split() {
|
||||
char path[128], plat_ver[10];
|
||||
struct cil_db *db = nullptr;
|
||||
cil_db_t *db = nullptr;
|
||||
sepol_policydb_t *pdb = nullptr;
|
||||
FILE *f;
|
||||
int policy_ver;
|
||||
const char *cil_file;
|
||||
|
||||
cil_db_init(&db);
|
||||
run_finally fin([db_ptr = &db]{ cil_db_destroy(db_ptr); });
|
||||
cil_set_mls(db, 1);
|
||||
cil_set_multiple_decls(db, 1);
|
||||
cil_set_disable_neverallow(db, 1);
|
||||
@ -173,29 +164,48 @@ int compile_split_cil() {
|
||||
load_cil(db, cil_file);
|
||||
|
||||
if (cil_compile(db))
|
||||
return 1;
|
||||
return nullptr;
|
||||
if (cil_build_policydb(db, &pdb))
|
||||
return 1;
|
||||
return nullptr;
|
||||
|
||||
cil_db_destroy(&db);
|
||||
magisk_policydb = &pdb->p;
|
||||
return 0;
|
||||
auto sepol = new sepolicy();
|
||||
sepol->db = &pdb->p;
|
||||
return sepol;
|
||||
}
|
||||
|
||||
int dump_policydb(const char *file) {
|
||||
sepolicy *sepolicy::from_split() {
|
||||
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 sepolicy::from_file(odm_pre);
|
||||
else if (access(vend_pre, R_OK) == 0 && check_precompiled(vend_pre))
|
||||
return sepolicy::from_file(vend_pre);
|
||||
else
|
||||
return sepolicy::compile_split();
|
||||
}
|
||||
|
||||
sepolicy::~sepolicy() {
|
||||
policydb_destroy(db);
|
||||
free(db);
|
||||
}
|
||||
|
||||
int sepolicy::to_file(const char *file) {
|
||||
uint8_t *data;
|
||||
size_t len;
|
||||
|
||||
{
|
||||
auto fp = make_stream_fp<byte_stream>(data, len);
|
||||
struct policy_file pf;
|
||||
policy_file_init(&pf);
|
||||
pf.type = PF_USE_STDIO;
|
||||
pf.fp = fp.get();
|
||||
if (policydb_write(magisk_policydb, &pf)) {
|
||||
LOGE("Fail to create policy image\n");
|
||||
return 1;
|
||||
}
|
||||
/* No partial writes are allowed to /sys/fs/selinux/load, thus the reason why we
|
||||
* first dump everything into memory, then directly call write system call */
|
||||
|
||||
auto fp = make_stream_fp<byte_stream>(data, len);
|
||||
run_finally fin([=]{ free(data); });
|
||||
|
||||
policy_file_t pf;
|
||||
policy_file_init(&pf);
|
||||
pf.type = PF_USE_STDIO;
|
||||
pf.fp = fp.get();
|
||||
if (policydb_write(db, &pf)) {
|
||||
LOGE("Fail to create policy image\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int fd = xopen(file, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0644);
|
||||
@ -204,14 +214,5 @@ int dump_policydb(const char *file) {
|
||||
xwrite(fd, data, len);
|
||||
|
||||
close(fd);
|
||||
free(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void destroy_policydb() {
|
||||
if (magisk_policydb) {
|
||||
policydb_destroy(magisk_policydb);
|
||||
free(magisk_policydb);
|
||||
magisk_policydb = nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -4,202 +4,202 @@
|
||||
|
||||
#include "sepolicy.h"
|
||||
|
||||
static void allowSuClient(const char *target) {
|
||||
if (!sepol_exists(target))
|
||||
void sepolicy::allow_su_client(const char *type) {
|
||||
if (!exists(type))
|
||||
return;
|
||||
sepol_allow(target, SEPOL_PROC_DOMAIN, "unix_stream_socket", "connectto");
|
||||
sepol_allow(target, SEPOL_PROC_DOMAIN, "unix_stream_socket", "getopt");
|
||||
sepol_allow(SEPOL_PROC_DOMAIN, target, "fd", "use");
|
||||
sepol_allow(SEPOL_PROC_DOMAIN, target, "fifo_file", ALL);
|
||||
allow(type, SEPOL_PROC_DOMAIN, "unix_stream_socket", "connectto");
|
||||
allow(type, SEPOL_PROC_DOMAIN, "unix_stream_socket", "getopt");
|
||||
allow(SEPOL_PROC_DOMAIN, type, "fd", "use");
|
||||
allow(SEPOL_PROC_DOMAIN, type, "fifo_file", ALL);
|
||||
|
||||
// Allow binder service
|
||||
sepol_allow(target, SEPOL_PROC_DOMAIN, "binder", "call");
|
||||
sepol_allow(target, SEPOL_PROC_DOMAIN, "binder", "transfer");
|
||||
allow(type, SEPOL_PROC_DOMAIN, "binder", "call");
|
||||
allow(type, SEPOL_PROC_DOMAIN, "binder", "transfer");
|
||||
|
||||
// Allow termios ioctl
|
||||
sepol_allow(target, "devpts", "chr_file", "ioctl");
|
||||
sepol_allow(target, "untrusted_app_devpts", "chr_file", "ioctl");
|
||||
sepol_allow(target, "untrusted_app_25_devpts", "chr_file", "ioctl");
|
||||
sepol_allow(target, "untrusted_app_all_devpts", "chr_file", "ioctl");
|
||||
if (magisk_policydb->policyvers >= POLICYDB_VERSION_XPERMS_IOCTL) {
|
||||
sepol_allowxperm(target, "devpts", "chr_file", "0x5400-0x54FF");
|
||||
sepol_allowxperm(target, "untrusted_app_devpts", "chr_file", "0x5400-0x54FF");
|
||||
sepol_allowxperm(target, "untrusted_app_25_devpts", "chr_file", "0x5400-0x54FF");
|
||||
sepol_allowxperm(target, "untrusted_app_all_devpts", "chr_file", "0x5400-0x54FF");
|
||||
allow(type, "devpts", "chr_file", "ioctl");
|
||||
allow(type, "untrusted_app_devpts", "chr_file", "ioctl");
|
||||
allow(type, "untrusted_app_25_devpts", "chr_file", "ioctl");
|
||||
allow(type, "untrusted_app_all_devpts", "chr_file", "ioctl");
|
||||
if (db->policyvers >= POLICYDB_VERSION_XPERMS_IOCTL) {
|
||||
allowxperm(type, "devpts", "chr_file", "0x5400-0x54FF");
|
||||
allowxperm(type, "untrusted_app_devpts", "chr_file", "0x5400-0x54FF");
|
||||
allowxperm(type, "untrusted_app_25_devpts", "chr_file", "0x5400-0x54FF");
|
||||
allowxperm(type, "untrusted_app_all_devpts", "chr_file", "0x5400-0x54FF");
|
||||
}
|
||||
}
|
||||
|
||||
void sepol_magisk_rules() {
|
||||
void sepolicy::magisk_rules() {
|
||||
// Temp suppress warnings
|
||||
auto bak = log_cb.w;
|
||||
log_cb.w = nop_log;
|
||||
|
||||
// First prevent anything to change sepolicy except ourselves
|
||||
sepol_deny(ALL, "kernel", "security", "load_policy");
|
||||
deny(ALL, "kernel", "security", "load_policy");
|
||||
|
||||
if (!sepol_exists(SEPOL_PROC_DOMAIN))
|
||||
sepol_create(SEPOL_PROC_DOMAIN);
|
||||
if (!sepol_exists(SEPOL_FILE_DOMAIN))
|
||||
sepol_create(SEPOL_FILE_DOMAIN);
|
||||
sepol_permissive(SEPOL_PROC_DOMAIN);
|
||||
if (!exists(SEPOL_PROC_DOMAIN))
|
||||
create(SEPOL_PROC_DOMAIN);
|
||||
if (!exists(SEPOL_FILE_DOMAIN))
|
||||
create(SEPOL_FILE_DOMAIN);
|
||||
permissive(SEPOL_PROC_DOMAIN);
|
||||
|
||||
sepol_attradd(SEPOL_PROC_DOMAIN, "mlstrustedsubject");
|
||||
sepol_attradd(SEPOL_PROC_DOMAIN, "netdomain");
|
||||
sepol_attradd(SEPOL_PROC_DOMAIN, "bluetoothdomain");
|
||||
sepol_attradd(SEPOL_FILE_DOMAIN, "mlstrustedobject");
|
||||
typeattribute(SEPOL_PROC_DOMAIN, "mlstrustedsubject");
|
||||
typeattribute(SEPOL_PROC_DOMAIN, "netdomain");
|
||||
typeattribute(SEPOL_PROC_DOMAIN, "bluetoothdomain");
|
||||
typeattribute(SEPOL_FILE_DOMAIN, "mlstrustedobject");
|
||||
|
||||
// Let everyone access tmpfs files (for SAR sbin overlay)
|
||||
sepol_allow(ALL, "tmpfs", "file", ALL);
|
||||
allow(ALL, "tmpfs", "file", ALL);
|
||||
|
||||
// For normal rootfs file/directory operations when rw (for SAR / overlay)
|
||||
sepol_allow("rootfs", "labeledfs", "filesystem", "associate");
|
||||
allow("rootfs", "labeledfs", "filesystem", "associate");
|
||||
|
||||
// Let init transit to SEPOL_PROC_DOMAIN
|
||||
sepol_allow("kernel", "kernel", "process", "setcurrent");
|
||||
sepol_allow("kernel", SEPOL_PROC_DOMAIN, "process", "dyntransition");
|
||||
allow("kernel", "kernel", "process", "setcurrent");
|
||||
allow("kernel", SEPOL_PROC_DOMAIN, "process", "dyntransition");
|
||||
|
||||
// Let init run stuffs
|
||||
sepol_allow("kernel", SEPOL_PROC_DOMAIN, "fd", "use");
|
||||
sepol_allow("init", SEPOL_PROC_DOMAIN, "process", ALL);
|
||||
sepol_allow("init", "tmpfs", "file", "getattr");
|
||||
sepol_allow("init", "tmpfs", "file", "execute");
|
||||
allow("kernel", SEPOL_PROC_DOMAIN, "fd", "use");
|
||||
allow("init", SEPOL_PROC_DOMAIN, "process", ALL);
|
||||
allow("init", "tmpfs", "file", "getattr");
|
||||
allow("init", "tmpfs", "file", "execute");
|
||||
|
||||
// Shell, properties, logs
|
||||
if (sepol_exists("default_prop"))
|
||||
sepol_allow(SEPOL_PROC_DOMAIN, "default_prop", "property_service", "set");
|
||||
sepol_allow(SEPOL_PROC_DOMAIN, "init", "unix_stream_socket", "connectto");
|
||||
sepol_allow(SEPOL_PROC_DOMAIN, "rootfs", "filesystem", "remount");
|
||||
if (sepol_exists("logd"))
|
||||
sepol_allow(SEPOL_PROC_DOMAIN, "logd", "unix_stream_socket", "connectto");
|
||||
sepol_allow(SEPOL_PROC_DOMAIN, SEPOL_PROC_DOMAIN, ALL, ALL);
|
||||
if (exists("default_prop"))
|
||||
allow(SEPOL_PROC_DOMAIN, "default_prop", "property_service", "set");
|
||||
allow(SEPOL_PROC_DOMAIN, "init", "unix_stream_socket", "connectto");
|
||||
allow(SEPOL_PROC_DOMAIN, "rootfs", "filesystem", "remount");
|
||||
if (exists("logd"))
|
||||
allow(SEPOL_PROC_DOMAIN, "logd", "unix_stream_socket", "connectto");
|
||||
allow(SEPOL_PROC_DOMAIN, SEPOL_PROC_DOMAIN, ALL, ALL);
|
||||
|
||||
// For sepolicy live patching
|
||||
sepol_allow(SEPOL_PROC_DOMAIN, "kernel", "security", "read_policy");
|
||||
sepol_allow(SEPOL_PROC_DOMAIN, "kernel", "security", "load_policy");
|
||||
allow(SEPOL_PROC_DOMAIN, "kernel", "security", "read_policy");
|
||||
allow(SEPOL_PROC_DOMAIN, "kernel", "security", "load_policy");
|
||||
|
||||
// Allow these processes to access MagiskSU
|
||||
allowSuClient("init");
|
||||
allowSuClient("shell");
|
||||
allowSuClient("system_app");
|
||||
allowSuClient("priv_app");
|
||||
allowSuClient("platform_app");
|
||||
allowSuClient("untrusted_app");
|
||||
allowSuClient("untrusted_app_25");
|
||||
allowSuClient("untrusted_app_27");
|
||||
allowSuClient("untrusted_app_29");
|
||||
allowSuClient("update_engine");
|
||||
allow_su_client("init");
|
||||
allow_su_client("shell");
|
||||
allow_su_client("system_app");
|
||||
allow_su_client("priv_app");
|
||||
allow_su_client("platform_app");
|
||||
allow_su_client("untrusted_app");
|
||||
allow_su_client("untrusted_app_25");
|
||||
allow_su_client("untrusted_app_27");
|
||||
allow_su_client("untrusted_app_29");
|
||||
allow_su_client("update_engine");
|
||||
|
||||
// suRights
|
||||
sepol_allow("servicemanager", SEPOL_PROC_DOMAIN, "dir", "search");
|
||||
sepol_allow("servicemanager", SEPOL_PROC_DOMAIN, "dir", "read");
|
||||
sepol_allow("servicemanager", SEPOL_PROC_DOMAIN, "file", "open");
|
||||
sepol_allow("servicemanager", SEPOL_PROC_DOMAIN, "file", "read");
|
||||
sepol_allow("servicemanager", SEPOL_PROC_DOMAIN, "process", "getattr");
|
||||
sepol_allow("servicemanager", SEPOL_PROC_DOMAIN, "binder", "transfer");
|
||||
sepol_allow(SEPOL_PROC_DOMAIN, "servicemanager", "dir", "search");
|
||||
sepol_allow(SEPOL_PROC_DOMAIN, "servicemanager", "dir", "read");
|
||||
sepol_allow(SEPOL_PROC_DOMAIN, "servicemanager", "file", "open");
|
||||
sepol_allow(SEPOL_PROC_DOMAIN, "servicemanager", "file", "read");
|
||||
sepol_allow(SEPOL_PROC_DOMAIN, "servicemanager", "process", "getattr");
|
||||
sepol_allow(SEPOL_PROC_DOMAIN, "servicemanager", "binder", "transfer");
|
||||
sepol_allow(SEPOL_PROC_DOMAIN, "servicemanager", "binder", "call");
|
||||
sepol_allow(ALL, SEPOL_PROC_DOMAIN, "process", "sigchld");
|
||||
allow("servicemanager", SEPOL_PROC_DOMAIN, "dir", "search");
|
||||
allow("servicemanager", SEPOL_PROC_DOMAIN, "dir", "read");
|
||||
allow("servicemanager", SEPOL_PROC_DOMAIN, "file", "open");
|
||||
allow("servicemanager", SEPOL_PROC_DOMAIN, "file", "read");
|
||||
allow("servicemanager", SEPOL_PROC_DOMAIN, "process", "getattr");
|
||||
allow("servicemanager", SEPOL_PROC_DOMAIN, "binder", "transfer");
|
||||
allow(SEPOL_PROC_DOMAIN, "servicemanager", "dir", "search");
|
||||
allow(SEPOL_PROC_DOMAIN, "servicemanager", "dir", "read");
|
||||
allow(SEPOL_PROC_DOMAIN, "servicemanager", "file", "open");
|
||||
allow(SEPOL_PROC_DOMAIN, "servicemanager", "file", "read");
|
||||
allow(SEPOL_PROC_DOMAIN, "servicemanager", "process", "getattr");
|
||||
allow(SEPOL_PROC_DOMAIN, "servicemanager", "binder", "transfer");
|
||||
allow(SEPOL_PROC_DOMAIN, "servicemanager", "binder", "call");
|
||||
allow(ALL, SEPOL_PROC_DOMAIN, "process", "sigchld");
|
||||
|
||||
// allowLog
|
||||
sepol_allow("logd", SEPOL_PROC_DOMAIN, "dir", "search");
|
||||
sepol_allow("logd", SEPOL_PROC_DOMAIN, "file", "read");
|
||||
sepol_allow("logd", SEPOL_PROC_DOMAIN, "file", "open");
|
||||
sepol_allow("logd", SEPOL_PROC_DOMAIN, "file", "getattr");
|
||||
allow("logd", SEPOL_PROC_DOMAIN, "dir", "search");
|
||||
allow("logd", SEPOL_PROC_DOMAIN, "file", "read");
|
||||
allow("logd", SEPOL_PROC_DOMAIN, "file", "open");
|
||||
allow("logd", SEPOL_PROC_DOMAIN, "file", "getattr");
|
||||
|
||||
// suBackL0
|
||||
sepol_allow("system_server", SEPOL_PROC_DOMAIN, "binder", "call");
|
||||
sepol_allow("system_server", SEPOL_PROC_DOMAIN, "binder", "transfer");
|
||||
sepol_allow(SEPOL_PROC_DOMAIN, "system_server", "binder", "call");
|
||||
sepol_allow(SEPOL_PROC_DOMAIN, "system_server", "binder", "transfer");
|
||||
allow("system_server", SEPOL_PROC_DOMAIN, "binder", "call");
|
||||
allow("system_server", SEPOL_PROC_DOMAIN, "binder", "transfer");
|
||||
allow(SEPOL_PROC_DOMAIN, "system_server", "binder", "call");
|
||||
allow(SEPOL_PROC_DOMAIN, "system_server", "binder", "transfer");
|
||||
|
||||
// suBackL6
|
||||
sepol_allow("surfaceflinger", "app_data_file", "dir", ALL);
|
||||
sepol_allow("surfaceflinger", "app_data_file", "file", ALL);
|
||||
sepol_allow("surfaceflinger", "app_data_file", "lnk_file", ALL);
|
||||
sepol_attradd("surfaceflinger", "mlstrustedsubject");
|
||||
allow("surfaceflinger", "app_data_file", "dir", ALL);
|
||||
allow("surfaceflinger", "app_data_file", "file", ALL);
|
||||
allow("surfaceflinger", "app_data_file", "lnk_file", ALL);
|
||||
typeattribute("surfaceflinger", "mlstrustedsubject");
|
||||
|
||||
// suMiscL6
|
||||
if (sepol_exists("audioserver"))
|
||||
sepol_allow("audioserver", "audioserver", "process", "execmem");
|
||||
if (exists("audioserver"))
|
||||
allow("audioserver", "audioserver", "process", "execmem");
|
||||
|
||||
// Liveboot
|
||||
sepol_allow("surfaceflinger", SEPOL_PROC_DOMAIN, "process", "ptrace");
|
||||
sepol_allow("surfaceflinger", SEPOL_PROC_DOMAIN, "binder", "transfer");
|
||||
sepol_allow("surfaceflinger", SEPOL_PROC_DOMAIN, "binder", "call");
|
||||
sepol_allow("surfaceflinger", SEPOL_PROC_DOMAIN, "fd", "use");
|
||||
sepol_allow("debuggerd", SEPOL_PROC_DOMAIN, "process", "ptrace");
|
||||
allow("surfaceflinger", SEPOL_PROC_DOMAIN, "process", "ptrace");
|
||||
allow("surfaceflinger", SEPOL_PROC_DOMAIN, "binder", "transfer");
|
||||
allow("surfaceflinger", SEPOL_PROC_DOMAIN, "binder", "call");
|
||||
allow("surfaceflinger", SEPOL_PROC_DOMAIN, "fd", "use");
|
||||
allow("debuggerd", SEPOL_PROC_DOMAIN, "process", "ptrace");
|
||||
|
||||
// dumpsys
|
||||
sepol_allow(ALL, SEPOL_PROC_DOMAIN, "fd", "use");
|
||||
sepol_allow(ALL, SEPOL_PROC_DOMAIN, "fifo_file", "write");
|
||||
sepol_allow(ALL, SEPOL_PROC_DOMAIN, "fifo_file", "read");
|
||||
sepol_allow(ALL, SEPOL_PROC_DOMAIN, "fifo_file", "open");
|
||||
sepol_allow(ALL, SEPOL_PROC_DOMAIN, "fifo_file", "getattr");
|
||||
allow(ALL, SEPOL_PROC_DOMAIN, "fd", "use");
|
||||
allow(ALL, SEPOL_PROC_DOMAIN, "fifo_file", "write");
|
||||
allow(ALL, SEPOL_PROC_DOMAIN, "fifo_file", "read");
|
||||
allow(ALL, SEPOL_PROC_DOMAIN, "fifo_file", "open");
|
||||
allow(ALL, SEPOL_PROC_DOMAIN, "fifo_file", "getattr");
|
||||
|
||||
// bootctl
|
||||
sepol_allow("hwservicemanager", SEPOL_PROC_DOMAIN, "dir", "search");
|
||||
sepol_allow("hwservicemanager", SEPOL_PROC_DOMAIN, "file", "read");
|
||||
sepol_allow("hwservicemanager", SEPOL_PROC_DOMAIN, "file", "open");
|
||||
sepol_allow("hwservicemanager", SEPOL_PROC_DOMAIN, "process", "getattr");
|
||||
sepol_allow("hwservicemanager", SEPOL_PROC_DOMAIN, "binder", "transfer");
|
||||
allow("hwservicemanager", SEPOL_PROC_DOMAIN, "dir", "search");
|
||||
allow("hwservicemanager", SEPOL_PROC_DOMAIN, "file", "read");
|
||||
allow("hwservicemanager", SEPOL_PROC_DOMAIN, "file", "open");
|
||||
allow("hwservicemanager", SEPOL_PROC_DOMAIN, "process", "getattr");
|
||||
allow("hwservicemanager", SEPOL_PROC_DOMAIN, "binder", "transfer");
|
||||
|
||||
// For mounting loop devices, mirrors, tmpfs
|
||||
sepol_allow(SEPOL_PROC_DOMAIN, "kernel", "process", "setsched");
|
||||
sepol_allow(SEPOL_PROC_DOMAIN, "labeledfs", "filesystem", "mount");
|
||||
sepol_allow(SEPOL_PROC_DOMAIN, "labeledfs", "filesystem", "unmount");
|
||||
sepol_allow(SEPOL_PROC_DOMAIN, "tmpfs", "filesystem", "mount");
|
||||
sepol_allow(SEPOL_PROC_DOMAIN, "tmpfs", "filesystem", "unmount");
|
||||
sepol_allow("kernel", ALL, "file", "read");
|
||||
sepol_allow("kernel", ALL, "file", "write");
|
||||
allow(SEPOL_PROC_DOMAIN, "kernel", "process", "setsched");
|
||||
allow(SEPOL_PROC_DOMAIN, "labeledfs", "filesystem", "mount");
|
||||
allow(SEPOL_PROC_DOMAIN, "labeledfs", "filesystem", "unmount");
|
||||
allow(SEPOL_PROC_DOMAIN, "tmpfs", "filesystem", "mount");
|
||||
allow(SEPOL_PROC_DOMAIN, "tmpfs", "filesystem", "unmount");
|
||||
allow("kernel", ALL, "file", "read");
|
||||
allow("kernel", ALL, "file", "write");
|
||||
|
||||
// Allow us to do anything to any files/dir/links
|
||||
sepol_allow(SEPOL_PROC_DOMAIN, ALL, "file", ALL);
|
||||
sepol_allow(SEPOL_PROC_DOMAIN, ALL, "dir", ALL);
|
||||
sepol_allow(SEPOL_PROC_DOMAIN, ALL, "lnk_file", ALL);
|
||||
sepol_allow(SEPOL_PROC_DOMAIN, ALL, "blk_file", ALL);
|
||||
sepol_allow(SEPOL_PROC_DOMAIN, ALL, "sock_file", ALL);
|
||||
sepol_allow(SEPOL_PROC_DOMAIN, ALL, "chr_file", ALL);
|
||||
sepol_allow(SEPOL_PROC_DOMAIN, ALL, "fifo_file", ALL);
|
||||
allow(SEPOL_PROC_DOMAIN, ALL, "file", ALL);
|
||||
allow(SEPOL_PROC_DOMAIN, ALL, "dir", ALL);
|
||||
allow(SEPOL_PROC_DOMAIN, ALL, "lnk_file", ALL);
|
||||
allow(SEPOL_PROC_DOMAIN, ALL, "blk_file", ALL);
|
||||
allow(SEPOL_PROC_DOMAIN, ALL, "sock_file", ALL);
|
||||
allow(SEPOL_PROC_DOMAIN, ALL, "chr_file", ALL);
|
||||
allow(SEPOL_PROC_DOMAIN, ALL, "fifo_file", ALL);
|
||||
|
||||
// Allow us to do any ioctl on all block devices
|
||||
if (magisk_policydb->policyvers >= POLICYDB_VERSION_XPERMS_IOCTL)
|
||||
sepol_allowxperm(SEPOL_PROC_DOMAIN, ALL, "blk_file", "0x0000-0xFFFF");
|
||||
if (db->policyvers >= POLICYDB_VERSION_XPERMS_IOCTL)
|
||||
allowxperm(SEPOL_PROC_DOMAIN, ALL, "blk_file", "0x0000-0xFFFF");
|
||||
|
||||
// Allow all binder transactions
|
||||
sepol_allow(ALL, SEPOL_PROC_DOMAIN, "binder", ALL);
|
||||
allow(ALL, SEPOL_PROC_DOMAIN, "binder", ALL);
|
||||
|
||||
// Super files
|
||||
sepol_allow(ALL, SEPOL_FILE_DOMAIN, "file", ALL);
|
||||
sepol_allow(ALL, SEPOL_FILE_DOMAIN, "dir", ALL);
|
||||
sepol_allow(ALL, SEPOL_FILE_DOMAIN, "fifo_file", ALL);
|
||||
sepol_allow(ALL, SEPOL_FILE_DOMAIN, "chr_file", ALL);
|
||||
sepol_allow(SEPOL_FILE_DOMAIN, ALL, "filesystem", "associate");
|
||||
allow(ALL, SEPOL_FILE_DOMAIN, "file", ALL);
|
||||
allow(ALL, SEPOL_FILE_DOMAIN, "dir", ALL);
|
||||
allow(ALL, SEPOL_FILE_DOMAIN, "fifo_file", ALL);
|
||||
allow(ALL, SEPOL_FILE_DOMAIN, "chr_file", ALL);
|
||||
allow(SEPOL_FILE_DOMAIN, ALL, "filesystem", "associate");
|
||||
|
||||
// For changing attributes
|
||||
sepol_allow("rootfs", "tmpfs", "filesystem", "associate");
|
||||
allow("rootfs", "tmpfs", "filesystem", "associate");
|
||||
|
||||
// Xposed
|
||||
sepol_allow("untrusted_app", "untrusted_app", "capability", "setgid");
|
||||
sepol_allow("system_server", "dex2oat_exec", "file", ALL);
|
||||
allow("untrusted_app", "untrusted_app", "capability", "setgid");
|
||||
allow("system_server", "dex2oat_exec", "file", ALL);
|
||||
|
||||
// Support deodexed ROM on Oreo
|
||||
sepol_allow("zygote", "dalvikcache_data_file", "file", "execute");
|
||||
allow("zygote", "dalvikcache_data_file", "file", "execute");
|
||||
|
||||
// Support deodexed ROM on Pie (Samsung)
|
||||
sepol_allow("system_server", "dalvikcache_data_file", "file", "write");
|
||||
sepol_allow("system_server", "dalvikcache_data_file", "file", "execute");
|
||||
allow("system_server", "dalvikcache_data_file", "file", "write");
|
||||
allow("system_server", "dalvikcache_data_file", "file", "execute");
|
||||
|
||||
// Allow update_engine/addon.d-v2 to run permissive on all ROMs
|
||||
sepol_permissive("update_engine");
|
||||
permissive("update_engine");
|
||||
|
||||
#if 0
|
||||
// Remove all dontaudit in debug mode
|
||||
strip_dontaudit();
|
||||
strip_dontaudit(db);
|
||||
#endif
|
||||
|
||||
log_cb.w = bak;
|
||||
|
@ -5,9 +5,6 @@
|
||||
|
||||
#include "sepolicy.h"
|
||||
|
||||
policydb_t *magisk_policydb = NULL;
|
||||
#define mpdb magisk_policydb
|
||||
|
||||
extern void *xmalloc(size_t size);
|
||||
extern void *xcalloc(size_t nmemb, size_t size);
|
||||
extern void *xrealloc(void *ptr, size_t size);
|
||||
@ -39,20 +36,20 @@ hash_for_each(htable, size, hashtab, block)
|
||||
#define avtab_for_each(avtab, block) \
|
||||
hash_for_each(htable, nslot, avtab, block)
|
||||
|
||||
static int set_attr(const char *type, int value) {
|
||||
type_datum_t *attr = hashtab_search(mpdb->p_types.table, type);
|
||||
static int set_attr(policydb_t *db, const char *type, int value) {
|
||||
type_datum_t *attr = hashtab_search(db->p_types.table, type);
|
||||
if (!attr || attr->flavor != TYPE_ATTRIB)
|
||||
return -1;
|
||||
|
||||
if (ebitmap_set_bit(&mpdb->type_attr_map[value - 1], attr->s.value - 1, 1))
|
||||
if (ebitmap_set_bit(&db->type_attr_map[value - 1], attr->s.value - 1, 1))
|
||||
return -1;
|
||||
if (ebitmap_set_bit(&mpdb->attr_type_map[attr->s.value - 1], value - 1, 1))
|
||||
if (ebitmap_set_bit(&db->attr_type_map[attr->s.value - 1], value - 1, 1))
|
||||
return -1;
|
||||
|
||||
return attr->s.value;
|
||||
}
|
||||
|
||||
static void check_avtab_node(avtab_ptr_t node) {
|
||||
static void check_avtab_node(policydb_t *db, avtab_ptr_t node) {
|
||||
int redundant = 0;
|
||||
if (node->key.specified == AVTAB_AUDITDENY)
|
||||
redundant = node->datum.data == ~0U;
|
||||
@ -61,17 +58,17 @@ static void check_avtab_node(avtab_ptr_t node) {
|
||||
else
|
||||
redundant = node->datum.data == 0U;
|
||||
if (redundant)
|
||||
avtab_remove_node(&mpdb->te_avtab, node);
|
||||
avtab_remove_node(&db->te_avtab, node);
|
||||
}
|
||||
|
||||
static avtab_ptr_t get_avtab_node(avtab_key_t *key, avtab_extended_perms_t *xperms) {
|
||||
static avtab_ptr_t get_avtab_node(policydb_t *db, avtab_key_t *key, avtab_extended_perms_t *xperms) {
|
||||
avtab_ptr_t node;
|
||||
avtab_datum_t avdatum;
|
||||
int match = 0;
|
||||
|
||||
/* AVTAB_XPERMS entries are not necessarily unique */
|
||||
if (key->specified & AVTAB_XPERMS) {
|
||||
node = avtab_search_node(&mpdb->te_avtab, key);
|
||||
node = avtab_search_node(&db->te_avtab, key);
|
||||
while (node) {
|
||||
if ((node->datum.xperms->specified == xperms->specified) &&
|
||||
(node->datum.xperms->driver == xperms->driver)) {
|
||||
@ -83,7 +80,7 @@ static avtab_ptr_t get_avtab_node(avtab_key_t *key, avtab_extended_perms_t *xper
|
||||
if (!match)
|
||||
node = NULL;
|
||||
} else {
|
||||
node = avtab_search_node(&mpdb->te_avtab, key);
|
||||
node = avtab_search_node(&db->te_avtab, key);
|
||||
}
|
||||
|
||||
if (!node) {
|
||||
@ -94,14 +91,14 @@ static avtab_ptr_t get_avtab_node(avtab_key_t *key, avtab_extended_perms_t *xper
|
||||
*/
|
||||
avdatum.data = key->specified == AVTAB_AUDITDENY ? ~0U : 0U;
|
||||
/* this is used to get the node - insertion is actually unique */
|
||||
node = avtab_insert_nonunique(&mpdb->te_avtab, key, &avdatum);
|
||||
node = avtab_insert_nonunique(&db->te_avtab, key, &avdatum);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static int add_avrule(avtab_key_t *key, int val, int not) {
|
||||
avtab_ptr_t node = get_avtab_node(key, NULL);
|
||||
static int add_avrule(policydb_t *db, avtab_key_t *key, int val, int not) {
|
||||
avtab_ptr_t node = get_avtab_node(NULL, key, NULL);
|
||||
|
||||
if (not) {
|
||||
if (val < 0)
|
||||
@ -115,36 +112,36 @@ static int add_avrule(avtab_key_t *key, int val, int not) {
|
||||
node->datum.data |= 1U << (val - 1);
|
||||
}
|
||||
|
||||
check_avtab_node(node);
|
||||
check_avtab_node(db, node);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int add_rule_auto(type_datum_t *src, type_datum_t *tgt, class_datum_t *cls,
|
||||
static int add_rule_auto(policydb_t *db, type_datum_t *src, type_datum_t *tgt, class_datum_t *cls,
|
||||
perm_datum_t *perm, int effect, int not) {
|
||||
avtab_key_t key;
|
||||
int ret = 0;
|
||||
|
||||
if (src == NULL) {
|
||||
hashtab_for_each(mpdb->p_types.table, {
|
||||
hashtab_for_each(db->p_types.table, {
|
||||
src = node->datum;
|
||||
ret |= add_rule_auto(src, tgt, cls, perm, effect, not);
|
||||
ret |= add_rule_auto(db, src, tgt, cls, perm, effect, not);
|
||||
})
|
||||
} else if (tgt == NULL) {
|
||||
hashtab_for_each(mpdb->p_types.table, {
|
||||
hashtab_for_each(db->p_types.table, {
|
||||
tgt = node->datum;
|
||||
ret |= add_rule_auto(src, tgt, cls, perm, effect, not);
|
||||
ret |= add_rule_auto(db, src, tgt, cls, perm, effect, not);
|
||||
})
|
||||
} else if (cls == NULL) {
|
||||
hashtab_for_each(mpdb->p_classes.table, {
|
||||
hashtab_for_each(db->p_classes.table, {
|
||||
cls = node->datum;
|
||||
ret |= add_rule_auto(src, tgt, cls, perm, effect, not);
|
||||
ret |= add_rule_auto(db, src, tgt, cls, perm, effect, not);
|
||||
})
|
||||
} else {
|
||||
key.source_type = src->s.value;
|
||||
key.target_type = tgt->s.value;
|
||||
key.target_class = cls->s.value;
|
||||
key.specified = effect;
|
||||
return add_avrule(&key, perm ? perm->s.value : -1, not);
|
||||
return add_avrule(db, &key, perm ? perm->s.value : -1, not);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -152,7 +149,7 @@ static int add_rule_auto(type_datum_t *src, type_datum_t *tgt, class_datum_t *cl
|
||||
#define ioctl_driver(x) (x>>8 & 0xFF)
|
||||
#define ioctl_func(x) (x & 0xFF)
|
||||
|
||||
static int add_avxrule(avtab_key_t *key, uint16_t low, uint16_t high, int not) {
|
||||
static int add_avxrule(policydb_t *db, avtab_key_t *key, uint16_t low, uint16_t high, int not) {
|
||||
avtab_datum_t *datum;
|
||||
avtab_extended_perms_t xperms;
|
||||
|
||||
@ -181,7 +178,7 @@ static int add_avxrule(avtab_key_t *key, uint16_t low, uint16_t high, int not) {
|
||||
}
|
||||
}
|
||||
|
||||
datum = &get_avtab_node(key, &xperms)->datum;
|
||||
datum = &get_avtab_node(db, key, &xperms)->datum;
|
||||
|
||||
if (datum->xperms == NULL)
|
||||
datum->xperms = xmalloc(sizeof(xperms));
|
||||
@ -190,38 +187,38 @@ static int add_avxrule(avtab_key_t *key, uint16_t low, uint16_t high, int not) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int add_xperm_rule_auto(type_datum_t *src, type_datum_t *tgt, class_datum_t *cls,
|
||||
uint16_t low, uint16_t high, int effect, int not) {
|
||||
static int add_xperm_rule_auto(policydb_t *db, type_datum_t *src, type_datum_t *tgt,
|
||||
class_datum_t *cls, uint16_t low, uint16_t high, int effect, int not) {
|
||||
avtab_key_t key;
|
||||
int ret = 0;
|
||||
|
||||
if (src == NULL) {
|
||||
hashtab_for_each(mpdb->p_types.table, {
|
||||
hashtab_for_each(db->p_types.table, {
|
||||
src = node->datum;
|
||||
ret |= add_xperm_rule_auto(src, tgt, cls, low, high, effect, not);
|
||||
ret |= add_xperm_rule_auto(db, src, tgt, cls, low, high, effect, not);
|
||||
})
|
||||
} else if (tgt == NULL) {
|
||||
hashtab_for_each(mpdb->p_types.table, {
|
||||
hashtab_for_each(db->p_types.table, {
|
||||
tgt = node->datum;
|
||||
ret |= add_xperm_rule_auto(src, tgt, cls, low, high, effect, not);
|
||||
ret |= add_xperm_rule_auto(db, src, tgt, cls, low, high, effect, not);
|
||||
})
|
||||
} else if (cls == NULL) {
|
||||
hashtab_for_each(mpdb->p_classes.table, {
|
||||
hashtab_for_each(db->p_classes.table, {
|
||||
cls = node->datum;
|
||||
ret |= add_xperm_rule_auto(src, tgt, cls, low, high, effect, not);
|
||||
ret |= add_xperm_rule_auto(db, src, tgt, cls, low, high, effect, not);
|
||||
})
|
||||
} else {
|
||||
key.source_type = src->s.value;
|
||||
key.target_type = tgt->s.value;
|
||||
key.target_class = cls->s.value;
|
||||
key.specified = effect;
|
||||
return add_avxrule(&key, low, high, not);
|
||||
return add_avxrule(db, &key, low, high, not);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int create_domain(const char *d) {
|
||||
symtab_datum_t *src = hashtab_search(mpdb->p_types.table, d);
|
||||
int create_domain(policydb_t *db, const char *d) {
|
||||
symtab_datum_t *src = hashtab_search(db->p_types.table, d);
|
||||
if (src) {
|
||||
LOGW("Domain %s already exists\n", d);
|
||||
return 0;
|
||||
@ -233,60 +230,60 @@ int create_domain(const char *d) {
|
||||
typedatum->flavor = TYPE_TYPE;
|
||||
|
||||
uint32_t value = 0;
|
||||
symtab_insert(mpdb, SYM_TYPES, strdup(d), typedatum, SCOPE_DECL, 1, &value);
|
||||
symtab_insert(db, SYM_TYPES, strdup(d), typedatum, SCOPE_DECL, 1, &value);
|
||||
typedatum->s.value = value;
|
||||
|
||||
if (ebitmap_set_bit(&mpdb->global->branch_list->declared.scope[SYM_TYPES], value - 1, 1)) {
|
||||
if (ebitmap_set_bit(&db->global->branch_list->declared.scope[SYM_TYPES], value - 1, 1)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
mpdb->type_attr_map = xrealloc(mpdb->type_attr_map, sizeof(ebitmap_t) * mpdb->p_types.nprim);
|
||||
mpdb->attr_type_map = xrealloc(mpdb->attr_type_map, sizeof(ebitmap_t) * mpdb->p_types.nprim);
|
||||
ebitmap_init(&mpdb->type_attr_map[value-1]);
|
||||
ebitmap_init(&mpdb->attr_type_map[value-1]);
|
||||
ebitmap_set_bit(&mpdb->type_attr_map[value-1], value-1, 1);
|
||||
db->type_attr_map = xrealloc(db->type_attr_map, sizeof(ebitmap_t) * db->p_types.nprim);
|
||||
db->attr_type_map = xrealloc(db->attr_type_map, sizeof(ebitmap_t) * db->p_types.nprim);
|
||||
ebitmap_init(&db->type_attr_map[value-1]);
|
||||
ebitmap_init(&db->attr_type_map[value-1]);
|
||||
ebitmap_set_bit(&db->type_attr_map[value-1], value-1, 1);
|
||||
|
||||
src = hashtab_search(mpdb->p_types.table, d);
|
||||
if(!src)
|
||||
src = hashtab_search(db->p_types.table, d);
|
||||
if (!src)
|
||||
return 1;
|
||||
|
||||
if(policydb_index_decls(NULL, mpdb))
|
||||
if (policydb_index_decls(NULL, db))
|
||||
return 1;
|
||||
|
||||
if(policydb_index_classes(mpdb))
|
||||
if (policydb_index_classes(db))
|
||||
return 1;
|
||||
|
||||
if(policydb_index_others(NULL, mpdb, 0))
|
||||
if (policydb_index_others(NULL, db, 0))
|
||||
return 1;
|
||||
|
||||
//Add the domain to all roles
|
||||
for(unsigned i = 0; i < mpdb->p_roles.nprim; ++i) {
|
||||
//Not sure all those three calls are needed
|
||||
ebitmap_set_bit(&mpdb->role_val_to_struct[i]->types.negset, value - 1, 0);
|
||||
ebitmap_set_bit(&mpdb->role_val_to_struct[i]->types.types, value - 1, 1);
|
||||
type_set_expand(&mpdb->role_val_to_struct[i]->types, &mpdb->role_val_to_struct[i]->cache, mpdb, 0);
|
||||
// Add the domain to all roles
|
||||
for (unsigned i = 0; i < db->p_roles.nprim; ++i) {
|
||||
// Not sure all those three calls are needed
|
||||
ebitmap_set_bit(&db->role_val_to_struct[i]->types.negset, value - 1, 0);
|
||||
ebitmap_set_bit(&db->role_val_to_struct[i]->types.types, value - 1, 1);
|
||||
type_set_expand(&db->role_val_to_struct[i]->types, &db->role_val_to_struct[i]->cache, db, 0);
|
||||
}
|
||||
|
||||
return set_attr("domain", value);
|
||||
return set_attr(db, "domain", value);
|
||||
}
|
||||
|
||||
int set_domain_state(const char *s, int state) {
|
||||
int set_domain_state(policydb_t *db, const char *s, int state) {
|
||||
type_datum_t *type;
|
||||
if (s == NULL) {
|
||||
hashtab_for_each(mpdb->p_types.table, {
|
||||
hashtab_for_each(db->p_types.table, {
|
||||
type = node->datum;
|
||||
if (ebitmap_set_bit(&mpdb->permissive_map, type->s.value, state)) {
|
||||
if (ebitmap_set_bit(&db->permissive_map, type->s.value, state)) {
|
||||
LOGW("Could not set bit in permissive map\n");
|
||||
return 1;
|
||||
}
|
||||
})
|
||||
} else {
|
||||
type = hashtab_search(mpdb->p_types.table, s);
|
||||
type = hashtab_search(db->p_types.table, s);
|
||||
if (type == NULL) {
|
||||
LOGW("type %s does not exist\n", s);
|
||||
return 1;
|
||||
}
|
||||
if (ebitmap_set_bit(&mpdb->permissive_map, type->s.value, state)) {
|
||||
if (ebitmap_set_bit(&db->permissive_map, type->s.value, state)) {
|
||||
LOGW("Could not set bit in permissive map\n");
|
||||
return 1;
|
||||
}
|
||||
@ -295,26 +292,27 @@ int set_domain_state(const char *s, int state) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int add_filename_trans(const char *s, const char *t, const char *c, const char *d, const char *o) {
|
||||
int add_filename_trans(policydb_t *db, const char *s, const char *t, const char *c, const char *d,
|
||||
const char *o) {
|
||||
type_datum_t *src, *tgt, *def;
|
||||
class_datum_t *cls;
|
||||
|
||||
src = hashtab_search(mpdb->p_types.table, s);
|
||||
src = hashtab_search(db->p_types.table, s);
|
||||
if (src == NULL) {
|
||||
LOGW("source type %s does not exist\n", s);
|
||||
return 1;
|
||||
}
|
||||
tgt = hashtab_search(mpdb->p_types.table, t);
|
||||
tgt = hashtab_search(db->p_types.table, t);
|
||||
if (tgt == NULL) {
|
||||
LOGW("target type %s does not exist\n", t);
|
||||
return 1;
|
||||
}
|
||||
cls = hashtab_search(mpdb->p_classes.table, c);
|
||||
cls = hashtab_search(db->p_classes.table, c);
|
||||
if (cls == NULL) {
|
||||
LOGW("class %s does not exist\n", c);
|
||||
return 1;
|
||||
}
|
||||
def = hashtab_search(mpdb->p_types.table, d);
|
||||
def = hashtab_search(db->p_types.table, d);
|
||||
if (def == NULL) {
|
||||
LOGW("default type %s does not exist\n", d);
|
||||
return 1;
|
||||
@ -327,11 +325,11 @@ int add_filename_trans(const char *s, const char *t, const char *c, const char *
|
||||
trans_key.name = (char *) o;
|
||||
|
||||
filename_trans_datum_t *trans_datum;
|
||||
trans_datum = hashtab_search(mpdb->filename_trans, (hashtab_key_t) &trans_key);
|
||||
trans_datum = hashtab_search(db->filename_trans, (hashtab_key_t) &trans_key);
|
||||
|
||||
if (trans_datum == NULL) {
|
||||
trans_datum = xcalloc(sizeof(*trans_datum), 1);
|
||||
hashtab_insert(mpdb->filename_trans, (hashtab_key_t) &trans_key, trans_datum);
|
||||
hashtab_insert(db->filename_trans, (hashtab_key_t) &trans_key, trans_datum);
|
||||
}
|
||||
|
||||
// Overwrite existing
|
||||
@ -339,18 +337,18 @@ int add_filename_trans(const char *s, const char *t, const char *c, const char *
|
||||
return 0;
|
||||
}
|
||||
|
||||
int add_typeattribute(const char *type, const char *attr) {
|
||||
type_datum_t *domain = hashtab_search(mpdb->p_types.table, type);
|
||||
int add_typeattribute(policydb_t *db, const char *type, const char *attr) {
|
||||
type_datum_t *domain = hashtab_search(db->p_types.table, type);
|
||||
if (domain == NULL) {
|
||||
LOGW("type %s does not exist\n", type);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int attr_id = set_attr(attr, domain->s.value);
|
||||
int attr_id = set_attr(db, attr, domain->s.value);
|
||||
if (attr_id < 0)
|
||||
return 1;
|
||||
|
||||
hashtab_for_each(mpdb->p_classes.table, {
|
||||
hashtab_for_each(db->p_classes.table, {
|
||||
class_datum_t *cls = node->datum;
|
||||
for (constraint_node_t *n = cls->constraints; n ; n = n->next) {
|
||||
for (constraint_expr_t *e = n->expr; e; e = e->next) {
|
||||
@ -365,13 +363,14 @@ int add_typeattribute(const char *type, const char *attr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int add_rule(const char *s, const char *t, const char *c, const char *p, int effect, int n) {
|
||||
int add_rule(policydb_t *db,
|
||||
const char *s, const char *t, const char *c, const char *p, int effect, int n) {
|
||||
type_datum_t *src = NULL, *tgt = NULL;
|
||||
class_datum_t *cls = NULL;
|
||||
perm_datum_t *perm = NULL;
|
||||
|
||||
if (s) {
|
||||
src = hashtab_search(mpdb->p_types.table, s);
|
||||
src = hashtab_search(db->p_types.table, s);
|
||||
if (src == NULL) {
|
||||
LOGW("source type %s does not exist\n", s);
|
||||
return 1;
|
||||
@ -379,7 +378,7 @@ int add_rule(const char *s, const char *t, const char *c, const char *p, int eff
|
||||
}
|
||||
|
||||
if (t) {
|
||||
tgt = hashtab_search(mpdb->p_types.table, t);
|
||||
tgt = hashtab_search(db->p_types.table, t);
|
||||
if (tgt == NULL) {
|
||||
LOGW("target type %s does not exist\n", t);
|
||||
return 1;
|
||||
@ -387,7 +386,7 @@ int add_rule(const char *s, const char *t, const char *c, const char *p, int eff
|
||||
}
|
||||
|
||||
if (c) {
|
||||
cls = hashtab_search(mpdb->p_classes.table, c);
|
||||
cls = hashtab_search(db->p_classes.table, c);
|
||||
if (cls == NULL) {
|
||||
LOGW("class %s does not exist\n", c);
|
||||
return 1;
|
||||
@ -409,16 +408,16 @@ int add_rule(const char *s, const char *t, const char *c, const char *p, int eff
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return add_rule_auto(src, tgt, cls, perm, effect, n);
|
||||
return add_rule_auto(db, src, tgt, cls, perm, effect, n);
|
||||
}
|
||||
|
||||
int add_xperm_rule(const char *s, const char *t, const char *c, const char *range, int effect,
|
||||
int n) {
|
||||
int add_xperm_rule(policydb_t *db, const char *s, const char *t, const char *c, const char *range,
|
||||
int effect, int n) {
|
||||
type_datum_t *src = NULL, *tgt = NULL;
|
||||
class_datum_t *cls = NULL;
|
||||
|
||||
if (s) {
|
||||
src = hashtab_search(mpdb->p_types.table, s);
|
||||
src = hashtab_search(db->p_types.table, s);
|
||||
if (src == NULL) {
|
||||
LOGW("source type %s does not exist\n", s);
|
||||
return 1;
|
||||
@ -426,7 +425,7 @@ int add_xperm_rule(const char *s, const char *t, const char *c, const char *rang
|
||||
}
|
||||
|
||||
if (t) {
|
||||
tgt = hashtab_search(mpdb->p_types.table, t);
|
||||
tgt = hashtab_search(db->p_types.table, t);
|
||||
if (tgt == NULL) {
|
||||
LOGW("target type %s does not exist\n", t);
|
||||
return 1;
|
||||
@ -434,7 +433,7 @@ int add_xperm_rule(const char *s, const char *t, const char *c, const char *rang
|
||||
}
|
||||
|
||||
if (c) {
|
||||
cls = hashtab_search(mpdb->p_classes.table, c);
|
||||
cls = hashtab_search(db->p_classes.table, c);
|
||||
if (cls == NULL) {
|
||||
LOGW("class %s does not exist\n", c);
|
||||
return 1;
|
||||
@ -455,29 +454,30 @@ int add_xperm_rule(const char *s, const char *t, const char *c, const char *rang
|
||||
high = 0xFFFF;
|
||||
}
|
||||
|
||||
return add_xperm_rule_auto(src, tgt, cls, low, high, effect, n);
|
||||
return add_xperm_rule_auto(db, src, tgt, cls, low, high, effect, n);
|
||||
}
|
||||
|
||||
int add_type_rule(const char *s, const char *t, const char *c, const char *d, int effect) {
|
||||
int add_type_rule(policydb_t *db,
|
||||
const char *s, const char *t, const char *c, const char *d, int effect) {
|
||||
type_datum_t *src, *tgt, *def;
|
||||
class_datum_t *cls;
|
||||
|
||||
src = hashtab_search(mpdb->p_types.table, s);
|
||||
src = hashtab_search(db->p_types.table, s);
|
||||
if (src == NULL) {
|
||||
LOGW("source type %s does not exist\n", s);
|
||||
return 1;
|
||||
}
|
||||
tgt = hashtab_search(mpdb->p_types.table, t);
|
||||
tgt = hashtab_search(db->p_types.table, t);
|
||||
if (tgt == NULL) {
|
||||
LOGW("target type %s does not exist\n", t);
|
||||
return 1;
|
||||
}
|
||||
cls = hashtab_search(mpdb->p_classes.table, c);
|
||||
cls = hashtab_search(db->p_classes.table, c);
|
||||
if (cls == NULL) {
|
||||
LOGW("class %s does not exist\n", c);
|
||||
return 1;
|
||||
}
|
||||
def = hashtab_search(mpdb->p_types.table, d);
|
||||
def = hashtab_search(db->p_types.table, d);
|
||||
if (def == NULL) {
|
||||
LOGW("default type %s does not exist\n", d);
|
||||
return 1;
|
||||
@ -489,16 +489,16 @@ int add_type_rule(const char *s, const char *t, const char *c, const char *d, in
|
||||
key.target_class = cls->s.value;
|
||||
key.specified = effect;
|
||||
|
||||
avtab_ptr_t node = get_avtab_node(&key, NULL);
|
||||
avtab_ptr_t node = get_avtab_node(db, &key, NULL);
|
||||
node->datum.data = def->s.value;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int add_genfscon(const char *name, const char *path, const char *context) {
|
||||
int add_genfscon(policydb_t *db, const char *name, const char *path, const char *context) {
|
||||
// First try to create context
|
||||
context_struct_t *ctx;
|
||||
if (context_from_string(NULL, mpdb, &ctx, context, strlen(context))) {
|
||||
if (context_from_string(NULL, db, &ctx, context, strlen(context))) {
|
||||
LOGW("Failed to create context from string [%s]\n", context);
|
||||
return 1;
|
||||
}
|
||||
@ -512,7 +512,7 @@ int add_genfscon(const char *name, const char *path, const char *context) {
|
||||
// Find or allocate genfs
|
||||
genfs_t *last_gen = NULL;
|
||||
genfs_t *newfs = NULL;
|
||||
for (genfs_t *node = mpdb->genfs; node; node = node->next) {
|
||||
for (genfs_t *node = db->genfs; node; node = node->next) {
|
||||
if (strcmp(node->fstype, name) == 0) {
|
||||
newfs = node;
|
||||
break;
|
||||
@ -526,7 +526,7 @@ int add_genfscon(const char *name, const char *path, const char *context) {
|
||||
if (last_gen)
|
||||
last_gen->next = newfs;
|
||||
else
|
||||
mpdb->genfs = newfs;
|
||||
db->genfs = newfs;
|
||||
}
|
||||
|
||||
// Insert or replace genfs context
|
||||
@ -555,9 +555,9 @@ int add_genfscon(const char *name, const char *path, const char *context) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void strip_dontaudit() {
|
||||
avtab_for_each(&mpdb->te_avtab, {
|
||||
void strip_dontaudit(policydb_t *db) {
|
||||
avtab_for_each(&db->te_avtab, {
|
||||
if (node->key.specified == AVTAB_AUDITDENY || node->key.specified == AVTAB_XPERMS_DONTAUDIT)
|
||||
avtab_remove_node(&magisk_policydb->te_avtab, node);
|
||||
avtab_remove_node(&db->te_avtab, node);
|
||||
})
|
||||
}
|
||||
|
@ -4,17 +4,21 @@
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
// Global policydb
|
||||
extern policydb_t *magisk_policydb;
|
||||
// Internal C APIs, do not use directly
|
||||
int create_domain(policydb_t *db, const char *d);
|
||||
int set_domain_state(policydb_t *db, const char *s, int state);
|
||||
int add_typeattribute(policydb_t *db, const char *type, const char *attr);
|
||||
int add_rule(policydb_t *db, const char *s, const char *t, const char *c, const char *p, int effect,
|
||||
int n);
|
||||
int add_xperm_rule(policydb_t *db, const char *s, const char *t, const char *c, const char *range,
|
||||
int effect, int n);
|
||||
int add_type_rule(policydb_t *db, const char *s, const char *t, const char *c, const char *d,
|
||||
int effect);
|
||||
int add_filename_trans(policydb_t *db, const char *s, const char *t, const char *c, const char *d,
|
||||
const char *o);
|
||||
int add_genfscon(policydb_t *db, const char *name, const char *path, const char *context);
|
||||
void strip_dontaudit(policydb_t *db);
|
||||
|
||||
int create_domain(const char *d);
|
||||
int set_domain_state(const char *s, int state);
|
||||
int add_typeattribute(const char *type, const char *attr);
|
||||
int add_rule(const char *s, const char *t, const char *c, const char *p, int effect, int n);
|
||||
int add_xperm_rule(const char *s, const char *t, const char *c, const char *range, int effect, int n);
|
||||
int add_type_rule(const char *s, const char *t, const char *c, const char *d, int effect);
|
||||
int add_filename_trans(const char *s, const char *t, const char *c, const char *d, const char *o);
|
||||
int add_genfscon(const char *name, const char *path, const char *context);
|
||||
void strip_dontaudit();
|
||||
void statement_help();
|
||||
|
||||
__END_DECLS
|
||||
|
@ -6,42 +6,45 @@
|
||||
#include <logging.hpp>
|
||||
#include <utils.hpp>
|
||||
|
||||
#include "sepolicy.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
static const char *type_msg_1 =
|
||||
R"EOF(Type 1:
|
||||
"<rule_name> source_type target_type class perm_set"
|
||||
"<rule_name> ^source_type ^target_type ^class ^perm_set"
|
||||
Rules: allow, deny, auditallow, dontaudit
|
||||
)EOF";
|
||||
|
||||
static const char *type_msg_2 =
|
||||
R"EOF(Type 2:
|
||||
"<rule_name> source_type target_type class operation xperm_set"
|
||||
"<rule_name> ^source_type ^target_type ^class operation xperm_set"
|
||||
Rules: allowxperm, auditallowxperm, dontauditxperm
|
||||
* The only supported operation is ioctl
|
||||
* The only supported xperm_set format is range ([low-high])
|
||||
- The only supported operation is ioctl
|
||||
- The only supported xperm_set format is range ([low-high])
|
||||
)EOF";
|
||||
|
||||
static const char *type_msg_3 =
|
||||
R"EOF(Type 3:
|
||||
"<rule_name> class"
|
||||
"<rule_name> type"
|
||||
Rules: create, permissive, enforcing
|
||||
)EOF";
|
||||
|
||||
static const char *type_msg_4 =
|
||||
R"EOF(Type 4:
|
||||
"attradd class attribute"
|
||||
"typeattribute type attribute"
|
||||
)EOF";
|
||||
|
||||
static const char *type_msg_5 =
|
||||
R"EOF(Type 5:
|
||||
"<rule_name> source_type target_type class default_type"
|
||||
Rules: type_transition, type_change, type_member
|
||||
Rules: type_change, type_member
|
||||
)EOF";
|
||||
|
||||
static const char *type_msg_6 =
|
||||
R"EOF(Type 6:
|
||||
"name_transition source_type target_type class default_type object_name"
|
||||
"type_transition source_type target_type class default_type (object_name)"
|
||||
- Entry 'object_name' is optional
|
||||
)EOF";
|
||||
|
||||
static const char *type_msg_7 =
|
||||
@ -52,13 +55,22 @@ R"EOF(Type 7:
|
||||
void statement_help() {
|
||||
fprintf(stderr,
|
||||
R"EOF(One policy statement should be treated as one parameter;
|
||||
this means a full policy statement should be enclosed in quotes.
|
||||
this means each policy statement should be enclosed in quotes.
|
||||
Multiple policy statements can be provided in a single command.
|
||||
|
||||
The statements has a format of "<rule_name> [args...]"
|
||||
Multiple types and permissions can be grouped into collections
|
||||
wrapped in curly brackets.
|
||||
'*' represents a collection containing all valid matches.
|
||||
Statements has a format of "<rule_name> [args...]".
|
||||
Arguments labeled with (^) can accept one or more entries. Multiple
|
||||
entries consist of a space separated list enclosed in braces ({}).
|
||||
For args that support multiple entries, (*) can be used to
|
||||
represent all valid matches.
|
||||
|
||||
Example: "allow { s1 s2 } { t1 t2 } class *"
|
||||
Will be expanded to:
|
||||
|
||||
allow s1 t1 class { all-permissions-of-class }
|
||||
allow s1 t2 class { all-permissions-of-class }
|
||||
allow s2 t1 class { all-permissions-of-class }
|
||||
allow s2 t2 class { all-permissions-of-class }
|
||||
|
||||
Supported policy statements:
|
||||
|
||||
@ -69,388 +81,193 @@ Supported policy statements:
|
||||
%s
|
||||
%s
|
||||
%s
|
||||
Notes:
|
||||
* Type 4 - 7 does not support collections
|
||||
* Object classes cannot be collections
|
||||
* source_type and target_type can also be attributes
|
||||
|
||||
Example: allow { s1 s2 } { t1 t2 } class *
|
||||
Will be expanded to:
|
||||
|
||||
allow s1 t1 class { all-permissions }
|
||||
allow s1 t2 class { all-permissions }
|
||||
allow s2 t1 class { all-permissions }
|
||||
allow s2 t2 class { all-permissions }
|
||||
|
||||
)EOF", type_msg_1, type_msg_2, type_msg_3, type_msg_4, type_msg_5, type_msg_6, type_msg_7);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static int parse_bracket(char *tok, char *&stmt, vector<const char *> &vec) {
|
||||
if (tok == nullptr || tok[0] != '{') {
|
||||
// Not in a bracket
|
||||
vec.push_back(tok);
|
||||
} else {
|
||||
if (stmt)
|
||||
stmt[-1] = ' ';
|
||||
tok = strchr(tok, '{') + 1;
|
||||
char *end = strchr(tok, '}');
|
||||
if (end == nullptr) // Bracket not closed
|
||||
return 1;
|
||||
*end = '\0';
|
||||
char *cur;
|
||||
while ((cur = strtok_r(nullptr, " ", &tok)) != nullptr)
|
||||
vec.push_back(cur);
|
||||
stmt = end + 1;
|
||||
static bool tokenize_string(char *stmt, vector<vector<char *>> &arr) {
|
||||
// cur is the pointer to where the top level is parsing
|
||||
char *cur = stmt;
|
||||
for (char *tok; (tok = strtok_r(nullptr, " ", &cur)) != nullptr;) {
|
||||
vector<char *> token;
|
||||
if (tok[0] == '{') {
|
||||
// cur could point to somewhere in the braces, restore the string
|
||||
cur[-1] = ' ';
|
||||
++tok;
|
||||
char *end = strchr(tok, '}');
|
||||
if (end == nullptr) {
|
||||
// Bracket not closed, syntax error
|
||||
LOGE("Unclosed bracket detected\n");
|
||||
return false;
|
||||
}
|
||||
*end = '\0';
|
||||
for (char *sub_tok; (sub_tok = strtok_r(nullptr, " ", &tok)) != nullptr;)
|
||||
token.push_back(sub_tok);
|
||||
cur = end + 1;
|
||||
} else if (tok[0] == '*') {
|
||||
token.push_back(nullptr);
|
||||
} else {
|
||||
token.push_back(tok);
|
||||
}
|
||||
arr.push_back(std::move(token));
|
||||
}
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Pattern 1: action { source } { target } class { permission }
|
||||
static int parse_pattern_1(int action, const char *action_str, char *stmt) {
|
||||
int (*action_func)(const char*, const char*, const char*, const char*);
|
||||
switch (action) {
|
||||
case 0:
|
||||
action_func = sepol_allow;
|
||||
break;
|
||||
case 1:
|
||||
action_func = sepol_deny;
|
||||
break;
|
||||
case 2:
|
||||
action_func = sepol_auditallow;
|
||||
break;
|
||||
case 3:
|
||||
action_func = sepol_dontaudit;
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
|
||||
int state = 0;
|
||||
char *cur, *cls;
|
||||
vector<const char*> source, target, permission;
|
||||
while ((cur = strtok_r(nullptr, " ", &stmt)) != nullptr) {
|
||||
if (cur[0] == '*') cur = ALL;
|
||||
vector<const char *> *vec;
|
||||
switch (state) {
|
||||
case 0:
|
||||
vec = &source;
|
||||
break;
|
||||
case 1:
|
||||
vec = ⌖
|
||||
break;
|
||||
case 2:
|
||||
vec = nullptr;
|
||||
cls = cur;
|
||||
break;
|
||||
case 3:
|
||||
vec = &permission;
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (vec && parse_bracket(cur, stmt, *vec))
|
||||
return 1;
|
||||
++state;
|
||||
}
|
||||
if (state != 4 || source.empty() || target.empty() || permission.empty())
|
||||
return 1;
|
||||
|
||||
for (auto src : source)
|
||||
for (auto tgt : target)
|
||||
for (auto perm : permission)
|
||||
if (action_func(src, tgt, cls, perm))
|
||||
LOGW("Error in: %s %s %s %s %s\n", action_str, src, tgt, cls, perm);
|
||||
|
||||
return 0;
|
||||
// Pattern 1: action { source } { target } { class } { permission }
|
||||
template <typename Func>
|
||||
static bool parse_pattern_1(Func fn, const char *action, char *stmt) {
|
||||
vector<vector<char *>> arr;
|
||||
if (!tokenize_string(stmt, arr))
|
||||
return false;
|
||||
if (arr.size() != 4)
|
||||
return false;
|
||||
for (char *src : arr[0])
|
||||
for (char *tgt : arr[1])
|
||||
for (char *cls : arr[2])
|
||||
for (char *perm : arr[3])
|
||||
if (fn(src, tgt, cls, perm))
|
||||
LOGW("Error in: %s %s %s %s %s\n", action, src, tgt, cls, perm);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Pattern 2: action { source } { target } { class } ioctl range
|
||||
static int parse_pattern_2(int action, const char *action_str, char *stmt) {
|
||||
int (*action_func)(const char*, const char*, const char*, const char*);
|
||||
switch (action) {
|
||||
case 0:
|
||||
action_func = sepol_allowxperm;
|
||||
break;
|
||||
case 1:
|
||||
action_func = sepol_auditallowxperm;
|
||||
break;
|
||||
case 2:
|
||||
action_func = sepol_dontauditxperm;
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
|
||||
int state = 0;
|
||||
char *cur, *range;
|
||||
vector<const char *> source, target, classes;
|
||||
while ((cur = strtok_r(nullptr, " ", &stmt)) != nullptr) {
|
||||
if (cur[0] == '*') cur = ALL;
|
||||
vector<const char *> *vec;
|
||||
switch (state) {
|
||||
case 0:
|
||||
vec = &source;
|
||||
break;
|
||||
case 1:
|
||||
vec = ⌖
|
||||
break;
|
||||
case 2:
|
||||
vec = &classes;
|
||||
break;
|
||||
case 3:
|
||||
// Currently only support ioctl
|
||||
if (strcmp(cur, "ioctl") != 0)
|
||||
return 1;
|
||||
vec = nullptr;
|
||||
break;
|
||||
case 4:
|
||||
vec = nullptr;
|
||||
range = cur;
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (vec && parse_bracket(cur, stmt, *vec))
|
||||
return 1;
|
||||
++state;
|
||||
}
|
||||
if (state != 5 || source.empty() || target.empty() || classes.empty())
|
||||
return 1;
|
||||
|
||||
for (auto src : source)
|
||||
for (auto tgt : target)
|
||||
for (auto cls : classes)
|
||||
if (action_func(src, tgt, cls, range))
|
||||
LOGW("Error in: %s %s %s %s %s\n", action_str, src, tgt, cls, range);
|
||||
|
||||
return 0;
|
||||
template <typename Func>
|
||||
static bool parse_pattern_2(Func fn, const char *action, char *stmt) {
|
||||
vector<vector<char *>> arr;
|
||||
if (!tokenize_string(stmt, arr))
|
||||
return false;
|
||||
if (arr.size() != 5 || arr[3].size() != 1 || arr[3][0] != "ioctl"sv || arr[4].size() != 1)
|
||||
return false;
|
||||
char *range = arr[4][0];
|
||||
for (char *src : arr[0])
|
||||
for (char *tgt : arr[1])
|
||||
for (char *cls : arr[2])
|
||||
if (fn(src, tgt, cls, range))
|
||||
LOGW("Error in: %s %s %s %s ioctl %s\n", action, src, tgt, cls, range);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Pattern 3: action { type }
|
||||
static int parse_pattern_3(int action, const char *action_str, char* stmt) {
|
||||
int (*action_func)(const char*);
|
||||
switch (action) {
|
||||
case 0:
|
||||
action_func = sepol_create;
|
||||
break;
|
||||
case 1:
|
||||
action_func = sepol_permissive;
|
||||
break;
|
||||
case 2:
|
||||
action_func = sepol_enforce;
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *cur;
|
||||
vector<const char *> domains;
|
||||
while ((cur = strtok_r(nullptr, " {}", &stmt)) != nullptr) {
|
||||
if (cur[0] == '*') cur = ALL;
|
||||
domains.push_back(cur);
|
||||
}
|
||||
|
||||
if (domains.empty())
|
||||
return 1;
|
||||
|
||||
for (auto dom : domains)
|
||||
if (action_func(dom))
|
||||
LOGW("Error in: %s %s\n", action_str, dom);
|
||||
|
||||
return 0;
|
||||
template <typename Func>
|
||||
static bool parse_pattern_3(Func fn, const char *action, char *stmt) {
|
||||
vector<vector<char *>> arr;
|
||||
if (!tokenize_string(stmt, arr))
|
||||
return false;
|
||||
if (arr.size() != 1)
|
||||
return false;
|
||||
for (char *type : arr[0])
|
||||
if (fn(type))
|
||||
LOGW("Error in: %s %s\n", action, type);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Pattern 4: action { class } { attribute }
|
||||
static int parse_pattern_4(int action, const char *action_str, char *stmt) {
|
||||
int (*action_func)(const char*, const char*);
|
||||
switch (action) {
|
||||
case 0:
|
||||
action_func = sepol_attradd;
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
|
||||
int state = 0;
|
||||
char *cur;
|
||||
vector<const char *> classes, attribute;
|
||||
while ((cur = strtok_r(nullptr, " ", &stmt)) != nullptr) {
|
||||
if (cur[0] == '*') cur = ALL;
|
||||
vector<const char *> *vec;
|
||||
switch (state) {
|
||||
case 0:
|
||||
vec = &classes;
|
||||
break;
|
||||
case 1:
|
||||
vec = &attribute;
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (parse_bracket(cur, stmt, *vec))
|
||||
return 1;
|
||||
++state;
|
||||
}
|
||||
if (state != 2 || classes.empty() || attribute.empty())
|
||||
return 1;
|
||||
|
||||
for (auto cls : classes)
|
||||
for (auto attr : attribute)
|
||||
if (action_func(cls, attr))
|
||||
LOGW("Error in: %s %s %s\n", action_str, cls, attr);
|
||||
|
||||
return 0;
|
||||
// Pattern 4: action { type } { attribute }
|
||||
template <typename Func>
|
||||
static bool parse_pattern_4(Func fn, const char *action, char *stmt) {
|
||||
vector<vector<char *>> arr;
|
||||
if (!tokenize_string(stmt, arr))
|
||||
return false;
|
||||
if (arr.size() != 2)
|
||||
return false;
|
||||
for (char *type : arr[0])
|
||||
for (char *attr : arr[1])
|
||||
if (fn(type, attr))
|
||||
LOGW("Error in: %s %s %s\n", action, type, attr);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Pattern 5: action source target class default
|
||||
static int parse_pattern_5(int action, const char *action_str, char *stmt) {
|
||||
int (*action_func)(const char*, const char*, const char*, const char*);
|
||||
switch (action) {
|
||||
case 0:
|
||||
action_func = sepol_typetrans;
|
||||
break;
|
||||
case 1:
|
||||
action_func = sepol_typechange;
|
||||
break;
|
||||
case 2:
|
||||
action_func = sepol_typemember;
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
int state = 0;
|
||||
char *cur;
|
||||
char *source, *target, *cls, *def;
|
||||
while ((cur = strtok_r(nullptr, " ", &stmt)) != nullptr) {
|
||||
switch(state) {
|
||||
case 0:
|
||||
source = cur;
|
||||
break;
|
||||
case 1:
|
||||
target = cur;
|
||||
break;
|
||||
case 2:
|
||||
cls = cur;
|
||||
break;
|
||||
case 3:
|
||||
def = cur;
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
++state;
|
||||
}
|
||||
if (state < 4) return 1;
|
||||
if (action_func(source, target, cls, def))
|
||||
LOGW("Error in: %s %s %s %s %s\n", action_str, source, target, cls, def);
|
||||
return 0;
|
||||
template <typename Func>
|
||||
static bool parse_pattern_5(Func fn, const char *action, char *stmt) {
|
||||
vector<vector<char *>> arr;
|
||||
if (!tokenize_string(stmt, arr))
|
||||
return false;
|
||||
if (arr.size() != 4 ||
|
||||
arr[0].size() != 1 || arr[1].size() != 1 || arr[2].size() != 1 || arr[3].size() != 1)
|
||||
return false;
|
||||
if (fn(arr[0][0], arr[1][0], arr[2][0], arr[3][0]))
|
||||
LOGW("Error in: %s %s %s %s %s\n", action, arr[0][0], arr[1][0], arr[2][0], arr[3][0]);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Pattern 6: action source target class default filename
|
||||
static int parse_pattern_6(int action, const char *action_str, char *stmt) {
|
||||
int state = 0;
|
||||
char *cur;
|
||||
char *source, *target, *cls, *def, *filename;
|
||||
while ((cur = strtok_r(nullptr, " ", &stmt)) != nullptr) {
|
||||
switch(state) {
|
||||
case 0:
|
||||
source = cur;
|
||||
break;
|
||||
case 1:
|
||||
target = cur;
|
||||
break;
|
||||
case 2:
|
||||
cls = cur;
|
||||
break;
|
||||
case 3:
|
||||
def = cur;
|
||||
break;
|
||||
case 4:
|
||||
filename = cur;
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
++state;
|
||||
}
|
||||
if (state < 5) return 1;
|
||||
if (sepol_nametrans(source, target, cls, def, filename))
|
||||
LOGW("Error in: %s %s %s %s %s %s\n", action_str, source, target, cls, def, filename);
|
||||
return 0;
|
||||
// Pattern 6: action source target class default (filename)
|
||||
template <typename Func>
|
||||
static bool parse_pattern_6(Func fn, const char *action, char *stmt) {
|
||||
vector<vector<char *>> arr;
|
||||
if (!tokenize_string(stmt, arr))
|
||||
return false;
|
||||
if (arr.size() == 4)
|
||||
arr.emplace_back(initializer_list<char*>{nullptr});
|
||||
if (arr.size() != 5 ||
|
||||
arr[0].size() != 1 || arr[1].size() != 1 || arr[2].size() != 1 ||
|
||||
arr[3].size() != 1 || arr[4].size() != 1)
|
||||
return false;
|
||||
if (fn(arr[0][0], arr[1][0], arr[2][0], arr[3][0], arr[4][0]))
|
||||
LOGW("Error in: %s %s %s %s %s %s\n", action,
|
||||
arr[0][0], arr[1][0], arr[2][0], arr[3][0], arr[4][0] ? arr[4][0] : "");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Pattern 7: action name path context
|
||||
static int parse_pattern_7(int action, const char *action_str, char *stmt) {
|
||||
int state = 0;
|
||||
char *cur;
|
||||
char *name, *path, *context;
|
||||
while ((cur = strtok_r(nullptr, " ", &stmt)) != nullptr) {
|
||||
switch(state) {
|
||||
case 0:
|
||||
name = cur;
|
||||
break;
|
||||
case 1:
|
||||
path = cur;
|
||||
break;
|
||||
case 2:
|
||||
context = cur;
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
++state;
|
||||
}
|
||||
if (state < 3) return 1;
|
||||
if (sepol_genfscon(name, path, context))
|
||||
LOGW("Error in: %s %s %s %s\n", action_str, name, path, context);
|
||||
return 0;
|
||||
template <typename Func>
|
||||
static bool parse_pattern_7(Func fn, const char *action, char *stmt) {
|
||||
vector<vector<char *>> arr;
|
||||
if (!tokenize_string(stmt, arr))
|
||||
return false;
|
||||
if (arr.size() != 3 || arr[0].size() != 1 || arr[1].size() != 1 || arr[2].size() != 1)
|
||||
return false;
|
||||
if (fn(arr[0][0], arr[1][0], arr[2][0]))
|
||||
LOGW("Error in: %s %s %s %s\n", action, arr[0][0], arr[1][0], arr[2][0]);
|
||||
return true;
|
||||
}
|
||||
|
||||
#define add_action(name, type, num) \
|
||||
#define add_action_func(name, type, fn) \
|
||||
else if (strcmp(name, action) == 0) { \
|
||||
if (parse_pattern_##type(num, name, remain)) \
|
||||
LOGW("Syntax error in '%s'\n\n%s\n", statement, type_msg_##type); \
|
||||
auto __fn = [=](auto && ...args){ return (fn)(args...); };\
|
||||
if (!parse_pattern_##type(__fn, name, remain)) \
|
||||
LOGW("Syntax error in '%s'\n\n%s\n", stmt, type_msg_##type); \
|
||||
}
|
||||
|
||||
void parse_statement(const char *statement) {
|
||||
char *action, *remain;
|
||||
#define add_action(act, type) add_action_func(#act, type, act)
|
||||
|
||||
// strtok will modify strings, duplicate the statement
|
||||
string stmt(statement);
|
||||
|
||||
action = strtok_r(stmt.data(), " ", &remain);
|
||||
void sepolicy::parse_statement(const char *stmt) {
|
||||
// strtok modify strings, create a copy
|
||||
string cpy(stmt);
|
||||
|
||||
char *remain;
|
||||
char *action = strtok_r(cpy.data(), " ", &remain);
|
||||
if (remain == nullptr) {
|
||||
LOGE("Syntax error in '%s'\n\n", statement);
|
||||
LOGW("Syntax error in '%s'\n\n", stmt);
|
||||
return;
|
||||
}
|
||||
|
||||
if (0) {}
|
||||
add_action("allow", 1, 0)
|
||||
add_action("deny", 1, 1)
|
||||
add_action("auditallow", 1, 2)
|
||||
add_action("dontaudit", 1, 3)
|
||||
add_action("allowxperm", 2, 0)
|
||||
add_action("auditallowxperm", 2, 1)
|
||||
add_action("dontauditxperm", 2, 2)
|
||||
add_action("create", 3, 0)
|
||||
add_action("permissive", 3, 1)
|
||||
add_action("enforce", 3, 2)
|
||||
add_action("attradd", 4, 0)
|
||||
add_action("type_transition", 5, 0)
|
||||
add_action("type_change", 5, 1)
|
||||
add_action("type_member", 5, 2)
|
||||
add_action("name_transition", 6, 0)
|
||||
add_action("genfscon", 7, 0)
|
||||
else { LOGW("Unknown statement: '%s'\n\n", statement); }
|
||||
add_action(allow, 1)
|
||||
add_action(deny, 1)
|
||||
add_action(auditallow, 1)
|
||||
add_action(dontaudit, 1)
|
||||
add_action(allowxperm, 2)
|
||||
add_action(auditallowxperm, 2)
|
||||
add_action(dontauditxperm, 2)
|
||||
add_action(create, 3)
|
||||
add_action(permissive, 3)
|
||||
add_action(enforce, 3)
|
||||
add_action(typeattribute, 4)
|
||||
add_action(type_change, 5)
|
||||
add_action(type_member, 5)
|
||||
add_action(type_transition, 6)
|
||||
add_action(genfscon, 7)
|
||||
|
||||
// Backwards compatible syntax
|
||||
add_action_func("attradd", 4, typeattribute)
|
||||
add_action_func("name_transition", 6, type_transition)
|
||||
|
||||
else { LOGW("Syntax error in '%s'\n\n", stmt); }
|
||||
}
|
||||
|
||||
void load_rule_file(const char *file) {
|
||||
file_readline(true, file, [](string_view line) -> bool {
|
||||
void sepolicy::load_rule_file(const char *file) {
|
||||
file_readline(true, file, [=](string_view line) -> bool {
|
||||
if (line.empty() || line[0] == '#')
|
||||
return true;
|
||||
parse_statement(line.data());
|
||||
|
Loading…
Reference in New Issue
Block a user