Remove an additional unique_ptr indirection

This commit is contained in:
topjohnwu 2025-02-05 14:18:16 +08:00
parent a14fc90f07
commit b7ca73f431
10 changed files with 109 additions and 129 deletions

View File

@ -9,19 +9,19 @@ using namespace std;
void MagiskInit::patch_sepolicy(const char *in, const char *out) {
LOGD("Patching monolithic policy\n");
auto sepol = unique_ptr<sepolicy>(sepolicy::from_file(in));
auto sepol = SePolicy::from_file(in);
sepol->magisk_rules();
sepol.magisk_rules();
// Custom rules
auto rule = "/data/" PREINITMIRR "/sepolicy.rule";
if (xaccess(rule, R_OK) == 0) {
LOGD("Loading custom sepolicy patch: [%s]\n", rule);
sepol->load_rule_file(rule);
sepol.load_rule_file(rule);
}
LOGD("Dumping sepolicy to: [%s]\n", out);
sepol->to_file(out);
sepol.to_file(out);
// Remove OnePlus stupid debug sepolicy and use our own
if (access("/sepolicy_debug", F_OK) == 0) {
@ -124,12 +124,12 @@ bool MagiskInit::hijack_sepolicy() {
xumount2(SELINUX_ENFORCE, MNT_DETACH);
// Load and patch policy
auto sepol = unique_ptr<sepolicy>(sepolicy::from_file(MOCK_LOAD));
sepol->magisk_rules();
sepol->load_rules(rules);
auto sepol = SePolicy::from_file(MOCK_LOAD);
sepol.magisk_rules();
sepol.load_rules(rules);
// Load patched policy into kernel
sepol->to_file(SELINUX_LOAD);
sepol.to_file(SELINUX_LOAD);
// restore mounted files' context after sepolicy loaded
rust::reset_overlay_contexts();

View File

@ -62,70 +62,70 @@ static inline void expand(const Xperms &vec, T &&...args) {
}
}
void sepolicy::allow(StrVec src, StrVec tgt, StrVec cls, StrVec perm) noexcept {
void SePolicy::allow(StrVec src, StrVec tgt, StrVec cls, StrVec perm) noexcept {
expand(src, tgt, cls, perm, [this](auto ...args) {
print_rule("allow", args...);
impl->add_rule(args..., AVTAB_ALLOWED, false);
});
}
void sepolicy::deny(StrVec src, StrVec tgt, StrVec cls, StrVec perm) noexcept {
void SePolicy::deny(StrVec src, StrVec tgt, StrVec cls, StrVec perm) noexcept {
expand(src, tgt, cls, perm, [this](auto ...args) {
print_rule("deny", args...);
impl->add_rule(args..., AVTAB_ALLOWED, true);
});
}
void sepolicy::auditallow(StrVec src, StrVec tgt, StrVec cls, StrVec perm) noexcept {
void SePolicy::auditallow(StrVec src, StrVec tgt, StrVec cls, StrVec perm) noexcept {
expand(src, tgt, cls, perm, [this](auto ...args) {
print_rule("auditallow", args...);
impl->add_rule(args..., AVTAB_AUDITALLOW, false);
});
}
void sepolicy::dontaudit(StrVec src, StrVec tgt, StrVec cls, StrVec perm) noexcept {
void SePolicy::dontaudit(StrVec src, StrVec tgt, StrVec cls, StrVec perm) noexcept {
expand(src, tgt, cls, perm, [this](auto ...args) {
print_rule("dontaudit", args...);
impl->add_rule(args..., AVTAB_AUDITDENY, true);
});
}
void sepolicy::permissive(StrVec types) noexcept {
void SePolicy::permissive(StrVec types) noexcept {
expand(types, [this](auto ...args) {
print_rule("permissive", args...);
impl->set_type_state(args..., true);
});
}
void sepolicy::enforce(StrVec types) noexcept {
void SePolicy::enforce(StrVec types) noexcept {
expand(types, [this](auto ...args) {
print_rule("enforce", args...);
impl->set_type_state(args..., false);
});
}
void sepolicy::typeattribute(StrVec types, StrVec attrs) noexcept {
void SePolicy::typeattribute(StrVec types, StrVec attrs) noexcept {
expand(types, attrs, [this](auto ...args) {
print_rule("typeattribute", args...);
impl->add_typeattribute(args...);
});
}
void sepolicy::type(Str type, StrVec attrs) noexcept {
void SePolicy::type(Str type, StrVec attrs) noexcept {
expand(type, attrs, [this](auto name, auto attr) {
print_rule("type", name, attr);
impl->add_type(name, TYPE_TYPE) && impl->add_typeattribute(name, attr);
});
}
void sepolicy::attribute(Str name) noexcept {
void SePolicy::attribute(Str name) noexcept {
expand(name, [this](auto ...args) {
print_rule("attribute", args...);
impl->add_type(args..., TYPE_ATTRIB);
});
}
void sepolicy::type_transition(Str src, Str tgt, Str cls, Str def, Str obj) noexcept {
void SePolicy::type_transition(Str src, Str tgt, Str cls, Str def, Str obj) noexcept {
expand(src, tgt, cls, def, obj, [this](auto s, auto t, auto c, auto d, auto o) {
if (o) {
print_rule("type_transition", s, t, c, d, o);
@ -137,42 +137,42 @@ void sepolicy::type_transition(Str src, Str tgt, Str cls, Str def, Str obj) noex
});
}
void sepolicy::type_change(Str src, Str tgt, Str cls, Str def) noexcept {
void SePolicy::type_change(Str src, Str tgt, Str cls, Str def) noexcept {
expand(src, tgt, cls, def, [this](auto ...args) {
print_rule("type_change", args...);
impl->add_type_rule(args..., AVTAB_CHANGE);
});
}
void sepolicy::type_member(Str src, Str tgt, Str cls, Str def) noexcept {
void SePolicy::type_member(Str src, Str tgt, Str cls, Str def) noexcept {
expand(src, tgt, cls, def, [this](auto ...args) {
print_rule("type_member", args...);
impl->add_type_rule(args..., AVTAB_MEMBER);
});
}
void sepolicy::genfscon(Str fs_name, Str path, Str ctx) noexcept {
void SePolicy::genfscon(Str fs_name, Str path, Str ctx) noexcept {
expand(fs_name, path, ctx, [this](auto ...args) {
print_rule("genfscon", args...);
impl->add_genfscon(args...);
});
}
void sepolicy::allowxperm(StrVec src, StrVec tgt, StrVec cls, Xperms xperm) noexcept {
void SePolicy::allowxperm(StrVec src, StrVec tgt, StrVec cls, Xperms xperm) noexcept {
expand(src, tgt, cls, xperm, [this](auto ...args) {
print_rule("allowxperm", args...);
impl->add_xperm_rule(args..., AVTAB_XPERMS_ALLOWED);
});
}
void sepolicy::auditallowxperm(StrVec src, StrVec tgt, StrVec cls, Xperms xperm) noexcept {
void SePolicy::auditallowxperm(StrVec src, StrVec tgt, StrVec cls, Xperms xperm) noexcept {
expand(src, tgt, cls, xperm, [this](auto ...args) {
print_rule("auditallowxperm", args...);
impl->add_xperm_rule(args..., AVTAB_XPERMS_AUDITALLOW);
});
}
void sepolicy::dontauditxperm(StrVec src, StrVec tgt, StrVec cls, Xperms xperm) noexcept {
void SePolicy::dontauditxperm(StrVec src, StrVec tgt, StrVec cls, Xperms xperm) noexcept {
expand(src, tgt, cls, xperm, [this](auto ...args) {
print_rule("dontauditxperm", args...);
impl->add_xperm_rule(args..., AVTAB_XPERMS_DONTAUDIT);

View File

@ -6,6 +6,7 @@
#include <base.hpp>
#include "../policy-rs.hpp"
// sepolicy paths
#define PLAT_POLICY_DIR "/system/etc/selinux/"
#define VEND_POLICY_DIR "/vendor/etc/selinux/"

View File

@ -1,14 +1,14 @@
#![feature(format_args_nl)]
#![feature(try_blocks)]
use std::fmt::Write;
use std::io::{BufRead, BufReader, Cursor};
use cxx::CxxString;
pub use base;
use base::libc::{O_CLOEXEC, O_RDONLY};
use base::{BufReadExt, FsPath, LoggedResult, Utf8CStr};
use cxx::CxxString;
use std::fmt::Write;
use std::io::{BufRead, BufReader, Cursor};
use crate::ffi::sepolicy;
use crate::ffi::SePolicy;
mod rules;
mod statement;
@ -21,7 +21,7 @@ pub mod ffi {
reset: bool,
}
pub struct sepolicy {
struct SePolicy {
#[cxx_name = "impl"]
_impl: UniquePtr<sepol_impl>,
}
@ -36,88 +36,70 @@ pub mod ffi {
type sepol_impl;
fn allow(self: &mut sepolicy, s: Vec<&str>, t: Vec<&str>, c: Vec<&str>, p: Vec<&str>);
fn deny(self: &mut sepolicy, s: Vec<&str>, t: Vec<&str>, c: Vec<&str>, p: Vec<&str>);
fn auditallow(
self: &mut sepolicy,
s: Vec<&str>,
t: Vec<&str>,
c: Vec<&str>,
p: Vec<&str>,
);
fn dontaudit(
self: &mut sepolicy,
s: Vec<&str>,
t: Vec<&str>,
c: Vec<&str>,
p: Vec<&str>,
);
fn allowxperm(
self: &mut sepolicy,
s: Vec<&str>,
t: Vec<&str>,
c: Vec<&str>,
p: Vec<Xperm>,
);
fn allow(self: &mut SePolicy, s: Vec<&str>, t: Vec<&str>, c: Vec<&str>, p: Vec<&str>);
fn deny(self: &mut SePolicy, s: Vec<&str>, t: Vec<&str>, c: Vec<&str>, p: Vec<&str>);
fn auditallow(self: &mut SePolicy, s: Vec<&str>, t: Vec<&str>, c: Vec<&str>, p: Vec<&str>);
fn dontaudit(self: &mut SePolicy, s: Vec<&str>, t: Vec<&str>, c: Vec<&str>, p: Vec<&str>);
fn allowxperm(self: &mut SePolicy, s: Vec<&str>, t: Vec<&str>, c: Vec<&str>, p: Vec<Xperm>);
fn auditallowxperm(
self: &mut sepolicy,
self: &mut SePolicy,
s: Vec<&str>,
t: Vec<&str>,
c: Vec<&str>,
p: Vec<Xperm>,
);
fn dontauditxperm(
self: &mut sepolicy,
self: &mut SePolicy,
s: Vec<&str>,
t: Vec<&str>,
c: Vec<&str>,
p: Vec<Xperm>,
);
fn permissive(self: &mut sepolicy, t: Vec<&str>);
fn enforce(self: &mut sepolicy, t: Vec<&str>);
fn typeattribute(self: &mut sepolicy, t: Vec<&str>, a: Vec<&str>);
fn permissive(self: &mut SePolicy, t: Vec<&str>);
fn enforce(self: &mut SePolicy, t: Vec<&str>);
fn typeattribute(self: &mut SePolicy, t: Vec<&str>, a: Vec<&str>);
#[cxx_name = "type"]
fn type_(self: &mut sepolicy, t: &str, a: Vec<&str>);
fn attribute(self: &mut sepolicy, t: &str);
fn type_transition(self: &mut sepolicy, s: &str, t: &str, c: &str, d: &str, o: &str);
fn type_change(self: &mut sepolicy, s: &str, t: &str, c: &str, d: &str);
fn type_member(self: &mut sepolicy, s: &str, t: &str, c: &str, d: &str);
fn genfscon(self: &mut sepolicy, s: &str, t: &str, c: &str);
fn type_(self: &mut SePolicy, t: &str, a: Vec<&str>);
fn attribute(self: &mut SePolicy, t: &str);
fn type_transition(self: &mut SePolicy, s: &str, t: &str, c: &str, d: &str, o: &str);
fn type_change(self: &mut SePolicy, s: &str, t: &str, c: &str, d: &str);
fn type_member(self: &mut SePolicy, s: &str, t: &str, c: &str, d: &str);
fn genfscon(self: &mut SePolicy, s: &str, t: &str, c: &str);
#[allow(dead_code)]
fn strip_dontaudit(self: &mut sepolicy);
fn strip_dontaudit(self: &mut SePolicy);
fn print_rules(self: &sepolicy);
fn to_file(self: &sepolicy, file: Utf8CStrRef) -> bool;
fn print_rules(self: &SePolicy);
fn to_file(self: &SePolicy, file: Utf8CStrRef) -> bool;
#[Self = sepolicy]
fn from_file(file: Utf8CStrRef) -> UniquePtr<sepolicy>;
#[Self = sepolicy]
fn from_split() -> UniquePtr<sepolicy>;
#[Self = sepolicy]
fn compile_split() -> UniquePtr<sepolicy>;
#[Self = sepolicy]
unsafe fn from_data(data: *mut c_char, len: usize) -> UniquePtr<sepolicy>;
#[Self = SePolicy]
fn from_file(file: Utf8CStrRef) -> SePolicy;
#[Self = SePolicy]
fn from_split() -> SePolicy;
#[Self = SePolicy]
fn compile_split() -> SePolicy;
#[Self = SePolicy]
unsafe fn from_data(data: *mut c_char, len: usize) -> SePolicy;
}
extern "Rust" {
fn parse_statement(self: &mut sepolicy, statement: Utf8CStrRef);
fn magisk_rules(self: &mut sepolicy);
fn load_rule_file(self: &mut sepolicy, filename: Utf8CStrRef);
fn load_rules(self: &mut sepolicy, rules: &CxxString);
#[Self = sepolicy]
fn parse_statement(self: &mut SePolicy, statement: Utf8CStrRef);
fn magisk_rules(self: &mut SePolicy);
fn load_rule_file(self: &mut SePolicy, filename: Utf8CStrRef);
fn load_rules(self: &mut SePolicy, rules: &CxxString);
#[Self = SePolicy]
fn xperm_to_string(perm: &Xperm) -> String;
#[Self = sepolicy]
#[Self = SePolicy]
fn print_statement_help();
}
}
impl sepolicy {
fn load_rules(self: &mut sepolicy, rules: &CxxString) {
impl SePolicy {
fn load_rules(self: &mut SePolicy, rules: &CxxString) {
let mut cursor = Cursor::new(rules.as_bytes());
self.load_rules_from_reader(&mut cursor);
}
pub fn load_rule_file(self: &mut sepolicy, filename: &Utf8CStr) {
pub fn load_rule_file(self: &mut SePolicy, filename: &Utf8CStr) {
let result: LoggedResult<()> = try {
let file = FsPath::from(filename).open(O_RDONLY | O_CLOEXEC)?;
let mut reader = BufReader::new(file);
@ -126,7 +108,7 @@ impl sepolicy {
result.ok();
}
fn load_rules_from_reader<T: BufRead>(self: &mut sepolicy, reader: &mut T) {
fn load_rules_from_reader<T: BufRead>(self: &mut SePolicy, reader: &mut T) {
reader.foreach_lines(|line| {
self.parse_statement(line);
true

View File

@ -36,7 +36,7 @@ int main(int argc, char *argv[]) {
cmdline_logging();
const char *out_file = nullptr;
vector<string_view> rule_files;
std::unique_ptr<sepolicy> sepol;
SePolicy sepol;
bool magisk = false;
bool live = false;
bool print = false;
@ -56,21 +56,21 @@ int main(int argc, char *argv[]) {
else if (option == "load"sv) {
if (argv[i + 1] == nullptr)
usage(argv[0]);
sepol = sepolicy::from_file(argv[i + 1]);
if (!sepol) {
sepol = SePolicy::from_file(argv[i + 1]);
if (!sepol.impl) {
fprintf(stderr, "Cannot load policy from %s\n", argv[i + 1]);
return 1;
}
++i;
} else if (option == "load-split"sv) {
sepol = sepolicy::from_split();
if (!sepol) {
sepol = SePolicy::from_split();
if (!sepol.impl) {
fprintf(stderr, "Cannot load split cil\n");
return 1;
}
} else if (option == "compile-split"sv) {
sepol = sepolicy::compile_split();
if (!sepol) {
sepol = SePolicy::compile_split();
if (!sepol.impl) {
fprintf(stderr, "Cannot compile split cil\n");
return 1;
}
@ -85,7 +85,7 @@ int main(int argc, char *argv[]) {
rule_files.emplace_back(argv[i + 1]);
++i;
} else if (option == "help"sv) {
sepolicy::print_statement_help();
SePolicy::print_statement_help();
exit(0);
} else {
usage(argv[0]);
@ -96,32 +96,32 @@ int main(int argc, char *argv[]) {
}
// Use current policy if nothing is loaded
if (sepol == nullptr && !(sepol = sepolicy::from_file(SELINUX_POLICY))) {
if (!sepol.impl && !(sepol = SePolicy::from_file(SELINUX_POLICY)).impl) {
fprintf(stderr, "Cannot load policy from " SELINUX_POLICY "\n");
return 1;
}
if (print) {
sepol->print_rules();
sepol.print_rules();
return 0;
}
if (magisk)
sepol->magisk_rules();
sepol.magisk_rules();
if (!rule_files.empty())
for (const auto &rule_file : rule_files)
sepol->load_rule_file(rule_file.data());
sepol.load_rule_file(rule_file.data());
for (; i < argc; ++i)
sepol->parse_statement(argv[i]);
sepol.parse_statement(argv[i]);
if (live && !sepol->to_file(SELINUX_LOAD)) {
if (live && !sepol.to_file(SELINUX_LOAD)) {
fprintf(stderr, "Cannot apply policy\n");
return 1;
}
if (out_file && !sepol->to_file(out_file)) {
if (out_file && !sepol.to_file(out_file)) {
fprintf(stderr, "Cannot dump policy to %s\n", out_file);
return 1;
}

View File

@ -29,14 +29,13 @@ class sepol_impl {
void add_typeattribute(type_datum_t *type, type_datum_t *attr);
bool add_typeattribute(const char *type, const char *attr);
sepol_impl(policydb *db) : db(db) {}
policydb *db;
std::map<std::string_view, std::array<const char *, 32>> class_perm_names;
friend struct sepolicy;
friend struct SePolicy;
public:
sepol_impl(policydb *db) : db(db) {}
~sepol_impl();
};

View File

@ -79,7 +79,7 @@ static void load_cil(struct cil_db *db, const char *file) {
LOGD("cil_add [%s]\n", file);
}
std::unique_ptr<sepolicy> sepolicy::from_data(char *data, size_t len) noexcept {
SePolicy SePolicy::from_data(char *data, size_t len) noexcept {
LOGD("Load policy from data\n");
policy_file_t pf;
@ -92,12 +92,13 @@ std::unique_ptr<sepolicy> sepolicy::from_data(char *data, size_t len) noexcept {
if (policydb_init(db) || policydb_read(db, &pf, 0)) {
LOGE("Fail to load policy from data\n");
free(db);
return nullptr;
return {};
}
return std::make_unique<sepolicy>(sepolicy{.impl{new sepol_impl(db)}});
return {std::make_unique<sepol_impl>(db)};
}
std::unique_ptr<sepolicy> sepolicy::from_file(::rust::Utf8CStr file) noexcept {
SePolicy SePolicy::from_file(::rust::Utf8CStr file) noexcept {
LOGD("Load policy from: %.*s\n", static_cast<int>(file.size()), file.data());
policy_file_t pf;
@ -110,13 +111,13 @@ std::unique_ptr<sepolicy> sepolicy::from_file(::rust::Utf8CStr file) noexcept {
if (policydb_init(db) || policydb_read(db, &pf, 0)) {
LOGE("Fail to load policy from %.*s\n", static_cast<int>(file.size()), file.data());
free(db);
return nullptr;
return {};
}
return std::make_unique<sepolicy>(sepolicy{.impl{new sepol_impl(db)}});
return {std::make_unique<sepol_impl>(db)};
}
std::unique_ptr<sepolicy> sepolicy::compile_split() noexcept {
SePolicy SePolicy::compile_split() noexcept {
char path[128], plat_ver[10];
cil_db_t *db = nullptr;
sepol_policydb_t *pdb = nullptr;
@ -207,21 +208,21 @@ std::unique_ptr<sepolicy> sepolicy::compile_split() noexcept {
load_cil(db, cil_file);
if (cil_compile(db))
return nullptr;
return {};
if (cil_build_policydb(db, &pdb))
return nullptr;
return std::make_unique<sepolicy>(sepolicy{.impl{new sepol_impl(&pdb->p)}});
return {};
return {std::make_unique<sepol_impl>(&pdb->p)};
}
std::unique_ptr<sepolicy> sepolicy::from_split() noexcept {
SePolicy SePolicy::from_split() noexcept {
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);
return SePolicy::from_file(odm_pre);
else if (access(vend_pre, R_OK) == 0 && check_precompiled(vend_pre))
return sepolicy::from_file(vend_pre);
return SePolicy::from_file(vend_pre);
else
return sepolicy::compile_split();
return SePolicy::compile_split();
}
sepol_impl::~sepol_impl() {
@ -229,7 +230,7 @@ sepol_impl::~sepol_impl() {
free(db);
}
bool sepolicy::to_file(::rust::Utf8CStr file) const noexcept {
bool SePolicy::to_file(::rust::Utf8CStr file) const noexcept {
// 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
heap_data data;

View File

@ -1,4 +1,4 @@
use crate::{ffi::Xperm, sepolicy};
use crate::{ffi::Xperm, SePolicy};
use base::{set_log_level_state, LogLevel};
macro_rules! rules {
@ -45,7 +45,7 @@ macro_rules! rules {
}};
}
impl sepolicy {
impl SePolicy {
pub fn magisk_rules(&mut self) {
// Temp suppress warnings
set_log_level_state(LogLevel::Warn, false);

View File

@ -653,14 +653,14 @@ bool sepol_impl::add_typeattribute(const char *type, const char *attr) {
return true;
}
void sepolicy::strip_dontaudit() noexcept {
void SePolicy::strip_dontaudit() noexcept {
avtab_for_each(&impl->db->te_avtab, [=, this](avtab_ptr_t node) {
if (node->key.specified == AVTAB_AUDITDENY || node->key.specified == AVTAB_XPERMS_DONTAUDIT)
avtab_remove_node(&impl->db->te_avtab, node);
});
}
void sepolicy::print_rules() const noexcept {
void SePolicy::print_rules() const noexcept {
hashtab_for_each(impl->db->p_types.table, [&](hashtab_ptr_t node) {
type_datum_t *type = auto_cast(node->datum);
if (type->flavor == TYPE_ATTRIB) {

View File

@ -3,7 +3,7 @@ use std::io::stderr;
use std::{iter::Peekable, vec::IntoIter};
use crate::ffi::Xperm;
use crate::sepolicy;
use crate::SePolicy;
use base::{error, warn, FmtAdaptor};
pub enum Token<'a> {
@ -227,10 +227,7 @@ fn match_string<'a>(tokens: &mut Tokens<'a>, pattern: &str) -> ParseResult<'a, (
// statement ::= TC ID(s) ID(t) ID(c) ID(d) { sepolicy.type_change(s, t, c, d); };
// statement ::= TM ID(s) ID(t) ID(c) ID(d) { sepolicy.type_member(s, t, c, d);};
// statement ::= GF ID(s) ID(t) ID(c) { sepolicy.genfscon(s, t, c); };
fn exec_statement<'a>(
sepolicy: &mut sepolicy,
tokens: &mut Tokens<'a>,
) -> ParseResult<'a, ()> {
fn exec_statement<'a>(sepolicy: &mut SePolicy, tokens: &mut Tokens<'a>) -> ParseResult<'a, ()> {
let action = match tokens.next() {
Some(token) => token,
_ => Err(ParseError::ShowHelp)?,
@ -444,8 +441,8 @@ fn tokenize_statement(statement: &str) -> Vec<Token> {
tokens
}
impl sepolicy {
pub fn parse_statement(self: &mut sepolicy, statement: &str) {
impl SePolicy {
pub fn parse_statement(self: &mut SePolicy, statement: &str) {
let statement = statement.trim();
if statement.is_empty() || statement.starts_with('#') {
return;
@ -600,7 +597,7 @@ allowxperm source target class ioctl *
)
}
impl sepolicy {
impl SePolicy {
pub fn print_statement_help() {
format_statement_help(&mut FmtAdaptor(&mut stderr())).ok();
eprintln!();