You've already forked Magisk
mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-09-06 06:36:58 +00:00
Parse rule files with Rust
This commit is contained in:
@@ -7,5 +7,10 @@ edition = "2021"
|
||||
crate-type = ["staticlib", "rlib"]
|
||||
path = "lib.rs"
|
||||
|
||||
[build-dependencies]
|
||||
cxx-gen = { workspace = true }
|
||||
|
||||
[dependencies]
|
||||
base = { path = "../base" }
|
||||
cxx = { workspace = true }
|
||||
anyhow = { workspace = true }
|
||||
|
||||
@@ -103,3 +103,13 @@ bool sepolicy::genfscon(const char *fs_name, const char *path, const char *ctx)
|
||||
bool sepolicy::exists(const char *type) {
|
||||
return hashtab_search(impl->db->p_types.table, type) != nullptr;
|
||||
}
|
||||
|
||||
void sepolicy::load_rule_file(const char *file) {
|
||||
rust::load_rule_file(*this, rust::Slice(
|
||||
reinterpret_cast<const uint8_t *>(file), strlen(file)));
|
||||
}
|
||||
|
||||
void sepolicy::load_rules(const std::string &rules) {
|
||||
rust::load_rules(*this, rust::Slice(
|
||||
reinterpret_cast<const uint8_t *>(rules.data()), rules.length()));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
use crate::gen::gen_cxx_binding;
|
||||
|
||||
#[path = "../include/gen.rs"]
|
||||
mod gen;
|
||||
|
||||
fn main() {
|
||||
gen_cxx_binding("policy-rs");
|
||||
}
|
||||
@@ -1,9 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <selinux.hpp>
|
||||
#include <string>
|
||||
|
||||
#include <selinux.hpp>
|
||||
|
||||
#define ALL nullptr
|
||||
|
||||
struct sepolicy {
|
||||
@@ -17,7 +18,8 @@ struct sepolicy {
|
||||
|
||||
// External APIs
|
||||
bool to_file(c_str file);
|
||||
void parse_statement(c_str stmt);
|
||||
void parse_statement(c_str stmt, int len);
|
||||
void parse_statement(c_str stmt) { parse_statement(stmt, strlen(stmt)); }
|
||||
void load_rules(const std::string &rules);
|
||||
void load_rule_file(c_str file);
|
||||
|
||||
|
||||
@@ -1 +1,53 @@
|
||||
use io::Cursor;
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader};
|
||||
use std::pin::Pin;
|
||||
use std::{io, str};
|
||||
|
||||
pub use base;
|
||||
use base::*;
|
||||
|
||||
use crate::ffi::sepolicy;
|
||||
|
||||
#[cxx::bridge]
|
||||
mod ffi {
|
||||
unsafe extern "C++" {
|
||||
include!("include/sepolicy.hpp");
|
||||
|
||||
type sepolicy;
|
||||
unsafe fn parse_statement(self: Pin<&mut sepolicy>, stmt: *const c_char, len: i32);
|
||||
}
|
||||
|
||||
#[namespace = "rust"]
|
||||
extern "Rust" {
|
||||
fn load_rules(sepol: Pin<&mut sepolicy>, rules: &[u8]);
|
||||
fn load_rule_file(sepol: Pin<&mut sepolicy>, filename: &[u8]);
|
||||
}
|
||||
}
|
||||
|
||||
fn load_rules_from_reader<T: BufRead>(mut sepol: Pin<&mut sepolicy>, reader: &mut T) {
|
||||
reader.foreach_lines(|line| {
|
||||
let bytes = line.trim().as_bytes();
|
||||
unsafe {
|
||||
sepol
|
||||
.as_mut()
|
||||
.parse_statement(bytes.as_ptr().cast(), bytes.len() as i32);
|
||||
}
|
||||
true
|
||||
});
|
||||
}
|
||||
|
||||
pub fn load_rule_file(sepol: Pin<&mut sepolicy>, filename: &[u8]) {
|
||||
fn inner(sepol: Pin<&mut sepolicy>, filename: &[u8]) -> anyhow::Result<()> {
|
||||
let filename = str::from_utf8(filename)?;
|
||||
let mut reader = BufReader::new(File::open(filename)?);
|
||||
load_rules_from_reader(sepol, &mut reader);
|
||||
Ok(())
|
||||
}
|
||||
inner(sepol, filename).ok_or_log();
|
||||
}
|
||||
|
||||
pub fn load_rules(sepol: Pin<&mut sepolicy>, rules: &[u8]) {
|
||||
let mut cursor = Cursor::new(rules);
|
||||
load_rules_from_reader(sepol, &mut cursor);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#include <sepol/policydb/policydb.h>
|
||||
#include <sepolicy.hpp>
|
||||
|
||||
#include "policy-rs.hpp"
|
||||
|
||||
struct sepol_impl : public sepolicy {
|
||||
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);
|
||||
|
||||
@@ -266,22 +266,22 @@ static bool parse_pattern_9(const Func &fn, const char *action, char *stmt) {
|
||||
}
|
||||
|
||||
#define add_action_func(name, type, fn) \
|
||||
else if (strcmp(name, action) == 0) { \
|
||||
auto __fn = [=](auto && ...args){ return (fn)(args...); };\
|
||||
if (!parse_pattern_##type(__fn, name, remain)) \
|
||||
LOGW("Syntax error in '%s'\n\n%s\n", stmt, type_msg_##type); \
|
||||
else if (strcmp(name, action) == 0) { \
|
||||
auto __fn = [&](auto && ...args){ return (fn)(args...); }; \
|
||||
if (!parse_pattern_##type(__fn, name, remain)) \
|
||||
LOGW("Syntax error in '%.*s'\n\n%s\n", len, stmt, type_msg_##type); \
|
||||
}
|
||||
|
||||
#define add_action(act, type) add_action_func(#act, type, act)
|
||||
|
||||
void sepolicy::parse_statement(const char *stmt) {
|
||||
void sepolicy::parse_statement(const char *stmt, int len) {
|
||||
// strtok modify strings, create a copy
|
||||
string cpy(stmt);
|
||||
string cpy(stmt, len);
|
||||
|
||||
char *remain;
|
||||
char *action = strtok_r(cpy.data(), " ", &remain);
|
||||
if (remain == nullptr) {
|
||||
LOGW("Syntax error in '%s'\n\n", stmt);
|
||||
LOGW("Syntax error in '%.*s'\n\n", len, stmt);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -310,43 +310,3 @@ void sepolicy::parse_statement(const char *stmt) {
|
||||
|
||||
else { LOGW("Unknown action: '%s'\n\n", action); }
|
||||
}
|
||||
|
||||
void sepolicy::load_rule_file(const char *file) {
|
||||
file_readline(true, file, [&](string_view line) -> bool {
|
||||
if (line.empty() || line[0] == '#')
|
||||
return true;
|
||||
parse_statement(line.data());
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
void sepolicy::load_rules(const string &rules) {
|
||||
struct cookie {
|
||||
const string &s;
|
||||
size_t pos;
|
||||
};
|
||||
cookie c{rules, 0};
|
||||
FILE *fp = funopen(&c, /* read */ [](void *v, char *buf, int sz) -> int {
|
||||
auto c = reinterpret_cast<cookie*>(v);
|
||||
if (c->pos == c->s.length())
|
||||
return 0;
|
||||
size_t end = std::min(c->pos + sz, c->s.length());
|
||||
int len = end - c->pos;
|
||||
memcpy(buf, c->s.data() + c->pos, len);
|
||||
c->pos = end;
|
||||
return len;
|
||||
}, /* write */ [](auto, auto, auto) -> int {
|
||||
return 0;
|
||||
}, /* seek */ [](auto, auto, auto) -> fpos_t {
|
||||
return 0;
|
||||
}, /* close */ [](auto) -> int {
|
||||
return 0;
|
||||
});
|
||||
|
||||
file_readline(true, fp, [&](string_view line) -> bool {
|
||||
if (line.empty() || line[0] == '#')
|
||||
return true;
|
||||
parse_statement(line.data());
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user