diff --git a/native/build.gradle.kts b/native/build.gradle.kts index 1c89d22b7..8df092837 100644 --- a/native/build.gradle.kts +++ b/native/build.gradle.kts @@ -15,7 +15,7 @@ android { externalNativeBuild { ndkBuild { // Pass arguments to ndk-build. - arguments("B_MAGISK=1", "B_INIT=1", "B_BOOT=1", "B_TEST=1", + arguments("B_MAGISK=1", "B_INIT=1", "B_BOOT=1", "B_TEST=1", "B_POLICY=1", "MAGISK_DEBUG=1", "MAGISK_VERSION=debug", "MAGISK_VER_CODE=INT_MAX") } } diff --git a/native/jni/Android.mk b/native/jni/Android.mk index d805d4618..a979708cd 100644 --- a/native/jni/Android.mk +++ b/native/jni/Android.mk @@ -54,7 +54,7 @@ include $(CLEAR_VARS) LOCAL_MODULE := magiskinit LOCAL_STATIC_LIBRARIES := \ libutilx \ - libsepol \ + libpolicy \ libxz LOCAL_SRC_FILES := \ @@ -63,11 +63,7 @@ LOCAL_SRC_FILES := \ init/rootdir.cpp \ init/getinfo.cpp \ init/twostage.cpp \ - init/selinux.cpp \ - magiskpolicy/sepolicy.cpp \ - magiskpolicy/rules.cpp \ - magiskpolicy/policydb.cpp \ - magiskpolicy/statement.cpp + init/selinux.cpp LOCAL_LDFLAGS := -static include $(BUILD_EXECUTABLE) @@ -110,14 +106,9 @@ include $(CLEAR_VARS) LOCAL_MODULE := magiskpolicy LOCAL_STATIC_LIBRARIES := \ libutils \ - libsepol + libpolicy -LOCAL_SRC_FILES := \ - magiskpolicy/main.cpp \ - magiskpolicy/sepolicy.cpp \ - magiskpolicy/rules.cpp \ - magiskpolicy/policydb.cpp \ - magiskpolicy/statement.cpp +LOCAL_SRC_FILES := magiskpolicy/main.cpp include $(BUILD_EXECUTABLE) @@ -158,14 +149,30 @@ include $(BUILD_EXECUTABLE) endif endif +######################## +# Libraries +######################## + +include $(CLEAR_VARS) +LOCAL_MODULE:= libpolicy +LOCAL_STATIC_LIBRARIES := \ + libutils \ + libsepol +LOCAL_C_INCLUDES := jni/magiskpolicy jni/magiskpolicy/include +LOCAL_EXPORT_C_INCLUDES := jni/magiskpolicy/include +LOCAL_SRC_FILES := \ + magiskpolicy/api.cpp \ + magiskpolicy/sepolicy.cpp \ + magiskpolicy/rules.cpp \ + magiskpolicy/policydb.cpp \ + magiskpolicy/statement.cpp +include $(BUILD_STATIC_LIBRARY) + +include jni/utils/Android.mk +include jni/external/Android.mk + ifdef B_BB include jni/external/busybox/Android.mk endif - -######################## -# Libraries -######################## -include jni/utils/Android.mk -include jni/external/Android.mk diff --git a/native/jni/init/selinux.cpp b/native/jni/init/selinux.cpp index 7fbc9fa90..e06935f1a 100644 --- a/native/jni/init/selinux.cpp +++ b/native/jni/init/selinux.cpp @@ -1,7 +1,7 @@ #include #include -#include +#include #include #include "init.hpp" diff --git a/native/jni/magiskpolicy/api.cpp b/native/jni/magiskpolicy/api.cpp new file mode 100644 index 000000000..8d7606d98 --- /dev/null +++ b/native/jni/magiskpolicy/api.cpp @@ -0,0 +1,105 @@ +#include + +#include "policy.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 + +bool 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); +} + +bool 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); +} + +bool 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); +} + +bool 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); +} + +bool 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); +} + +bool 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); +} + +bool 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); +} + +bool 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); +} + +bool 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); +} + +bool 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, o); + return impl->add_filename_trans(s, t, c, d, o); + } else { + dprint(__FUNCTION__, s, t, c, d); + return impl->add_type_rule(s, t, c, d, AVTAB_TRANSITION); + } +} + +bool sepolicy::permissive(const char *s) { + dprint(__FUNCTION__, s); + return impl->set_type_state(s, true); +} + +bool sepolicy::enforce(const char *s) { + dprint(__FUNCTION__, s); + return impl->set_type_state(s, false); +} + +bool sepolicy::type(const char *name, const char *attr) { + dprint(__FUNCTION__, name, attr); + return impl->add_type(name, TYPE_TYPE) && impl->add_typeattribute(name, attr); +} + +bool sepolicy::attribute(const char *name) { + dprint(__FUNCTION__, name); + return impl->add_type(name, TYPE_ATTRIB); +} + +bool sepolicy::typeattribute(const char *type, const char *attr) { + dprint(__FUNCTION__, type, attr); + return impl->add_typeattribute(type, attr); +} + +bool 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); +} + +bool sepolicy::exists(const char *type) { + return hashtab_search(impl->db->p_types.table, type) != nullptr; +} diff --git a/native/jni/include/magiskpolicy.hpp b/native/jni/magiskpolicy/include/sepolicy.hpp similarity index 94% rename from native/jni/include/magiskpolicy.hpp rename to native/jni/magiskpolicy/include/sepolicy.hpp index 9153ca956..46c86735a 100644 --- a/native/jni/include/magiskpolicy.hpp +++ b/native/jni/magiskpolicy/include/sepolicy.hpp @@ -6,12 +6,8 @@ #define ALL nullptr -struct policydb; - -class sepolicy { -public: +struct sepolicy { using c_str = const char *; - ~sepolicy(); // Public static factory functions static sepolicy *from_data(char *data, size_t len); @@ -59,5 +55,6 @@ public: bool create(c_str name) { return type(name, "domain"); } protected: - policydb *db; + // Prevent anyone from accidentally creating an instance + sepolicy() = default; }; diff --git a/native/jni/magiskpolicy/main.cpp b/native/jni/magiskpolicy/main.cpp index a7c713a96..6a91a2c13 100644 --- a/native/jni/magiskpolicy/main.cpp +++ b/native/jni/magiskpolicy/main.cpp @@ -1,8 +1,7 @@ #include #include -#include -#include "sepolicy.hpp" +#include "policy.hpp" using namespace std; diff --git a/native/jni/magiskpolicy/sepolicy.hpp b/native/jni/magiskpolicy/policy.hpp similarity index 86% rename from native/jni/magiskpolicy/sepolicy.hpp rename to native/jni/magiskpolicy/policy.hpp index c4df9c0f0..b02edb673 100644 --- a/native/jni/magiskpolicy/sepolicy.hpp +++ b/native/jni/magiskpolicy/policy.hpp @@ -1,11 +1,11 @@ #pragma once -#include -#include +// libse internal APIs, do not use directly + +#include +#include -// Internal APIs, do not use directly struct sepol_impl : public sepolicy { - void check_avtab_node(avtab_ptr_t node); avtab_ptr_t get_avtab_node(avtab_key_t *key, avtab_extended_perms_t *xperms); bool add_rule(const char *s, const char *t, const char *c, const char *p, int effect, bool invert); void add_rule(type_datum_t *src, type_datum_t *tgt, class_datum_t *cls, perm_datum_t *perm, int effect, bool invert); @@ -20,8 +20,13 @@ struct sepol_impl : public sepolicy { void add_typeattribute(type_datum_t *type, type_datum_t *attr); bool add_typeattribute(const char *type, const char *attr); void strip_dontaudit(); + + sepol_impl(policydb *db) : db(db) {} + ~sepol_impl(); + + policydb *db; }; -#define impl static_cast(this) +#define impl reinterpret_cast(this) void statement_help(); diff --git a/native/jni/magiskpolicy/policydb.cpp b/native/jni/magiskpolicy/policydb.cpp index d035c256c..cfb2c72ff 100644 --- a/native/jni/magiskpolicy/policydb.cpp +++ b/native/jni/magiskpolicy/policydb.cpp @@ -7,9 +7,8 @@ #include #include -#include -#include "sepolicy.hpp" +#include "policy.hpp" #define SHALEN 64 static bool cmp_sha256(const char *a, const char *b) { @@ -95,8 +94,7 @@ sepolicy *sepolicy::from_data(char *data, size_t len) { return nullptr; } - auto sepol = new sepolicy(); - sepol->db = db; + auto sepol = new sepol_impl(db); return sepol; } @@ -116,8 +114,7 @@ sepolicy *sepolicy::from_file(const char *file) { return nullptr; } - auto sepol = new sepolicy(); - sepol->db = db; + auto sepol = new sepol_impl(db); return sepol; } @@ -216,8 +213,7 @@ sepolicy *sepolicy::compile_split() { if (cil_build_policydb(db, &pdb)) return nullptr; - auto sepol = new sepolicy(); - sepol->db = &pdb->p; + auto sepol = new sepol_impl(&pdb->p); return sepol; } @@ -232,7 +228,7 @@ sepolicy *sepolicy::from_split() { return sepolicy::compile_split(); } -sepolicy::~sepolicy() { +sepol_impl::~sepol_impl() { policydb_destroy(db); free(db); } @@ -241,8 +237,8 @@ bool sepolicy::to_file(const char *file) { uint8_t *data; size_t len; - /* 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 */ + // 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(data, len); run_finally fin([=]{ free(data); }); @@ -251,7 +247,7 @@ bool sepolicy::to_file(const char *file) { policy_file_init(&pf); pf.type = PF_USE_STDIO; pf.fp = fp.get(); - if (policydb_write(db, &pf)) { + if (policydb_write(impl->db, &pf)) { LOGE("Fail to create policy image\n"); return false; } diff --git a/native/jni/magiskpolicy/rules.cpp b/native/jni/magiskpolicy/rules.cpp index c20ab9f38..b3d232277 100644 --- a/native/jni/magiskpolicy/rules.cpp +++ b/native/jni/magiskpolicy/rules.cpp @@ -1,7 +1,6 @@ #include -#include -#include "sepolicy.hpp" +#include "policy.hpp" using namespace std; @@ -27,7 +26,7 @@ void sepolicy::magisk_rules() { // Make our root domain unconstrained allow(SEPOL_PROC_DOMAIN, ALL, ALL, ALL); // Allow us to do any ioctl - if (db->policyvers >= POLICYDB_VERSION_XPERMS_IOCTL) { + if (impl->db->policyvers >= POLICYDB_VERSION_XPERMS_IOCTL) { allowxperm(SEPOL_PROC_DOMAIN, ALL, "blk_file", ALL); allowxperm(SEPOL_PROC_DOMAIN, ALL, "fifo_file", ALL); allowxperm(SEPOL_PROC_DOMAIN, ALL, "chr_file", ALL); diff --git a/native/jni/magiskpolicy/sepolicy.cpp b/native/jni/magiskpolicy/sepolicy.cpp index a16639969..e2fd086b8 100644 --- a/native/jni/magiskpolicy/sepolicy.cpp +++ b/native/jni/magiskpolicy/sepolicy.cpp @@ -1,22 +1,6 @@ -#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 +#include "policy.hpp" // Invert is adding rules for auditdeny; in other cases, invert is removing rules #define strip_av(effect, invert) ((effect == AVTAB_AUDITDENY) == !invert) @@ -106,16 +90,15 @@ static int avtab_remove_node(avtab_t *h, avtab_ptr_t node) { return 0; } -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); +static bool is_redundant(avtab_ptr_t node) { + switch (node->key.specified) { + case AVTAB_AUDITDENY: + return node->datum.data == ~0U; + case AVTAB_XPERMS: + return node->datum.xperms == nullptr; + default: + return node->datum.data == 0U; + } } avtab_ptr_t sepol_impl::get_avtab_node(avtab_key_t *key, avtab_extended_perms_t *xperms) { @@ -199,7 +182,9 @@ void sepol_impl::add_rule(type_datum_t *src, type_datum_t *tgt, class_datum_t *c else node->datum.data = ~0U; } - check_avtab_node(node); + + if (is_redundant(node)) + avtab_remove_node(&db->te_avtab, node); } } @@ -622,92 +607,3 @@ void sepol_impl::strip_dontaudit() { avtab_remove_node(&db->te_avtab, node); }); } - -bool 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); -} - -bool 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); -} - -bool 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); -} - -bool 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); -} - -bool 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); -} - -bool 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); -} - -bool 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); -} - -bool 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); -} - -bool 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); -} - -bool 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, o); - return impl->add_filename_trans(s, t, c, d, o); - } else { - dprint(__FUNCTION__, s, t, c, d); - return impl->add_type_rule(s, t, c, d, AVTAB_TRANSITION); - } -} - -bool sepolicy::permissive(const char *s) { - dprint(__FUNCTION__, s); - return impl->set_type_state(s, true); -} - -bool sepolicy::enforce(const char *s) { - dprint(__FUNCTION__, s); - return impl->set_type_state(s, false); -} - -bool sepolicy::type(const char *name, const char *attr) { - dprint(__FUNCTION__, name, attr); - return impl->add_type(name, TYPE_TYPE) && impl->add_typeattribute(name, attr); -} - -bool sepolicy::attribute(const char *name) { - dprint(__FUNCTION__, name); - return impl->add_type(name, TYPE_ATTRIB); -} - -bool sepolicy::typeattribute(const char *type, const char *attr) { - dprint(__FUNCTION__, type, attr); - return impl->add_typeattribute(type, attr); -} - -bool 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); -} - -bool sepolicy::exists(const char *source) { - return hashtab_search(db->p_types.table, source) != nullptr; -} diff --git a/native/jni/magiskpolicy/statement.cpp b/native/jni/magiskpolicy/statement.cpp index 201eb0c69..61b6f496c 100644 --- a/native/jni/magiskpolicy/statement.cpp +++ b/native/jni/magiskpolicy/statement.cpp @@ -2,10 +2,9 @@ #include #include -#include #include -#include "sepolicy.hpp" +#include "policy.hpp" using namespace std;