From f392ade78dd7163d8279bb2a9aff2f1e1b53854c Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Sat, 23 May 2020 00:18:25 -0700 Subject: [PATCH] Rewrite sepolicy.c in C++ --- native/jni/Android.mk | 8 +- native/jni/include/magiskpolicy.hpp | 5 +- native/jni/magiskpolicy/api.cpp | 90 --- native/jni/magiskpolicy/magiskpolicy.cpp | 2 +- native/jni/magiskpolicy/policydb.cpp | 2 +- native/jni/magiskpolicy/rules.cpp | 23 +- native/jni/magiskpolicy/sepolicy.c | 563 ------------------- native/jni/magiskpolicy/sepolicy.cpp | 666 +++++++++++++++++++++++ native/jni/magiskpolicy/sepolicy.h | 24 - native/jni/magiskpolicy/sepolicy.hpp | 30 + native/jni/magiskpolicy/statement.cpp | 2 +- 11 files changed, 714 insertions(+), 701 deletions(-) delete mode 100644 native/jni/magiskpolicy/api.cpp delete mode 100644 native/jni/magiskpolicy/sepolicy.c create mode 100644 native/jni/magiskpolicy/sepolicy.cpp delete mode 100644 native/jni/magiskpolicy/sepolicy.h create mode 100644 native/jni/magiskpolicy/sepolicy.hpp diff --git a/native/jni/Android.mk b/native/jni/Android.mk index 95ab27058..3e0fbed41 100644 --- a/native/jni/Android.mk +++ b/native/jni/Android.mk @@ -63,12 +63,11 @@ LOCAL_SRC_FILES := \ init/getinfo.cpp \ init/twostage.cpp \ core/socket.cpp \ - magiskpolicy/api.cpp \ + magiskpolicy/sepolicy.cpp \ magiskpolicy/magiskpolicy.cpp \ magiskpolicy/rules.cpp \ magiskpolicy/policydb.cpp \ magiskpolicy/statement.cpp \ - magiskpolicy/sepolicy.c \ magiskboot/pattern.cpp LOCAL_LDFLAGS := -static @@ -108,12 +107,11 @@ LOCAL_C_INCLUDES := jni/include LOCAL_SRC_FILES := \ core/applet_stub.cpp \ - magiskpolicy/api.cpp \ + magiskpolicy/sepolicy.cpp \ magiskpolicy/magiskpolicy.cpp \ magiskpolicy/rules.cpp \ magiskpolicy/policydb.cpp \ - magiskpolicy/statement.cpp \ - magiskpolicy/sepolicy.c + magiskpolicy/statement.cpp LOCAL_CFLAGS := -DAPPLET_STUB_MAIN=magiskpolicy_main LOCAL_LDFLAGS := -static diff --git a/native/jni/include/magiskpolicy.hpp b/native/jni/include/magiskpolicy.hpp index 2fa341a5a..14d6c818e 100644 --- a/native/jni/include/magiskpolicy.hpp +++ b/native/jni/include/magiskpolicy.hpp @@ -41,7 +41,7 @@ public: 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_transition(c_str s, c_str t, c_str c, c_str d, c_str o = 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); @@ -50,8 +50,7 @@ public: // Magisk void magisk_rules(); - void allow_su_client(c_str type); -private: +protected: policydb *db; }; diff --git a/native/jni/magiskpolicy/api.cpp b/native/jni/magiskpolicy/api.cpp deleted file mode 100644 index 7e2240dc0..000000000 --- a/native/jni/magiskpolicy/api.cpp +++ /dev/null @@ -1,90 +0,0 @@ -#include - -#include "sepolicy.h" - -//#define vprint(fmt, ...) printf(fmt, __VA_ARGS__) -#define vprint(...) - -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(db, s, t, c, p, AVTAB_ALLOWED, 0); -} - -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(db, s, t, c, p, AVTAB_ALLOWED, 1); -} - -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(db, s, t, c, p, AVTAB_AUDITALLOW, 0); -} - -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(db, s, t, c, p, AVTAB_AUDITDENY, 1); -} - -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(db, s, t, c, range, AVTAB_XPERMS_ALLOWED, 0); -} - -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(db, s, t, c, range, AVTAB_XPERMS_AUDITALLOW, 0); -} - -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(db, s, t, c, range, AVTAB_XPERMS_DONTAUDIT, 0); -} - -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(db, s, t, c, d, AVTAB_CHANGE); -} - -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(db, s, t, c, d, AVTAB_MEMBER); -} - -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 sepolicy::permissive(const char *s) { - vprint("permissive %s\n", s); - return set_domain_state(db, s, 1); -} - -int sepolicy::enforce(const char *s) { - vprint("enforce %s\n", s); - return set_domain_state(db, s, 0); -} - -int sepolicy::create(const char *s) { - vprint("create %s\n", s); - return create_domain(db, s); -} - -int sepolicy::typeattribute(const char *type, const char *attr) { - vprint("typeattribute %s %s\n", type, attr); - return add_typeattribute(db, type, attr); -} - -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 sepolicy::exists(const char *source) { - return hashtab_search(db->p_types.table, source) != nullptr; -} diff --git a/native/jni/magiskpolicy/magiskpolicy.cpp b/native/jni/magiskpolicy/magiskpolicy.cpp index baa59e32f..ed25b15a4 100644 --- a/native/jni/magiskpolicy/magiskpolicy.cpp +++ b/native/jni/magiskpolicy/magiskpolicy.cpp @@ -6,7 +6,7 @@ #include #include -#include "sepolicy.h" +#include "sepolicy.hpp" using namespace std::literals; diff --git a/native/jni/magiskpolicy/policydb.cpp b/native/jni/magiskpolicy/policydb.cpp index e6652cd82..efa0d4cc5 100644 --- a/native/jni/magiskpolicy/policydb.cpp +++ b/native/jni/magiskpolicy/policydb.cpp @@ -10,7 +10,7 @@ #include #include -#include "sepolicy.h" +#include "sepolicy.hpp" #define SHALEN 64 static bool cmp_sha256(const char *a, const char *b) { diff --git a/native/jni/magiskpolicy/rules.cpp b/native/jni/magiskpolicy/rules.cpp index f9196b51a..348db83b3 100644 --- a/native/jni/magiskpolicy/rules.cpp +++ b/native/jni/magiskpolicy/rules.cpp @@ -1,10 +1,12 @@ +#include + #include #include #include -#include "sepolicy.h" +#include "sepolicy.hpp" -void sepolicy::allow_su_client(const char *type) { +void sepol_impl::allow_su_client(const char *type) { if (!exists(type)) return; allow(type, SEPOL_PROC_DOMAIN, "unix_stream_socket", "connectto"); @@ -78,16 +80,11 @@ void sepolicy::magisk_rules() { allow(SEPOL_PROC_DOMAIN, "kernel", "security", "load_policy"); // Allow these processes to access MagiskSU - 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"); + std::initializer_list clients { + "init", "shell", "system_app", "priv_app", "platform_app", "untrusted_app", + "untrusted_app_25", "untrusted_app_27", "untrusted_app_29", "update_engine" }; + for (auto type : clients) + impl->allow_su_client(type); // suRights allow("servicemanager", SEPOL_PROC_DOMAIN, "dir", "search"); @@ -199,7 +196,7 @@ void sepolicy::magisk_rules() { #if 0 // Remove all dontaudit in debug mode - strip_dontaudit(db); + impl->strip_dontaudit(); #endif log_cb.w = bak; diff --git a/native/jni/magiskpolicy/sepolicy.c b/native/jni/magiskpolicy/sepolicy.c deleted file mode 100644 index f0c44d9b9..000000000 --- a/native/jni/magiskpolicy/sepolicy.c +++ /dev/null @@ -1,563 +0,0 @@ -#include -#include - -#include - -#include "sepolicy.h" - -extern void *xmalloc(size_t size); -extern void *xcalloc(size_t nmemb, size_t size); -extern void *xrealloc(void *ptr, size_t size); - -// Internal libsepol APIs -extern int policydb_index_decls(sepol_handle_t * handle, policydb_t * p); -extern int context_from_string( - sepol_handle_t * handle, - const policydb_t * policydb, - context_struct_t ** cptr, - const char *con_str, size_t con_str_len); - -// Generic hash table traversal -#define hash_for_each(node_ptr, n_slots, table, block) \ -for (int __i = 0; __i < (table)->n_slots; ++__i) { \ - __typeof__(*(table)->node_ptr) node; \ - __typeof__(node) __next; \ - for (node = (table)->node_ptr[__i]; node; node = __next) { \ - __next = node->next; \ - block \ - } \ -} - -// hashtab traversal -#define hashtab_for_each(hashtab, block) \ -hash_for_each(htable, size, hashtab, block) - -// avtab traversal -#define avtab_for_each(avtab, block) \ -hash_for_each(htable, nslot, avtab, block) - -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(&db->type_attr_map[value - 1], attr->s.value - 1, 1)) - return -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(policydb_t *db, avtab_ptr_t node) { - int redundant = 0; - if (node->key.specified == AVTAB_AUDITDENY) - redundant = node->datum.data == ~0U; - else if (node->key.specified & AVTAB_XPERMS) - redundant = node->datum.xperms == NULL; - else - redundant = node->datum.data == 0U; - if (redundant) - avtab_remove_node(&db->te_avtab, node); -} - -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(&db->te_avtab, key); - while (node) { - if ((node->datum.xperms->specified == xperms->specified) && - (node->datum.xperms->driver == xperms->driver)) { - match = 1; - break; - } - node = avtab_search_node_next(node, key->specified); - } - if (!match) - node = NULL; - } else { - node = avtab_search_node(&db->te_avtab, key); - } - - if (!node) { - memset(&avdatum, 0, sizeof avdatum); - /* - * AUDITDENY, aka DONTAUDIT, are &= assigned, versus |= for - * others. Initialize the data accordingly. - */ - avdatum.data = key->specified == AVTAB_AUDITDENY ? ~0U : 0U; - /* this is used to get the node - insertion is actually unique */ - node = avtab_insert_nonunique(&db->te_avtab, key, &avdatum); - } - - return node; -} - -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) - node->datum.data = 0U; - else - node->datum.data &= ~(1U << (val - 1)); - } else { - if (val < 0) - node->datum.data = ~0U; - else - node->datum.data |= 1U << (val - 1); - } - - check_avtab_node(db, node); - return 0; -} - -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(db->p_types.table, { - src = node->datum; - ret |= add_rule_auto(db, src, tgt, cls, perm, effect, not); - }) - } else if (tgt == NULL) { - hashtab_for_each(db->p_types.table, { - tgt = node->datum; - ret |= add_rule_auto(db, src, tgt, cls, perm, effect, not); - }) - } else if (cls == NULL) { - hashtab_for_each(db->p_classes.table, { - cls = node->datum; - 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(db, &key, perm ? perm->s.value : -1, not); - } - return ret; -} - -#define ioctl_driver(x) (x>>8 & 0xFF) -#define ioctl_func(x) (x & 0xFF) - -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; - - memset(&xperms, 0, sizeof(xperms)); - if (ioctl_driver(low) != ioctl_driver(high)) { - xperms.specified = AVTAB_XPERMS_IOCTLDRIVER; - xperms.driver = 0; - } else { - xperms.specified = AVTAB_XPERMS_IOCTLFUNCTION; - xperms.driver = ioctl_driver(low); - } - - if (xperms.specified == AVTAB_XPERMS_IOCTLDRIVER) { - for (int i = ioctl_driver(low); i <= ioctl_driver(high); ++i) { - if (not) - xperm_clear(i, xperms.perms); - else - xperm_set(i, xperms.perms); - } - } else { - for (int i = ioctl_func(low); i <= ioctl_func(high); ++i) { - if (not) - xperm_clear(i, xperms.perms); - else - xperm_set(i, xperms.perms); - } - } - - datum = &get_avtab_node(db, key, &xperms)->datum; - - if (datum->xperms == NULL) - datum->xperms = xmalloc(sizeof(xperms)); - - memcpy(datum->xperms, &xperms, sizeof(xperms)); - return 0; -} - -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(db->p_types.table, { - src = node->datum; - ret |= add_xperm_rule_auto(db, src, tgt, cls, low, high, effect, not); - }) - } else if (tgt == NULL) { - hashtab_for_each(db->p_types.table, { - tgt = node->datum; - ret |= add_xperm_rule_auto(db, src, tgt, cls, low, high, effect, not); - }) - } else if (cls == NULL) { - hashtab_for_each(db->p_classes.table, { - cls = node->datum; - 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(db, &key, low, high, not); - } - return ret; -} - -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; - } - - type_datum_t *typedatum = xmalloc(sizeof(type_datum_t)); - type_datum_init(typedatum); - typedatum->primary = 1; - typedatum->flavor = TYPE_TYPE; - - uint32_t value = 0; - symtab_insert(db, SYM_TYPES, strdup(d), typedatum, SCOPE_DECL, 1, &value); - typedatum->s.value = value; - - if (ebitmap_set_bit(&db->global->branch_list->declared.scope[SYM_TYPES], value - 1, 1)) { - return 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(db->p_types.table, d); - if (!src) - return 1; - - if (policydb_index_decls(NULL, db)) - return 1; - - if (policydb_index_classes(db)) - return 1; - - if (policydb_index_others(NULL, db, 0)) - return 1; - - // 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(db, "domain", value); -} - -int set_domain_state(policydb_t *db, const char *s, int state) { - type_datum_t *type; - if (s == NULL) { - hashtab_for_each(db->p_types.table, { - type = node->datum; - 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(db->p_types.table, s); - if (type == NULL) { - LOGW("type %s does not exist\n", s); - return 1; - } - if (ebitmap_set_bit(&db->permissive_map, type->s.value, state)) { - LOGW("Could not set bit in permissive map\n"); - return 1; - } - } - - return 0; -} - -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(db->p_types.table, s); - if (src == NULL) { - LOGW("source type %s does not exist\n", s); - return 1; - } - 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(db->p_classes.table, c); - if (cls == NULL) { - LOGW("class %s does not exist\n", c); - return 1; - } - def = hashtab_search(db->p_types.table, d); - if (def == NULL) { - LOGW("default type %s does not exist\n", d); - return 1; - } - - filename_trans_t trans_key; - trans_key.stype = src->s.value; - trans_key.ttype = tgt->s.value; - trans_key.tclass = cls->s.value; - trans_key.name = (char *) o; - - filename_trans_datum_t *trans_datum; - 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(db->filename_trans, (hashtab_key_t) &trans_key, trans_datum); - } - - // Overwrite existing - trans_datum->otype = def->s.value; - return 0; -} - -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(db, attr, domain->s.value); - if (attr_id < 0) - return 1; - - 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) { - if (e->expr_type == CEXPR_NAMES && - ebitmap_get_bit(&e->type_names->types, attr_id - 1)) { - ebitmap_set_bit(&e->names, domain->s.value - 1, 1); - } - } - } - }) - - return 0; -} - -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(db->p_types.table, s); - if (src == NULL) { - LOGW("source type %s does not exist\n", s); - return 1; - } - } - - if (t) { - tgt = hashtab_search(db->p_types.table, t); - if (tgt == NULL) { - LOGW("target type %s does not exist\n", t); - return 1; - } - } - - if (c) { - cls = hashtab_search(db->p_classes.table, c); - if (cls == NULL) { - LOGW("class %s does not exist\n", c); - return 1; - } - } - - if (p) { - if (c == NULL) { - LOGW("No class is specified, cannot add perm [%s] \n", p); - return 1; - } - - perm = hashtab_search(cls->permissions.table, p); - if (perm == NULL && cls->comdatum != NULL) { - perm = hashtab_search(cls->comdatum->permissions.table, p); - } - if (perm == NULL) { - LOGW("perm %s does not exist in class %s\n", p, c); - return 1; - } - } - return add_rule_auto(db, src, tgt, cls, perm, effect, 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(db->p_types.table, s); - if (src == NULL) { - LOGW("source type %s does not exist\n", s); - return 1; - } - } - - if (t) { - tgt = hashtab_search(db->p_types.table, t); - if (tgt == NULL) { - LOGW("target type %s does not exist\n", t); - return 1; - } - } - - if (c) { - cls = hashtab_search(db->p_classes.table, c); - if (cls == NULL) { - LOGW("class %s does not exist\n", c); - return 1; - } - } - - uint16_t low, high; - - if (range) { - if (strchr(range, '-')){ - sscanf(range, "%hx-%hx", &low, &high); - } else { - sscanf(range, "%hx", &low); - high = low; - } - } else { - low = 0; - high = 0xFFFF; - } - - return add_xperm_rule_auto(db, src, tgt, cls, low, high, effect, n); -} - -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(db->p_types.table, s); - if (src == NULL) { - LOGW("source type %s does not exist\n", s); - return 1; - } - 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(db->p_classes.table, c); - if (cls == NULL) { - LOGW("class %s does not exist\n", c); - return 1; - } - def = hashtab_search(db->p_types.table, d); - if (def == NULL) { - LOGW("default type %s does not exist\n", d); - return 1; - } - - avtab_key_t key; - key.source_type = src->s.value; - key.target_type = tgt->s.value; - key.target_class = cls->s.value; - key.specified = effect; - - avtab_ptr_t node = get_avtab_node(db, &key, NULL); - node->datum.data = def->s.value; - - return 0; -} - -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, db, &ctx, context, strlen(context))) { - LOGW("Failed to create context from string [%s]\n", context); - return 1; - } - - // Allocate genfs context - ocontext_t *newc = xcalloc(sizeof(*newc), 1); - newc->u.name = strdup(path); - memcpy(&newc->context[0], ctx, sizeof(*ctx)); - free(ctx); - - // Find or allocate genfs - genfs_t *last_gen = NULL; - genfs_t *newfs = NULL; - for (genfs_t *node = db->genfs; node; node = node->next) { - if (strcmp(node->fstype, name) == 0) { - newfs = node; - break; - } - last_gen = node; - } - if (newfs == NULL) { - newfs = xcalloc(sizeof(*newfs), 1); - newfs->fstype = strdup(name); - // Insert - if (last_gen) - last_gen->next = newfs; - else - db->genfs = newfs; - } - - // Insert or replace genfs context - ocontext_t *last_ctx = NULL; - for (ocontext_t *node = newfs->head; node; node = node->next) { - if (strcmp(node->u.name, path) == 0) { - // Unlink - if (last_ctx) - last_ctx->next = node->next; - else - newfs->head = NULL; - // Destroy old node - free(node->u.name); - context_destroy(&node->context[0]); - free(node); - break; - } - last_ctx = node; - } - // Insert - if (last_ctx) - last_ctx->next = newc; - else - newfs->head = newc; - - return 0; -} - -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(&db->te_avtab, node); - }) -} diff --git a/native/jni/magiskpolicy/sepolicy.cpp b/native/jni/magiskpolicy/sepolicy.cpp new file mode 100644 index 000000000..879e65a5c --- /dev/null +++ b/native/jni/magiskpolicy/sepolicy.cpp @@ -0,0 +1,666 @@ +#include + +#include +#include +#include + +#include "sepolicy.hpp" + +#if 0 +// Print out all rules going through public API for debugging +template +static void dprint(const char *action, Args ...args) { + std::string s(action); + for (int i = 0; i < sizeof...(args); ++i) s += " %s"; + s += "\n"; + LOGD(s.data(), (args ? args : "*")...); +} +#else +#define dprint(...) +#endif + +template +struct auto_cast_wrapper +{ + auto_cast_wrapper(T *ptr) : ptr(ptr) {} + template + operator U*() const { return static_cast(ptr); } + +private: + T *ptr; +}; + +template +static auto_cast_wrapper auto_cast(T *p) { + return auto_cast_wrapper(p); +} + +static auto hashtab_find(hashtab_t h, const_hashtab_key_t key) { + return auto_cast(hashtab_search(h, key)); +} + +template +static void hash_for_each(Node **node_ptr, int n_slot, const Func &fn) { + for (int i = 0; i < n_slot; ++i) { + for (Node *cur = node_ptr[i]; cur; cur = cur->next) { + fn(cur); + } + } +} + +#define hashtab_for_each(hashtab, fn) \ +hash_for_each((hashtab)->htable, (hashtab)->size, fn) + +#define avtab_for_each(avtab, fn) \ +hash_for_each((avtab)->htable, (avtab)->nslot, fn) + +// libsepol internal APIs +extern "C" int policydb_index_decls(sepol_handle_t * handle, policydb_t * p); +extern "C" int context_from_string( + sepol_handle_t * handle, + const policydb_t * policydb, + context_struct_t ** cptr, + const char *con_str, size_t con_str_len); +extern "C" int type_set_expand( + type_set_t * set, ebitmap_t * t, policydb_t * p, + unsigned char alwaysexpand); + +int sepol_impl::set_attr(const char *attr_name, int type_val) { + type_datum_t *attr = hashtab_find(db->p_types.table, attr_name); + if (!attr || attr->flavor != TYPE_ATTRIB) + return -1; + + if (ebitmap_set_bit(&db->type_attr_map[type_val - 1], attr->s.value - 1, 1)) + return -1; + if (ebitmap_set_bit(&db->attr_type_map[attr->s.value - 1], type_val - 1, 1)) + return -1; + + return attr->s.value; +} + +void sepol_impl::check_avtab_node(avtab_ptr_t node) { + bool redundant; + if (node->key.specified == AVTAB_AUDITDENY) + redundant = node->datum.data == ~0U; + else if (node->key.specified & AVTAB_XPERMS) + redundant = node->datum.xperms == nullptr; + else + redundant = node->datum.data == 0U; + if (redundant) + avtab_remove_node(&db->te_avtab, node); +} + +avtab_ptr_t sepol_impl::get_avtab_node(avtab_key_t *key, avtab_extended_perms_t *xperms) { + avtab_ptr_t node; + + /* AVTAB_XPERMS entries are not necessarily unique */ + if (key->specified & AVTAB_XPERMS) { + bool match = false; + node = avtab_search_node(&db->te_avtab, key); + while (node) { + if ((node->datum.xperms->specified == xperms->specified) && + (node->datum.xperms->driver == xperms->driver)) { + match = true; + break; + } + node = avtab_search_node_next(node, key->specified); + } + if (!match) + node = nullptr; + } else { + node = avtab_search_node(&db->te_avtab, key); + } + + if (!node) { + avtab_datum_t avdatum{}; + /* + * AUDITDENY, aka DONTAUDIT, are &= assigned, versus |= for + * others. Initialize the data accordingly. + */ + avdatum.data = key->specified == AVTAB_AUDITDENY ? ~0U : 0U; + /* this is used to get the node - insertion is actually unique */ + node = avtab_insert_nonunique(&db->te_avtab, key, &avdatum); + } + + return node; +} + +int sepol_impl::add_avrule(avtab_key_t *key, int val, bool n) { + avtab_ptr_t node = get_avtab_node(key, nullptr); + + if (n) { + if (val < 0) + node->datum.data = 0U; + else + node->datum.data &= ~(1U << (val - 1)); + } else { + if (val < 0) + node->datum.data = ~0U; + else + node->datum.data |= 1U << (val - 1); + } + + check_avtab_node(node); + return 0; +} + +int sepol_impl::add_rule(type_datum_t *src, type_datum_t *tgt, class_datum_t *cls, perm_datum_t *perm, int effect, bool n) { + int ret = 0; + + if (src == nullptr) { + hashtab_for_each(db->p_types.table, [&](hashtab_ptr_t node) { + src = auto_cast(node->datum); + ret |= add_rule(src, tgt, cls, perm, effect, n); + }); + } else if (tgt == nullptr) { + hashtab_for_each(db->p_types.table, [&](hashtab_ptr_t node) { + tgt = auto_cast(node->datum); + ret |= add_rule(src, tgt, cls, perm, effect, n); + }); + } else if (cls == nullptr) { + hashtab_for_each(db->p_classes.table, [&](hashtab_ptr_t node) { + cls = auto_cast(node->datum); + ret |= add_rule(src, tgt, cls, perm, effect, n); + }); + } else { + avtab_key_t key; + 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, n); + } + + return ret; +} + +int sepol_impl::add_rule(const char *s, const char *t, const char *c, const char *p, int effect, bool n) { + type_datum_t *src = nullptr, *tgt = nullptr; + class_datum_t *cls = nullptr; + perm_datum_t *perm = nullptr; + + if (s) { + src = hashtab_find(db->p_types.table, s); + if (src == nullptr) { + LOGW("source type %s does not exist\n", s); + return 1; + } + } + + if (t) { + tgt = hashtab_find(db->p_types.table, t); + if (tgt == nullptr) { + LOGW("target type %s does not exist\n", t); + return 1; + } + } + + if (c) { + cls = hashtab_find(db->p_classes.table, c); + if (cls == nullptr) { + LOGW("class %s does not exist\n", c); + return 1; + } + } + + if (p) { + if (c == nullptr) { + LOGW("No class is specified, cannot add perm [%s] \n", p); + return 1; + } + + perm = hashtab_find(cls->permissions.table, p); + if (perm == nullptr && cls->comdatum != nullptr) { + perm = hashtab_find(cls->comdatum->permissions.table, p); + } + if (perm == nullptr) { + LOGW("perm %s does not exist in class %s\n", p, c); + return 1; + } + } + return add_rule(src, tgt, cls, perm, effect, n); +} + +#define ioctl_driver(x) (x>>8 & 0xFF) +#define ioctl_func(x) (x & 0xFF) + +int sepol_impl::add_avxrule(avtab_key_t *key, uint16_t low, uint16_t high, bool n) { + avtab_datum_t *datum; + avtab_extended_perms_t xperms; + + memset(&xperms, 0, sizeof(xperms)); + if (ioctl_driver(low) != ioctl_driver(high)) { + xperms.specified = AVTAB_XPERMS_IOCTLDRIVER; + xperms.driver = 0; + } else { + xperms.specified = AVTAB_XPERMS_IOCTLFUNCTION; + xperms.driver = ioctl_driver(low); + } + + if (xperms.specified == AVTAB_XPERMS_IOCTLDRIVER) { + for (int i = ioctl_driver(low); i <= ioctl_driver(high); ++i) { + if (n) + xperm_clear(i, xperms.perms); + else + xperm_set(i, xperms.perms); + } + } else { + for (int i = ioctl_func(low); i <= ioctl_func(high); ++i) { + if (n) + xperm_clear(i, xperms.perms); + else + xperm_set(i, xperms.perms); + } + } + + datum = &get_avtab_node(key, &xperms)->datum; + + if (datum->xperms == nullptr) + datum->xperms = auto_cast(xmalloc(sizeof(xperms))); + + memcpy(datum->xperms, &xperms, sizeof(xperms)); + return 0; +} + +int sepol_impl::add_xperm_rule(type_datum_t *src, type_datum_t *tgt, + class_datum_t *cls, uint16_t low, uint16_t high, int effect, bool n) { + int ret = 0; + if (src == nullptr) { + hashtab_for_each(db->p_types.table, [&](hashtab_ptr_t node) { + src = auto_cast(node->datum); + ret |= add_xperm_rule(src, tgt, cls, low, high, effect, n); + }); + } else if (tgt == nullptr) { + hashtab_for_each(db->p_types.table, [&](hashtab_ptr_t node) { + tgt = auto_cast(node->datum); + ret |= add_xperm_rule(src, tgt, cls, low, high, effect, n); + }); + } else if (cls == nullptr) { + hashtab_for_each(db->p_classes.table, [&](hashtab_ptr_t node) { + tgt = auto_cast(node->datum); + ret |= add_xperm_rule(src, tgt, cls, low, high, effect, n); + }); + } else { + avtab_key_t key; + 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, n); + } + return ret; +} + +int sepol_impl::add_xperm_rule(const char *s, const char *t, const char *c, const char *range, int effect, bool n) { + type_datum_t *src = nullptr, *tgt = nullptr; + class_datum_t *cls = nullptr; + + if (s) { + src = hashtab_find(db->p_types.table, s); + if (src == nullptr) { + LOGW("source type %s does not exist\n", s); + return 1; + } + } + + if (t) { + tgt = hashtab_find(db->p_types.table, t); + if (tgt == nullptr) { + LOGW("target type %s does not exist\n", t); + return 1; + } + } + + if (c) { + cls = hashtab_find(db->p_classes.table, c); + if (cls == nullptr) { + LOGW("class %s does not exist\n", c); + return 1; + } + } + + uint16_t low, high; + + if (range) { + if (strchr(range, '-')){ + sscanf(range, "%hx-%hx", &low, &high); + } else { + sscanf(range, "%hx", &low); + high = low; + } + } else { + low = 0; + high = 0xFFFF; + } + + return add_xperm_rule(src, tgt, cls, low, high, effect, n); +} + +int sepol_impl::create_domain(const char *type_name) { + symtab_datum_t *src = hashtab_find(db->p_types.table, type_name); + if (src) { + LOGW("Type %s already exists\n", type_name); + return 0; + } + + type_datum_t *type = auto_cast(xmalloc(sizeof(type_datum_t))); + type_datum_init(type); + type->primary = 1; + type->flavor = TYPE_TYPE; + + uint32_t value = 0; + symtab_insert(db, SYM_TYPES, strdup(type_name), type, SCOPE_DECL, 1, &value); + type->s.value = value; + + if (ebitmap_set_bit(&db->global->branch_list->declared.scope[SYM_TYPES], value - 1, 1)) { + return 1; + } + + db->type_attr_map = auto_cast(xrealloc(db->type_attr_map, sizeof(ebitmap_t) * db->p_types.nprim)); + db->attr_type_map = auto_cast(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_find(db->p_types.table, type_name); + if (!src) + return 1; + + if (policydb_index_decls(nullptr, db)) + return 1; + + if (policydb_index_classes(db)) + return 1; + + if (policydb_index_others(nullptr, db, 0)) + return 1; + + // 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); +} + +int sepol_impl::set_domain_state(const char *s, bool permissive) { + type_datum_t *type; + if (s == nullptr) { + hashtab_for_each(db->p_types.table, [&](hashtab_ptr_t node) { + type = auto_cast(node->datum); + if (ebitmap_set_bit(&db->permissive_map, type->s.value, permissive)) + LOGW("Could not set bit in permissive map\n"); + }); + } else { + type = hashtab_find(db->p_types.table, s); + if (type == nullptr) { + LOGW("type %s does not exist\n", s); + return 1; + } + if (ebitmap_set_bit(&db->permissive_map, type->s.value, permissive)) { + LOGW("Could not set bit in permissive map\n"); + return 1; + } + } + return 0; +} + +int sepol_impl::add_filename_trans(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; + filename_trans_datum_t *trans; + + src = hashtab_find(db->p_types.table, s); + if (src == nullptr) { + LOGW("source type %s does not exist\n", s); + return 1; + } + tgt = hashtab_find(db->p_types.table, t); + if (tgt == nullptr) { + LOGW("target type %s does not exist\n", t); + return 1; + } + cls = hashtab_find(db->p_classes.table, c); + if (cls == nullptr) { + LOGW("class %s does not exist\n", c); + return 1; + } + def = hashtab_find(db->p_types.table, d); + if (def == nullptr) { + LOGW("default type %s does not exist\n", d); + return 1; + } + + filename_trans_t trans_key; + trans_key.stype = src->s.value; + trans_key.ttype = tgt->s.value; + trans_key.tclass = cls->s.value; + trans_key.name = (char *) o; + + trans = hashtab_find(db->filename_trans, (hashtab_key_t) &trans_key); + + if (trans == nullptr) { + trans = auto_cast(xcalloc(sizeof(*trans), 1)); + hashtab_insert(db->filename_trans, (hashtab_key_t) &trans_key, trans); + } + + // Overwrite existing + trans->otype = def->s.value; + return 0; +} + +int sepol_impl::add_typeattribute(const char *type, const char *attr) { + type_datum_t *domain = hashtab_find(db->p_types.table, type); + if (domain == nullptr) { + LOGW("type %s does not exist\n", type); + return 1; + } + + int attr_val = set_attr(attr, domain->s.value); + if (attr_val < 0) + return 1; + + hashtab_for_each(db->p_classes.table, [&](hashtab_ptr_t node){ + auto cls = static_cast(node->datum); + for (constraint_node_t *n = cls->constraints; n ; n = n->next) { + for (constraint_expr_t *e = n->expr; e; e = e->next) { + if (e->expr_type == CEXPR_NAMES && + ebitmap_get_bit(&e->type_names->types, attr_val - 1)) { + ebitmap_set_bit(&e->names, domain->s.value - 1, 1); + } + } + } + }); + return 0; +} + +int sepol_impl::add_type_rule(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_find(db->p_types.table, s); + if (src == nullptr) { + LOGW("source type %s does not exist\n", s); + return 1; + } + tgt = hashtab_find(db->p_types.table, t); + if (tgt == nullptr) { + LOGW("target type %s does not exist\n", t); + return 1; + } + cls = hashtab_find(db->p_classes.table, c); + if (cls == nullptr) { + LOGW("class %s does not exist\n", c); + return 1; + } + def = hashtab_find(db->p_types.table, d); + if (def == nullptr) { + LOGW("default type %s does not exist\n", d); + return 1; + } + + avtab_key_t key; + key.source_type = src->s.value; + key.target_type = tgt->s.value; + key.target_class = cls->s.value; + key.specified = effect; + + avtab_ptr_t node = get_avtab_node(&key, nullptr); + node->datum.data = def->s.value; + + return 0; +} + +int sepol_impl::add_genfscon(const char *fs_name, const char *path, const char *context) { + // First try to create context + context_struct_t *ctx; + if (context_from_string(nullptr, db, &ctx, context, strlen(context))) { + LOGW("Failed to create context from string [%s]\n", context); + return 1; + } + + // Allocate genfs context + ocontext_t *newc = auto_cast(xcalloc(sizeof(*newc), 1)); + newc->u.name = strdup(path); + memcpy(&newc->context[0], ctx, sizeof(*ctx)); + free(ctx); + + // Find or allocate genfs + genfs_t *last_gen = nullptr; + genfs_t *newfs = nullptr; + for (genfs_t *node = db->genfs; node; node = node->next) { + if (strcmp(node->fstype, fs_name) == 0) { + newfs = node; + break; + } + last_gen = node; + } + if (newfs == nullptr) { + newfs = auto_cast(xcalloc(sizeof(*newfs), 1)); + newfs->fstype = strdup(fs_name); + // Insert + if (last_gen) + last_gen->next = newfs; + else + db->genfs = newfs; + } + + // Insert or replace genfs context + ocontext_t *last_ctx = nullptr; + for (ocontext_t *node = newfs->head; node; node = node->next) { + if (strcmp(node->u.name, path) == 0) { + // Unlink + if (last_ctx) + last_ctx->next = node->next; + else + newfs->head = nullptr; + // Destroy old node + free(node->u.name); + context_destroy(&node->context[0]); + free(node); + break; + } + last_ctx = node; + } + // Insert + if (last_ctx) + last_ctx->next = newc; + else + newfs->head = newc; + + return 0; +} + +void sepol_impl::strip_dontaudit() { + avtab_for_each(&db->te_avtab, [=](avtab_ptr_t node) { + if (node->key.specified == AVTAB_AUDITDENY || node->key.specified == AVTAB_XPERMS_DONTAUDIT) + avtab_remove_node(&db->te_avtab, node); + }); +} + +int sepolicy::allow(const char *s, const char *t, const char *c, const char *p) { + dprint(__FUNCTION__, s, t, c, p); + return impl->add_rule(s, t, c, p, AVTAB_ALLOWED, false); +} + +int sepolicy::deny(const char *s, const char *t, const char *c, const char *p) { + dprint(__FUNCTION__, s, t, c, p); + return impl->add_rule(s, t, c, p, AVTAB_ALLOWED, true); +} + +int sepolicy::auditallow(const char *s, const char *t, const char *c, const char *p) { + dprint(__FUNCTION__, s, t, c, p); + return impl->add_rule(s, t, c, p, AVTAB_AUDITALLOW, false); +} + +int sepolicy::dontaudit(const char *s, const char *t, const char *c, const char *p) { + dprint(__FUNCTION__, s, t, c, p); + return impl->add_rule(s, t, c, p, AVTAB_AUDITDENY, true); +} + +int sepolicy::allowxperm(const char *s, const char *t, const char *c, const char *range) { + dprint(__FUNCTION__, s, t, c, "ioctl", range); + return impl->add_xperm_rule(s, t, c, range, AVTAB_XPERMS_ALLOWED, false); +} + +int sepolicy::auditallowxperm(const char *s, const char *t, const char *c, const char *range) { + dprint(__FUNCTION__, s, t, c, "ioctl", range); + return impl->add_xperm_rule(s, t, c, range, AVTAB_XPERMS_AUDITALLOW, false); +} + +int sepolicy::dontauditxperm(const char *s, const char *t, const char *c, const char *range) { + dprint(__FUNCTION__, s, t, c, "ioctl", range); + return impl->add_xperm_rule(s, t, c, range, AVTAB_XPERMS_DONTAUDIT, false); +} + +int sepolicy::type_change(const char *s, const char *t, const char *c, const char *d) { + dprint(__FUNCTION__, s, t, c, d); + return impl->add_type_rule(s, t, c, d, AVTAB_CHANGE); +} + +int sepolicy::type_member(const char *s, const char *t, const char *c, const char *d) { + dprint(__FUNCTION__, s, t, c, d); + return impl->add_type_rule(s, t, c, d, AVTAB_MEMBER); +} + +int sepolicy::type_transition(const char *s, const char *t, const char *c, const char *d, const char *o) { + if (o) { + dprint(__FUNCTION__, s, t, c, d); + return impl->add_type_rule(s, t, c, d, AVTAB_TRANSITION); + } else { + dprint(__FUNCTION__, s, t, c, d, o); + return impl->add_filename_trans(s, t, c, d, o); + } +} + +int sepolicy::permissive(const char *s) { + dprint(__FUNCTION__, s); + return impl->set_domain_state(s, true); +} + +int sepolicy::enforce(const char *s) { + dprint(__FUNCTION__, s); + return impl->set_domain_state(s, false); +} + +int sepolicy::create(const char *s) { + dprint(__FUNCTION__, s); + return impl->create_domain(s); +} + +int sepolicy::typeattribute(const char *type, const char *attr) { + dprint(__FUNCTION__, type, attr); + return impl->add_typeattribute(type, attr); +} + +int sepolicy::genfscon(const char *fs_name, const char *path, const char *ctx) { + dprint(__FUNCTION__, fs_name, path, ctx); + return impl->add_genfscon(fs_name, path, ctx); +} + +int sepolicy::exists(const char *source) { + return hashtab_search(db->p_types.table, source) != nullptr; +} diff --git a/native/jni/magiskpolicy/sepolicy.h b/native/jni/magiskpolicy/sepolicy.h deleted file mode 100644 index 6aaa9d913..000000000 --- a/native/jni/magiskpolicy/sepolicy.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include - -__BEGIN_DECLS - -// 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); - -void statement_help(); - -__END_DECLS diff --git a/native/jni/magiskpolicy/sepolicy.hpp b/native/jni/magiskpolicy/sepolicy.hpp new file mode 100644 index 000000000..8c951405b --- /dev/null +++ b/native/jni/magiskpolicy/sepolicy.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include +#include + +// Internal APIs, do not use directly +struct sepol_impl : public sepolicy { + int set_attr(const char *attr_name, int type_val); + void check_avtab_node(avtab_ptr_t node); + avtab_ptr_t get_avtab_node(avtab_key_t *key, avtab_extended_perms_t *xperms); + int add_avrule(avtab_key_t *key, int val, bool n); + int add_rule(const char *s, const char *t, const char *c, const char *p, int effect, bool n); + int add_rule(type_datum_t *src, type_datum_t *tgt, class_datum_t *cls, perm_datum_t *perm, int effect, bool n); + int add_avxrule(avtab_key_t *key, uint16_t low, uint16_t high, bool n); + int add_xperm_rule(type_datum_t *src, type_datum_t *tgt, + class_datum_t *cls, uint16_t low, uint16_t high, int effect, bool n); + int add_xperm_rule(const char *s, const char *t, const char *c, const char *range, int effect, bool n); + int create_domain(const char *type_name); + int set_domain_state(const char *s, bool permissive); + int add_filename_trans(const char *s, const char *t, const char *c, const char *d, const char *o); + int add_typeattribute(const char *type, const char *attr); + int add_type_rule(const char *s, const char *t, const char *c, const char *d, int effect); + int add_genfscon(const char *fs_name, const char *path, const char *context); + void strip_dontaudit(); + void allow_su_client(const char *type); +}; + +#define impl static_cast(this) + +void statement_help(); diff --git a/native/jni/magiskpolicy/statement.cpp b/native/jni/magiskpolicy/statement.cpp index 1689cd607..1d03e7b85 100644 --- a/native/jni/magiskpolicy/statement.cpp +++ b/native/jni/magiskpolicy/statement.cpp @@ -6,7 +6,7 @@ #include #include -#include "sepolicy.h" +#include "sepolicy.hpp" using namespace std;