mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-12-22 16:07:39 +00:00
Several code cleanups in sepolicy
This commit is contained in:
parent
4d2921e742
commit
d654b9cb97
@ -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();
|
|
||||||
}
|
|
||||||
|
@ -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();
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
@ -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();
|
|
||||||
|
@ -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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user