mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-12-22 07:57:39 +00:00
Parse rule files with Rust
This commit is contained in:
parent
5a94ef9106
commit
18d0cedbe2
@ -176,7 +176,8 @@ LOCAL_SRC_FILES := \
|
||||
sepolicy/sepolicy.cpp \
|
||||
sepolicy/rules.cpp \
|
||||
sepolicy/policydb.cpp \
|
||||
sepolicy/statement.cpp
|
||||
sepolicy/statement.cpp \
|
||||
sepolicy/policy-rs.cpp
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
include src/Android-rs.mk
|
||||
|
46
native/src/Cargo.lock
generated
46
native/src/Cargo.lock
generated
@ -83,7 +83,7 @@ dependencies = [
|
||||
"codespan-reporting",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.15",
|
||||
"syn 2.0.16",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -96,7 +96,7 @@ version = "1.0.94"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.15",
|
||||
"syn 2.0.16",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -168,9 +168,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "io-lifetimes"
|
||||
version = "1.0.10"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220"
|
||||
checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
@ -179,15 +179,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.142"
|
||||
version = "0.2.144"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317"
|
||||
checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.3.6"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b64f40e5e03e0d54f03845c8197d0291253cdbedfb1cb46b13c2c117554a9f4c"
|
||||
checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
@ -228,13 +228,17 @@ dependencies = [
|
||||
"base",
|
||||
"cxx",
|
||||
"cxx-gen",
|
||||
"magiskpolicy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "magiskpolicy"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"base",
|
||||
"cxx",
|
||||
"cxx-gen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -331,9 +335,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.26"
|
||||
version = "1.0.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
|
||||
checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
@ -349,9 +353,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.8.1"
|
||||
version = "1.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370"
|
||||
checksum = "d1a59b5d8e97dee33696bf13c5ba8ab85341c002922fba050069326b9c498974"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
@ -360,15 +364,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.7.1"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c"
|
||||
checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78"
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.37.18"
|
||||
version = "0.37.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8bbfc1d1c7c40c01715f47d71444744a81669ca84e8b63e25a55e169b1f86433"
|
||||
checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"errno",
|
||||
@ -391,9 +395,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.15"
|
||||
version = "2.0.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822"
|
||||
checksum = "a6f671d4b5ffdb8eadec19c0ae67fe2639df8684bd7bc4b83d986b8db549cf01"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -439,14 +443,14 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.15",
|
||||
"syn 2.0.16",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.8"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
|
||||
checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
|
@ -2,19 +2,23 @@
|
||||
exclude = ["external"]
|
||||
members = ["base", "boot", "core", "init", "sepolicy"]
|
||||
|
||||
[workspace.dependencies]
|
||||
cxx = { path = "external/cxx-rs" }
|
||||
cxx-gen = { path = "external/cxx-rs/gen/lib" }
|
||||
libc = "0.2"
|
||||
cfg-if = "1.0"
|
||||
anyhow = "1.0"
|
||||
num-traits = "0.2"
|
||||
num-derive = "0.3"
|
||||
|
||||
[profile.dev]
|
||||
opt-level = "z"
|
||||
lto = true
|
||||
codegen-units = 1
|
||||
panic = "abort"
|
||||
strip = true
|
||||
|
||||
[profile.release]
|
||||
opt-level = "z"
|
||||
lto = true
|
||||
codegen-units = 1
|
||||
panic = "abort"
|
||||
strip = true
|
||||
|
||||
[patch.crates-io]
|
||||
cxx = { path = "external/cxx-rs" }
|
||||
|
@ -7,9 +7,9 @@ edition = "2021"
|
||||
path = "lib.rs"
|
||||
|
||||
[build-dependencies]
|
||||
cxx-gen = { path = "../external/cxx-rs/gen/lib" }
|
||||
cxx-gen = { workspace = true }
|
||||
|
||||
[dependencies]
|
||||
cxx = { path = "../external/cxx-rs" }
|
||||
libc = "0.2"
|
||||
cfg-if = "1.0"
|
||||
cxx = { workspace = true }
|
||||
libc = { workspace = true }
|
||||
cfg-if = { workspace = true }
|
||||
|
@ -1,14 +1,12 @@
|
||||
use std::cmp::min;
|
||||
use std::ffi::CStr;
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::io::{BufRead, Write};
|
||||
use std::os::unix::io::{AsRawFd, FromRawFd, OwnedFd, RawFd};
|
||||
use std::path::Path;
|
||||
|
||||
use libc::{c_char, c_uint, mode_t, EEXIST, ENOENT, O_CLOEXEC, O_PATH};
|
||||
|
||||
use crate::{bfmt_cstr, errno, xopen};
|
||||
use crate::{bfmt_cstr, errno, error, xopen};
|
||||
|
||||
pub mod unsafe_impl {
|
||||
use std::ffi::CStr;
|
||||
@ -137,9 +135,43 @@ pub extern "C" fn mkdirs(path: *const c_char, mode: mode_t) -> i32 {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_lines<P: AsRef<Path>>(path: P) -> io::Result<io::Lines<io::BufReader<File>>> {
|
||||
let file = File::open(path)?;
|
||||
Ok(io::BufReader::new(file).lines())
|
||||
pub trait BufReadExt {
|
||||
fn foreach_lines<F: FnMut(&mut String) -> bool>(&mut self, f: F);
|
||||
fn foreach_props<F: FnMut(&str, &str) -> bool>(&mut self, f: F);
|
||||
}
|
||||
|
||||
impl<T: BufRead> BufReadExt for T {
|
||||
fn foreach_lines<F: FnMut(&mut String) -> bool>(&mut self, mut f: F) {
|
||||
let mut buf = String::new();
|
||||
loop {
|
||||
match self.read_line(&mut buf) {
|
||||
Ok(0) => break,
|
||||
Ok(_) => {
|
||||
if !f(&mut buf) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
error!("{}", e);
|
||||
break;
|
||||
}
|
||||
};
|
||||
buf.clear();
|
||||
}
|
||||
}
|
||||
|
||||
fn foreach_props<F: FnMut(&str, &str) -> bool>(&mut self, mut f: F) {
|
||||
self.foreach_lines(|line| {
|
||||
let line = line.trim();
|
||||
if line.starts_with('#') {
|
||||
return true;
|
||||
}
|
||||
if let Some((key, value)) = line.split_once('=') {
|
||||
return f(key, value);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pub trait WriteExt {
|
||||
|
@ -9,7 +9,7 @@ path = "lib.rs"
|
||||
|
||||
[build-dependencies]
|
||||
protobuf-codegen = "3.2.0"
|
||||
cxx-gen = { path = "../external/cxx-rs/gen/lib" }
|
||||
cxx-gen = { workspace = true }
|
||||
|
||||
[dependencies]
|
||||
base = { path = "../base" }
|
||||
|
@ -8,10 +8,10 @@ crate-type = ["staticlib"]
|
||||
path = "lib.rs"
|
||||
|
||||
[build-dependencies]
|
||||
cxx-gen = { path = "../external/cxx-rs/gen/lib" }
|
||||
cxx-gen = { workspace = true }
|
||||
|
||||
[dependencies]
|
||||
base = { path = "../base" }
|
||||
cxx = { path = "../external/cxx-rs" }
|
||||
num-traits = "0.2"
|
||||
num-derive = "0.3"
|
||||
cxx = { workspace = true }
|
||||
num-traits = { workspace = true }
|
||||
num-derive = { workspace = true }
|
||||
|
@ -8,8 +8,9 @@ crate-type = ["staticlib"]
|
||||
path = "lib.rs"
|
||||
|
||||
[build-dependencies]
|
||||
cxx-gen = { path = "../external/cxx-rs/gen/lib" }
|
||||
cxx-gen = { workspace = true }
|
||||
|
||||
[dependencies]
|
||||
base = { path = "../base" }
|
||||
cxx = { path = "../external/cxx-rs" }
|
||||
magiskpolicy = { path = "../sepolicy" }
|
||||
cxx = { workspace = true }
|
||||
|
@ -1,4 +1,6 @@
|
||||
pub use logging::*;
|
||||
// Has to be pub so all symbols in that crate is included
|
||||
pub use magiskpolicy;
|
||||
|
||||
mod logging;
|
||||
|
||||
|
@ -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()));
|
||||
}
|
||||
|
8
native/src/sepolicy/build.rs
Normal file
8
native/src/sepolicy/build.rs
Normal file
@ -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;
|
||||
});
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user