Several code cleanups in sepolicy

This commit is contained in:
topjohnwu 2024-03-20 23:09:22 -07:00
parent 4d2921e742
commit d654b9cb97
6 changed files with 145 additions and 141 deletions

View File

@ -1,12 +1,17 @@
#include <base.hpp> #include <base.hpp>
#include "flags.h" #include "flags.h"
#include "policy.hpp" #include "policy.hpp"
using Str = rust::Str;
#if MAGISK_DEBUG #if MAGISK_DEBUG
template<typename Arg> template<typename Arg>
auto as_str(Arg arg) { std::string as_str(const Arg &arg) {
if constexpr (std::is_same_v<Arg, const char *> || std::is_same_v<Arg, char *>) { if constexpr (std::is_same_v<Arg, const char *> || std::is_same_v<Arg, char *>) {
return arg == nullptr ? std::string("*") : std::string(arg); return arg == nullptr ? "*" : arg;
} else if constexpr (std::is_same_v<Arg, Xperm>) {
return std::string(rust::xperm_to_string(arg));
} else { } else {
return std::to_string(arg); return std::to_string(arg);
} }
@ -14,13 +19,13 @@ auto as_str(Arg arg) {
// Print out all rules going through public API for debugging // Print out all rules going through public API for debugging
template<typename ...Args> template<typename ...Args>
static void dprint(const char *action, Args ...args) { static void print_rule(const char *action, Args ...args) {
std::string s; std::string s;
s = (... + (" " + as_str(args))); s = (... + (" " + as_str(args)));
LOGD("%s%s", action, s.data()); LOGD("%s%s\n", action, s.data());
} }
#else #else
#define dprint(...) ((void) 0) #define print_rule(...) ((void) 0)
#endif #endif
bool sepolicy::exists(const char *type) { bool sepolicy::exists(const char *type) {
@ -45,107 +50,109 @@ void sepolicy::load_rules(const std::string &rules) {
template<typename F, typename ...T> template<typename F, typename ...T>
requires(std::invocable<F, T...>) requires(std::invocable<F, T...>)
inline void expand(F &&f, T &&...args) { static inline void expand(F &&f, T &&...args) {
f(std::forward<T>(args)...); f(std::forward<T>(args)...);
} }
template<typename ...T> template<typename ...T>
inline void expand(const rust::Vec<rust::Str> &vec, T &&...args) { static inline void expand(const StrVec &vec, T &&...args) {
for (auto i = vec.begin(); i != vec.end() || vec.empty(); ++i) { if (vec.empty()) {
expand(std::forward<T>(args)..., vec.empty() ? nullptr : std::string(*i).data()); expand(std::forward<T>(args)..., (char *) nullptr);
if (vec.empty()) break; } else {
char buf[64];
for (auto &s : vec) {
if (s.length() >= sizeof(buf)) continue;
memcpy(buf, s.data(), s.length());
buf[s.length()] = '\0';
expand(std::forward<T>(args)..., buf);
}
} }
} }
template<typename ...T> template<typename ...T>
inline void expand(const rust::Vec<Xperm> &vec, T &&...args) { static inline void expand(const Xperms &vec, T &&...args) {
for (auto &p : vec) { for (auto &p : vec) {
expand(std::forward<T>(args)..., p.low, p.high, p.reset); expand(std::forward<T>(args)..., p);
} }
} }
template<typename ...T> template<typename ...T>
inline void expand(const rust::Str &s, T &&...args) { static inline void expand(const Str &s, T &&...args) {
expand(std::forward<T>(args)..., std::string(s).data()); char buf[64];
if (s.length() >= sizeof(buf)) return;
memcpy(buf, s.data(), s.length());
buf[s.length()] = '\0';
expand(std::forward<T>(args)..., buf);
} }
void void sepolicy::allow(StrVec src, StrVec tgt, StrVec cls, StrVec perm) {
sepolicy::allow(rust::Vec<rust::Str> src, rust::Vec<rust::Str> tgt, rust::Vec<rust::Str> cls,
rust::Vec<rust::Str> perm) {
expand(src, tgt, cls, perm, [this](auto ...args) { expand(src, tgt, cls, perm, [this](auto ...args) {
dprint("allow", args...); print_rule("allow", args...);
impl->add_rule(args..., AVTAB_ALLOWED, false); impl->add_rule(args..., AVTAB_ALLOWED, false);
}); });
} }
void void sepolicy::deny(StrVec src, StrVec tgt, StrVec cls, StrVec perm) {
sepolicy::deny(rust::Vec<rust::Str> src, rust::Vec<rust::Str> tgt, rust::Vec<rust::Str> cls,
rust::Vec<rust::Str> perm) {
expand(src, tgt, cls, perm, [this](auto ...args) { expand(src, tgt, cls, perm, [this](auto ...args) {
dprint("deny", args...); print_rule("deny", args...);
impl->add_rule(args..., AVTAB_ALLOWED, true); impl->add_rule(args..., AVTAB_ALLOWED, true);
}); });
} }
void sepolicy::auditallow(rust::Vec<rust::Str> src, rust::Vec<rust::Str> tgt, void sepolicy::auditallow(StrVec src, StrVec tgt, StrVec cls, StrVec perm) {
rust::Vec<rust::Str> cls,
rust::Vec<rust::Str> perm) {
expand(src, tgt, cls, perm, [this](auto ...args) { expand(src, tgt, cls, perm, [this](auto ...args) {
dprint("auditallow", args...); print_rule("auditallow", args...);
impl->add_rule(args..., AVTAB_AUDITALLOW, false); impl->add_rule(args..., AVTAB_AUDITALLOW, false);
}); });
} }
void sepolicy::dontaudit(rust::Vec<rust::Str> src, rust::Vec<rust::Str> tgt, void sepolicy::dontaudit(StrVec src, StrVec tgt, StrVec cls, StrVec perm) {
rust::Vec<rust::Str> cls,
rust::Vec<rust::Str> perm) {
expand(src, tgt, cls, perm, [this](auto ...args) { expand(src, tgt, cls, perm, [this](auto ...args) {
dprint("dontaudit", args...); print_rule("dontaudit", args...);
impl->add_rule(args..., AVTAB_AUDITDENY, true); impl->add_rule(args..., AVTAB_AUDITDENY, true);
}); });
} }
void sepolicy::permissive(rust::Vec<rust::Str> types) { void sepolicy::permissive(StrVec types) {
expand(types, [this](auto ...args) { expand(types, [this](auto ...args) {
dprint("permissive", args...); print_rule("permissive", args...);
impl->set_type_state(args..., true); impl->set_type_state(args..., true);
}); });
} }
void sepolicy::enforce(rust::Vec<rust::Str> types) { void sepolicy::enforce(StrVec types) {
expand(types, [this](auto ...args) { expand(types, [this](auto ...args) {
dprint("enforce", args...); print_rule("enforce", args...);
impl->set_type_state(args..., false); impl->set_type_state(args..., false);
}); });
} }
void sepolicy::typeattribute(rust::Vec<rust::Str> types, rust::Vec<rust::Str> attrs) { void sepolicy::typeattribute(StrVec types, StrVec attrs) {
expand(types, attrs, [this](auto ...args) { expand(types, attrs, [this](auto ...args) {
dprint("typeattribute", args...); print_rule("typeattribute", args...);
impl->add_typeattribute(args...); impl->add_typeattribute(args...);
}); });
} }
void sepolicy::type(rust::Str type, rust::Vec<rust::Str> attrs) { void sepolicy::type(Str type, StrVec attrs) {
expand(type, attrs, [this](auto name, auto attr) { expand(type, attrs, [this](auto name, auto attr) {
dprint("type", name, attr); print_rule("type", name, attr);
impl->add_type(name, TYPE_TYPE) && impl->add_typeattribute(name, attr); impl->add_type(name, TYPE_TYPE) && impl->add_typeattribute(name, attr);
}); });
} }
void sepolicy::attribute(rust::Str name) { void sepolicy::attribute(Str name) {
expand(name, [this](auto ...args) { expand(name, [this](auto ...args) {
dprint("name", args...); print_rule("name", args...);
impl->add_type(args..., TYPE_ATTRIB); impl->add_type(args..., TYPE_ATTRIB);
}); });
} }
void sepolicy::type_transition(rust::Str src, rust::Str tgt, rust::Str cls, rust::Str def, void sepolicy::type_transition(Str src, Str tgt, Str cls, Str def, StrVec obj) {
rust::Vec<rust::Str> obj) {
auto obj_str = obj.empty() ? std::string() : std::string(obj[0]); auto obj_str = obj.empty() ? std::string() : std::string(obj[0]);
auto o = obj.empty() ? nullptr : obj_str.data(); auto o = obj.empty() ? nullptr : obj_str.data();
expand(src, tgt, cls, def, [this, &o](auto ...args) { expand(src, tgt, cls, def, [this, &o](auto ...args) {
dprint("type_transition", args..., o); print_rule("type_transition", args..., o);
if (o) { if (o) {
impl->add_filename_trans(args..., o); impl->add_filename_trans(args..., o);
} else { } else {
@ -154,54 +161,44 @@ void sepolicy::type_transition(rust::Str src, rust::Str tgt, rust::Str cls, rust
}); });
} }
void sepolicy::type_change(rust::Str src, rust::Str tgt, rust::Str cls, rust::Str def) { void sepolicy::type_change(Str src, Str tgt, Str cls, Str def) {
expand(src, tgt, cls, def, [this](auto ...args) { expand(src, tgt, cls, def, [this](auto ...args) {
dprint("type_change", args...); print_rule("type_change", args...);
impl->add_type_rule(args..., AVTAB_CHANGE); impl->add_type_rule(args..., AVTAB_CHANGE);
}); });
} }
void sepolicy::type_member(rust::Str src, rust::Str tgt, rust::Str cls, rust::Str def) { void sepolicy::type_member(Str src, Str tgt, Str cls, Str def) {
expand(src, tgt, cls, def, [this](auto ...args) { expand(src, tgt, cls, def, [this](auto ...args) {
dprint("type_member", args...); print_rule("type_member", args...);
impl->add_type_rule(args..., AVTAB_MEMBER); impl->add_type_rule(args..., AVTAB_MEMBER);
}); });
} }
void sepolicy::genfscon(rust::Str fs_name, rust::Str path, rust::Str ctx) { void sepolicy::genfscon(Str fs_name, Str path, Str ctx) {
expand(fs_name, path, ctx, [this](auto ...args) { expand(fs_name, path, ctx, [this](auto ...args) {
dprint("genfscon", args...); print_rule("genfscon", args...);
impl->add_genfscon(args...); impl->add_genfscon(args...);
}); });
} }
void void sepolicy::allowxperm(StrVec src, StrVec tgt, StrVec cls, Xperms xperm) {
sepolicy::allowxperm(rust::Vec<rust::Str> src, rust::Vec<rust::Str> tgt, rust::Vec<rust::Str> cls,
rust::Vec<Xperm> xperm) {
expand(src, tgt, cls, xperm, [this](auto ...args) { expand(src, tgt, cls, xperm, [this](auto ...args) {
dprint("allowxperm", args...); print_rule("allowxperm", args...);
impl->add_xperm_rule(args..., AVTAB_XPERMS_ALLOWED); impl->add_xperm_rule(args..., AVTAB_XPERMS_ALLOWED);
}); });
} }
void sepolicy::auditallowxperm(rust::Vec<rust::Str> src, rust::Vec<rust::Str> tgt, void sepolicy::auditallowxperm(StrVec src, StrVec tgt, StrVec cls, Xperms xperm) {
rust::Vec<rust::Str> cls,
rust::Vec<Xperm> xperm) {
expand(src, tgt, cls, xperm, [this](auto ...args) { expand(src, tgt, cls, xperm, [this](auto ...args) {
dprint("auditallowxperm", args...); print_rule("auditallowxperm", args...);
impl->add_xperm_rule(args..., AVTAB_XPERMS_AUDITALLOW); impl->add_xperm_rule(args..., AVTAB_XPERMS_AUDITALLOW);
}); });
} }
void sepolicy::dontauditxperm(rust::Vec<rust::Str> src, rust::Vec<rust::Str> tgt, void sepolicy::dontauditxperm(StrVec src, StrVec tgt, StrVec cls, Xperms xperm) {
rust::Vec<rust::Str> cls,
rust::Vec<Xperm> xperm) {
expand(src, tgt, cls, xperm, [this](auto ...args) { expand(src, tgt, cls, xperm, [this](auto ...args) {
dprint("dontauditxperm", args...); print_rule("dontauditxperm", args...);
impl->add_xperm_rule(args..., AVTAB_XPERMS_DONTAUDIT); impl->add_xperm_rule(args..., AVTAB_XPERMS_DONTAUDIT);
}); });
} }
void sepolicy::strip_dontaudit() {
impl->strip_dontaudit();
}

View File

@ -20,22 +20,21 @@
#define SELINUX_LOAD SELINUX_MNT "/load" #define SELINUX_LOAD SELINUX_MNT "/load"
#define SELINUX_VERSION SELINUX_MNT "/policyvers" #define SELINUX_VERSION SELINUX_MNT "/policyvers"
using token_list = std::vector<const char *>;
using argument = std::pair<token_list, bool>;
using argument_list = std::vector<argument>;
struct Xperm; struct Xperm;
#define ALL nullptr using StrVec = rust::Vec<rust::Str>;
using Xperms = rust::Vec<Xperm>;
struct sepolicy { struct sepolicy {
using c_str = const char *; using c_str = const char *;
using Str = rust::Str;
// Public static factory functions // Public static factory functions
static sepolicy *from_data(char *data, size_t len); static sepolicy *from_data(char *data, size_t len);
static sepolicy *from_file(c_str file); static sepolicy *from_file(c_str file);
static sepolicy *from_split(); static sepolicy *from_split();
static sepolicy *compile_split(); static sepolicy *compile_split();
// External APIs // External APIs
bool to_file(c_str file); bool to_file(c_str file);
void load_rules(const std::string &rules); void load_rules(const std::string &rules);
@ -44,31 +43,31 @@ struct sepolicy {
void parse_statement(c_str statement); void parse_statement(c_str statement);
// Operation on types // Operation on types
void type(rust::Str type, rust::Vec<rust::Str> attrs); void type(Str type, StrVec attrs);
void attribute(rust::Str names); void attribute(Str names);
void permissive(rust::Vec<rust::Str> types); void permissive(StrVec types);
void enforce(rust::Vec<rust::Str> types); void enforce(StrVec types);
void typeattribute(rust::Vec<rust::Str> types, rust::Vec<rust::Str> attrs); void typeattribute(StrVec types, StrVec attrs);
bool exists(c_str type); bool exists(c_str type);
// Access vector rules // Access vector rules
void allow(rust::Vec<rust::Str> src, rust::Vec<rust::Str> tgt, rust::Vec<rust::Str> cls, rust::Vec<rust::Str> perm); void allow(StrVec src, StrVec tgt, StrVec cls, StrVec perm);
void deny(rust::Vec<rust::Str> src, rust::Vec<rust::Str> tgt, rust::Vec<rust::Str> cls, rust::Vec<rust::Str> perm); void deny(StrVec src, StrVec tgt, StrVec cls, StrVec perm);
void auditallow(rust::Vec<rust::Str> src, rust::Vec<rust::Str> tgt, rust::Vec<rust::Str> cls, rust::Vec<rust::Str> perm); void auditallow(StrVec src, StrVec tgt, StrVec cls, StrVec perm);
void dontaudit(rust::Vec<rust::Str> src, rust::Vec<rust::Str> tgt, rust::Vec<rust::Str> cls, rust::Vec<rust::Str> perm); void dontaudit(StrVec src, StrVec tgt, StrVec cls, StrVec perm);
// Extended permissions access vector rules // Extended permissions access vector rules
void allowxperm(rust::Vec<rust::Str> src, rust::Vec<rust::Str> tgt, rust::Vec<rust::Str> cls, rust::Vec<Xperm> xperm); void allowxperm(StrVec src, StrVec tgt, StrVec cls, Xperms xperm);
void auditallowxperm(rust::Vec<rust::Str> src, rust::Vec<rust::Str> tgt, rust::Vec<rust::Str> cls, rust::Vec<Xperm> xperm); void auditallowxperm(StrVec src, StrVec tgt, StrVec cls, Xperms xperm);
void dontauditxperm(rust::Vec<rust::Str> src, rust::Vec<rust::Str> tgt, rust::Vec<rust::Str> cls, rust::Vec<Xperm> xperm); void dontauditxperm(StrVec src, StrVec tgt, StrVec cls, Xperms xperm);
// Type rules // Type rules
void type_transition(rust::Str src, rust::Str tgt, rust::Str cls, rust::Str def, rust::Vec<rust::Str> obj); void type_transition(Str src, Str tgt, Str cls, Str def, StrVec obj);
void type_change(rust::Str src, rust::Str tgt, rust::Str cls, rust::Str def); void type_change(Str src, Str tgt, Str cls, Str def);
void type_member(rust::Str src, rust::Str tgt, rust::Str cls, rust::Str def); void type_member(Str src, Str tgt, Str cls, Str def);
// File system labeling // File system labeling
void genfscon(rust::Str fs_name, rust::Str path, rust::Str ctx); void genfscon(Str fs_name, Str path, Str ctx);
// Magisk // Magisk
void magisk_rules(); void magisk_rules();

View File

@ -1,6 +1,7 @@
#![feature(format_args_nl)] #![feature(format_args_nl)]
use io::Cursor; use io::Cursor;
use std::fmt::Write;
use std::io; use std::io;
use std::io::{BufRead, BufReader}; use std::io::{BufRead, BufReader};
use std::pin::Pin; use std::pin::Pin;
@ -11,9 +12,8 @@ use base::{error, BufReadExt, FsPath, LoggedResult, Utf8CStr};
use crate::ffi::sepolicy; use crate::ffi::sepolicy;
mod statement;
mod rules; mod rules;
mod statement;
#[cxx::bridge] #[cxx::bridge]
mod ffi { mod ffi {
@ -94,6 +94,7 @@ mod ffi {
fn load_rule_file(sepol: Pin<&mut sepolicy>, filename: Utf8CStrRef); fn load_rule_file(sepol: Pin<&mut sepolicy>, filename: Utf8CStrRef);
fn parse_statement(sepol: Pin<&mut sepolicy>, statement: Utf8CStrRef); fn parse_statement(sepol: Pin<&mut sepolicy>, statement: Utf8CStrRef);
fn magisk_rules(sepol: Pin<&mut sepolicy>); fn magisk_rules(sepol: Pin<&mut sepolicy>);
fn xperm_to_string(perm: &Xperm) -> String;
} }
} }
@ -104,10 +105,6 @@ trait SepolicyExt {
fn parse_statement(self: Pin<&mut Self>, statement: &str); fn parse_statement(self: Pin<&mut Self>, statement: &str);
} }
trait SepolicyMagisk {
fn magisk_rules(self: Pin<&mut Self>);
}
impl SepolicyExt for sepolicy { impl SepolicyExt for sepolicy {
fn load_rules(self: Pin<&mut sepolicy>, rules: &[u8]) { fn load_rules(self: Pin<&mut sepolicy>, rules: &[u8]) {
let mut cursor = Cursor::new(rules); let mut cursor = Cursor::new(rules);
@ -136,24 +133,38 @@ impl SepolicyExt for sepolicy {
} }
fn parse_statement(self: Pin<&mut Self>, statement: &str) { fn parse_statement(self: Pin<&mut Self>, statement: &str) {
if let Err(_) = statement::parse_statement(self, statement) { if statement::parse_statement(self, statement).is_err() {
error!("sepolicy rule syntax error: {statement}"); error!("sepolicy rule syntax error: {statement}");
} }
} }
} }
pub fn load_rule_file(sepol: Pin<&mut sepolicy>, filename: &Utf8CStr) { fn load_rule_file(sepol: Pin<&mut sepolicy>, filename: &Utf8CStr) {
sepol.load_rule_file(filename); sepol.load_rule_file(filename);
} }
pub fn load_rules(sepol: Pin<&mut sepolicy>, rules: &[u8]) { fn load_rules(sepol: Pin<&mut sepolicy>, rules: &[u8]) {
sepol.load_rules(rules); sepol.load_rules(rules);
} }
pub fn parse_statement(sepol: Pin<&mut sepolicy>, statement: &Utf8CStr) { fn parse_statement(sepol: Pin<&mut sepolicy>, statement: &Utf8CStr) {
sepol.parse_statement(statement.as_str()); sepol.parse_statement(statement.as_str());
} }
pub fn magisk_rules(sepol: Pin<&mut sepolicy>) { trait SepolicyMagisk {
fn magisk_rules(self: Pin<&mut Self>);
}
fn magisk_rules(sepol: Pin<&mut sepolicy>) {
sepol.magisk_rules(); sepol.magisk_rules();
} }
fn xperm_to_string(perm: &ffi::Xperm) -> String {
let mut s = String::new();
if perm.reset {
s.push('~');
}
s.write_fmt(format_args!("{{ {:#06x}-{:#06x} }}", perm.low, perm.high))
.ok();
s
}

View File

@ -20,8 +20,8 @@ struct sepol_impl : public sepolicy {
bool add_rule(const char *s, const char *t, const char *c, const char *p, int effect, bool invert); 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); void add_rule(type_datum_t *src, type_datum_t *tgt, class_datum_t *cls, perm_datum_t *perm, int effect, bool invert);
void add_xperm_rule(type_datum_t *src, type_datum_t *tgt, class_datum_t *cls, uint16_t low, uint16_t high, bool reset, int effect); void add_xperm_rule(type_datum_t *src, type_datum_t *tgt, class_datum_t *cls, const Xperm &p, int effect);
bool add_xperm_rule(const char *s, const char *t, const char *c, uint16_t low, uint16_t high, bool reset, int effect); bool add_xperm_rule(const char *s, const char *t, const char *c, const Xperm &p, int effect);
bool add_type_rule(const char *s, const char *t, const char *c, const char *d, int effect); bool add_type_rule(const char *s, const char *t, const char *c, const char *d, int effect);
bool add_filename_trans(const char *s, const char *t, const char *c, const char *d, const char *o); bool add_filename_trans(const char *s, const char *t, const char *c, const char *d, const char *o);
bool add_genfscon(const char *fs_name, const char *path, const char *context); bool add_genfscon(const char *fs_name, const char *path, const char *context);
@ -29,7 +29,6 @@ struct sepol_impl : public sepolicy {
bool set_type_state(const char *type_name, bool permissive); bool set_type_state(const char *type_name, bool permissive);
void add_typeattribute(type_datum_t *type, type_datum_t *attr); void add_typeattribute(type_datum_t *type, type_datum_t *attr);
bool add_typeattribute(const char *type, const char *attr); bool add_typeattribute(const char *type, const char *attr);
void strip_dontaudit();
sepol_impl(policydb *db) : db(db) {} sepol_impl(policydb *db) : db(db) {}
~sepol_impl(); ~sepol_impl();
@ -42,8 +41,4 @@ private:
#define impl reinterpret_cast<sepol_impl *>(this) #define impl reinterpret_cast<sepol_impl *>(this)
const char *as_str(const argument &arg);
const char *as_str(const char *arg);
void statement_help(); void statement_help();
void test_parse_statements();

View File

@ -270,18 +270,18 @@ bool sepol_impl::add_rule(const char *s, const char *t, const char *c, const cha
#define ioctl_driver(x) (x>>8 & 0xFF) #define ioctl_driver(x) (x>>8 & 0xFF)
#define ioctl_func(x) (x & 0xFF) #define ioctl_func(x) (x & 0xFF)
void sepol_impl::add_xperm_rule(type_datum_t *src, type_datum_t *tgt, class_datum_t *cls, uint16_t low, uint16_t high, bool reset, int effect) { void sepol_impl::add_xperm_rule(type_datum_t *src, type_datum_t *tgt, class_datum_t *cls, const Xperm &p, int effect) {
if (src == nullptr) { if (src == nullptr) {
for_each_attr(db->p_types.table, [&](type_datum_t *type) { for_each_attr(db->p_types.table, [&](type_datum_t *type) {
add_xperm_rule(type, tgt, cls, low, high, reset, effect); add_xperm_rule(type, tgt, cls, p, effect);
}); });
} else if (tgt == nullptr) { } else if (tgt == nullptr) {
for_each_attr(db->p_types.table, [&](type_datum_t *type) { for_each_attr(db->p_types.table, [&](type_datum_t *type) {
add_xperm_rule(src, type, cls, low, high, reset, effect); add_xperm_rule(src, type, cls, p, effect);
}); });
} else if (cls == nullptr) { } else if (cls == nullptr) {
hashtab_for_each(db->p_classes.table, [&](hashtab_ptr_t node) { hashtab_for_each(db->p_classes.table, [&](hashtab_ptr_t node) {
add_xperm_rule(src, tgt, auto_cast(node->datum), low, high, reset, effect); add_xperm_rule(src, tgt, auto_cast(node->datum), p, effect);
}); });
} else { } else {
avtab_key_t key; avtab_key_t key;
@ -304,7 +304,7 @@ void sepol_impl::add_xperm_rule(type_datum_t *src, type_datum_t *tgt, class_datu
node = avtab_search_node_next(node, key.specified); node = avtab_search_node_next(node, key.specified);
} }
if (reset) { if (p.reset) {
for (int i = 0; i <= 0xFF; ++i) { for (int i = 0; i <= 0xFF; ++i) {
if (node_list[i]) { if (node_list[i]) {
avtab_remove_node(&db->te_avtab, node_list[i]); avtab_remove_node(&db->te_avtab, node_list[i]);
@ -332,22 +332,22 @@ void sepol_impl::add_xperm_rule(type_datum_t *src, type_datum_t *tgt, class_datu
return node; return node;
}; };
if (!reset) { if (!p.reset) {
if (ioctl_driver(low) != ioctl_driver(high)) { if (ioctl_driver(p.low) != ioctl_driver(p.high)) {
if (driver_node == nullptr) { if (driver_node == nullptr) {
driver_node = new_driver_node(); driver_node = new_driver_node();
} }
for (int i = ioctl_driver(low); i <= ioctl_driver(high); ++i) { for (int i = ioctl_driver(p.low); i <= ioctl_driver(p.high); ++i) {
xperm_set(i, driver_node->datum.xperms->perms); xperm_set(i, driver_node->datum.xperms->perms);
} }
} else { } else {
uint8_t driver = ioctl_driver(low); uint8_t driver = ioctl_driver(p.low);
auto node = node_list[driver]; auto node = node_list[driver];
if (node == nullptr) { if (node == nullptr) {
node = new_func_node(driver); node = new_func_node(driver);
node_list[driver] = node; node_list[driver] = node;
} }
for (int i = ioctl_func(low); i <= ioctl_func(high); ++i) { for (int i = ioctl_func(p.low); i <= ioctl_func(p.high); ++i) {
xperm_set(i, node->datum.xperms->perms); xperm_set(i, node->datum.xperms->perms);
} }
} }
@ -358,12 +358,12 @@ void sepol_impl::add_xperm_rule(type_datum_t *src, type_datum_t *tgt, class_datu
// Fill the driver perms // Fill the driver perms
memset(driver_node->datum.xperms->perms, ~0, sizeof(avtab_extended_perms_t::perms)); memset(driver_node->datum.xperms->perms, ~0, sizeof(avtab_extended_perms_t::perms));
if (ioctl_driver(low) != ioctl_driver(high)) { if (ioctl_driver(p.low) != ioctl_driver(p.high)) {
for (int i = ioctl_driver(low); i <= ioctl_driver(high); ++i) { for (int i = ioctl_driver(p.low); i <= ioctl_driver(p.high); ++i) {
xperm_clear(i, driver_node->datum.xperms->perms); xperm_clear(i, driver_node->datum.xperms->perms);
} }
} else { } else {
uint8_t driver = ioctl_driver(low); uint8_t driver = ioctl_driver(p.low);
auto node = node_list[driver]; auto node = node_list[driver];
if (node == nullptr) { if (node == nullptr) {
node = new_func_node(driver); node = new_func_node(driver);
@ -372,7 +372,7 @@ void sepol_impl::add_xperm_rule(type_datum_t *src, type_datum_t *tgt, class_datu
node_list[driver] = node; node_list[driver] = node;
} }
xperm_clear(driver, driver_node->datum.xperms->perms); xperm_clear(driver, driver_node->datum.xperms->perms);
for (int i = ioctl_func(low); i <= ioctl_func(high); ++i) { for (int i = ioctl_func(p.low); i <= ioctl_func(p.high); ++i) {
xperm_clear(i, node->datum.xperms->perms); xperm_clear(i, node->datum.xperms->perms);
} }
} }
@ -380,7 +380,7 @@ void sepol_impl::add_xperm_rule(type_datum_t *src, type_datum_t *tgt, class_datu
} }
} }
bool sepol_impl::add_xperm_rule(const char *s, const char *t, const char *c, uint16_t low, uint16_t high, bool reset, int effect) { bool sepol_impl::add_xperm_rule(const char *s, const char *t, const char *c, const Xperm &p, int effect) {
type_datum_t *src = nullptr, *tgt = nullptr; type_datum_t *src = nullptr, *tgt = nullptr;
class_datum_t *cls = nullptr; class_datum_t *cls = nullptr;
@ -408,7 +408,7 @@ bool sepol_impl::add_xperm_rule(const char *s, const char *t, const char *c, uin
} }
} }
add_xperm_rule(src, tgt, cls, low, high, reset, effect); add_xperm_rule(src, tgt, cls, p, effect);
return true; return true;
} }
@ -649,10 +649,10 @@ bool sepol_impl::add_typeattribute(const char *type, const char *attr) {
return true; return true;
} }
void sepol_impl::strip_dontaudit() { void sepolicy::strip_dontaudit() {
avtab_for_each(&db->te_avtab, [=, this](avtab_ptr_t node) { avtab_for_each(&impl->db->te_avtab, [=, this](avtab_ptr_t node) {
if (node->key.specified == AVTAB_AUDITDENY || node->key.specified == AVTAB_XPERMS_DONTAUDIT) if (node->key.specified == AVTAB_AUDITDENY || node->key.specified == AVTAB_XPERMS_DONTAUDIT)
avtab_remove_node(&db->te_avtab, node); avtab_remove_node(&impl->db->te_avtab, node);
}); });
} }

View File

@ -1,7 +1,9 @@
use std::{iter::Peekable, pin::Pin, vec::IntoIter};
use base::{LoggedError, LoggedResult};
use crate::ffi::Xperm; use crate::ffi::Xperm;
use crate::sepolicy; use crate::sepolicy;
use base::{LoggedError, LoggedResult};
use std::{iter::Peekable, pin::Pin, vec::IntoIter};
pub enum Token<'a> { pub enum Token<'a> {
AL, AL,
@ -52,7 +54,7 @@ fn parse_id<'a>(tokens: &mut Tokens<'a>) -> LoggedResult<&'a str> {
// term ::= LB names(n) RB { n }; // term ::= LB names(n) RB { n };
fn parse_term<'a>(tokens: &mut Tokens<'a>) -> LoggedResult<Vec<&'a str>> { fn parse_term<'a>(tokens: &mut Tokens<'a>) -> LoggedResult<Vec<&'a str>> {
match tokens.next() { match tokens.next() {
Some(Token::ID(name)) => return Ok(vec![name]), Some(Token::ID(name)) => Ok(vec![name]),
Some(Token::LB) => { Some(Token::LB) => {
let mut names = Vec::new(); let mut names = Vec::new();
loop { loop {
@ -87,7 +89,7 @@ fn parse_terms<'a>(tokens: &mut Tokens<'a>) -> LoggedResult<Vec<&'a str>> {
// xperm ::= HX(low) { Xperm{low, high: 0, reset: false} }; // xperm ::= HX(low) { Xperm{low, high: 0, reset: false} };
// xperm ::= HX(low) HP HX(high) { Xperm{low, high, reset: false} }; // xperm ::= HX(low) HP HX(high) { Xperm{low, high, reset: false} };
fn parse_xperm<'a>(tokens: &mut Tokens<'a>) -> LoggedResult<Xperm> { fn parse_xperm(tokens: &mut Tokens) -> LoggedResult<Xperm> {
let low = match tokens.next() { let low = match tokens.next() {
Some(Token::HX(low)) => low, Some(Token::HX(low)) => low,
_ => throw!(), _ => throw!(),
@ -116,7 +118,7 @@ fn parse_xperm<'a>(tokens: &mut Tokens<'a>) -> LoggedResult<Xperm> {
// //
// xperm_list ::= xperm(p) { vec![p] } // xperm_list ::= xperm(p) { vec![p] }
// xperm_list ::= xperm_list(mut l) xperm(p) { l.push(p); l } // xperm_list ::= xperm_list(mut l) xperm(p) { l.push(p); l }
fn parse_xperms<'a>(tokens: &mut Tokens<'a>) -> LoggedResult<Vec<Xperm>> { fn parse_xperms(tokens: &mut Tokens) -> LoggedResult<Vec<Xperm>> {
let mut xperms = Vec::new(); let mut xperms = Vec::new();
let reset = match tokens.peek() { let reset = match tokens.peek() {
Some(Token::TL) => { Some(Token::TL) => {
@ -186,7 +188,7 @@ fn parse_xperms<'a>(tokens: &mut Tokens<'a>) -> LoggedResult<Vec<Xperm>> {
// statement ::= TC ID(s) ID(t) ID(c) ID(d) { extra.as_mut().type_change(s, t, c, d); }; // statement ::= TC ID(s) ID(t) ID(c) ID(d) { extra.as_mut().type_change(s, t, c, d); };
// statement ::= TM ID(s) ID(t) ID(c) ID(d) { extra.as_mut().type_member(s, t, c, d);}; // statement ::= TM ID(s) ID(t) ID(c) ID(d) { extra.as_mut().type_member(s, t, c, d);};
// statement ::= GF ID(s) ID(t) ID(c) { extra.as_mut().genfscon(s, t, c); }; // statement ::= GF ID(s) ID(t) ID(c) { extra.as_mut().genfscon(s, t, c); };
fn exec_statement<'a>(sepolicy: Pin<&mut sepolicy>, tokens: &mut Tokens<'a>) -> LoggedResult<()> { fn exec_statement(sepolicy: Pin<&mut sepolicy>, tokens: &mut Tokens) -> LoggedResult<()> {
let action = match tokens.next() { let action = match tokens.next() {
Some(token) => token, Some(token) => token,
_ => throw!(), _ => throw!(),
@ -236,7 +238,7 @@ fn exec_statement<'a>(sepolicy: Pin<&mut sepolicy>, tokens: &mut Tokens<'a>) ->
} }
Token::TY => { Token::TY => {
let t = parse_id(tokens)?; let t = parse_id(tokens)?;
let a = if matches!(tokens.peek(), None) { let a = if tokens.peek().is_none() {
vec![] vec![]
} else { } else {
parse_term(tokens)? parse_term(tokens)?
@ -254,7 +256,7 @@ fn exec_statement<'a>(sepolicy: Pin<&mut sepolicy>, tokens: &mut Tokens<'a>) ->
let d = parse_id(tokens)?; let d = parse_id(tokens)?;
match action { match action {
Token::TT => { Token::TT => {
let o = if matches!(tokens.peek(), None) { let o = if tokens.peek().is_none() {
vec![] vec![]
} else { } else {
vec![parse_id(tokens)?] vec![parse_id(tokens)?]
@ -274,16 +276,16 @@ fn exec_statement<'a>(sepolicy: Pin<&mut sepolicy>, tokens: &mut Tokens<'a>) ->
} }
_ => throw!(), _ => throw!(),
} }
if matches!(tokens.peek(), None) { if tokens.peek().is_none() {
Ok(()) Ok(())
} else { } else {
throw!() throw!()
} }
} }
fn tokenize_statement<'a>(statement: &'a str) -> Vec<Token<'a>> { fn tokenize_statement(statement: &str) -> Vec<Token> {
let mut tokens = Vec::new(); let mut tokens = Vec::new();
for s in statement.trim().split_whitespace() { for s in statement.split_whitespace() {
let mut res = Some(s); let mut res = Some(s);
while let Some(s) = res { while let Some(s) = res {
match s { match s {
@ -306,27 +308,27 @@ fn tokenize_statement<'a>(statement: &'a str) -> Vec<Token<'a>> {
"ioctl" => tokens.push(Token::IO), "ioctl" => tokens.push(Token::IO),
"" => {} "" => {}
_ => { _ => {
if let Some(s) = s.strip_prefix("{") { if let Some(s) = s.strip_prefix('{') {
tokens.push(Token::LB); tokens.push(Token::LB);
res = Some(s); res = Some(s);
continue; continue;
} else if let Some(s) = s.strip_prefix("}") { } else if let Some(s) = s.strip_prefix('}') {
tokens.push(Token::RB); tokens.push(Token::RB);
res = Some(s); res = Some(s);
continue; continue;
} else if let Some(s) = s.strip_prefix(",") { } else if let Some(s) = s.strip_prefix(',') {
tokens.push(Token::CM); tokens.push(Token::CM);
res = Some(s); res = Some(s);
continue; continue;
} else if let Some(s) = s.strip_prefix("*") { } else if let Some(s) = s.strip_prefix('*') {
tokens.push(Token::ST); tokens.push(Token::ST);
res = Some(s); res = Some(s);
continue; continue;
} else if let Some(s) = s.strip_prefix("~") { } else if let Some(s) = s.strip_prefix('~') {
res = Some(s); res = Some(s);
tokens.push(Token::TL); tokens.push(Token::TL);
continue; continue;
} else if let Some(s) = s.strip_prefix("-") { } else if let Some(s) = s.strip_prefix('-') {
res = Some(s); res = Some(s);
tokens.push(Token::HP); tokens.push(Token::HP);
continue; continue;
@ -343,7 +345,7 @@ fn tokenize_statement<'a>(statement: &'a str) -> Vec<Token<'a>> {
tokens tokens
} }
pub fn parse_statement<'a>(sepolicy: Pin<&mut sepolicy>, statement: &'a str) -> LoggedResult<()> { pub fn parse_statement(sepolicy: Pin<&mut sepolicy>, statement: &str) -> LoggedResult<()> {
let mut tokens = tokenize_statement(statement).into_iter().peekable(); let mut tokens = tokenize_statement(statement).into_iter().peekable();
exec_statement(sepolicy, &mut tokens) exec_statement(sepolicy, &mut tokens)
} }