From c64de35375677ed3840d2fc58a625b0006210069 Mon Sep 17 00:00:00 2001 From: LoveSy Date: Fri, 7 Mar 2025 14:29:30 -0800 Subject: [PATCH] Move magiskpolicy cli to argh --- native/src/Android.mk | 2 - native/src/Cargo.lock | 1 + native/src/init/Cargo.toml | 2 +- native/src/sepolicy/Cargo.toml | 5 ++ native/src/sepolicy/cli.rs | 133 +++++++++++++++++++++++++++++++++ native/src/sepolicy/lib.rs | 4 +- native/src/sepolicy/main.cpp | 130 -------------------------------- 7 files changed, 142 insertions(+), 135 deletions(-) create mode 100644 native/src/sepolicy/cli.rs delete mode 100644 native/src/sepolicy/main.cpp diff --git a/native/src/Android.mk b/native/src/Android.mk index d60ab3cbb..701ec61d7 100644 --- a/native/src/Android.mk +++ b/native/src/Android.mk @@ -119,8 +119,6 @@ LOCAL_STATIC_LIBRARIES := \ libpolicy \ libpolicy-rs -LOCAL_SRC_FILES := sepolicy/main.cpp - include $(BUILD_EXECUTABLE) endif diff --git a/native/src/Cargo.lock b/native/src/Cargo.lock index 58b4df3d9..dba9b12c6 100644 --- a/native/src/Cargo.lock +++ b/native/src/Cargo.lock @@ -527,6 +527,7 @@ dependencies = [ name = "magiskpolicy" version = "0.0.0" dependencies = [ + "argh", "base", "cxx", "cxx-gen", diff --git a/native/src/init/Cargo.toml b/native/src/init/Cargo.toml index c377a1adf..7f41e9415 100644 --- a/native/src/init/Cargo.toml +++ b/native/src/init/Cargo.toml @@ -12,5 +12,5 @@ cxx-gen = { workspace = true } [dependencies] base = { path = "../base" } -magiskpolicy = { path = "../sepolicy" } +magiskpolicy = { path = "../sepolicy", default-features = false } cxx = { workspace = true } diff --git a/native/src/sepolicy/Cargo.toml b/native/src/sepolicy/Cargo.toml index 4cbdd8dcf..d86de8619 100644 --- a/native/src/sepolicy/Cargo.toml +++ b/native/src/sepolicy/Cargo.toml @@ -10,6 +10,11 @@ path = "lib.rs" [build-dependencies] cxx-gen = { workspace = true } +[features] +default = ["main"] +main = [] + [dependencies] base = { path = "../base" } cxx = { workspace = true } +argh = { workspace = true } diff --git a/native/src/sepolicy/cli.rs b/native/src/sepolicy/cli.rs new file mode 100644 index 000000000..3e3b46353 --- /dev/null +++ b/native/src/sepolicy/cli.rs @@ -0,0 +1,133 @@ +use crate::ffi::SePolicy; +use argh::FromArgs; +use base::{ + EarlyExitExt, LoggedResult, Utf8CStr, cmdline_logging, cstr, libc::umask, log_err, map_args, +}; +use std::{ffi::c_char, io::Cursor}; + +#[derive(FromArgs)] +struct Cli { + #[argh(switch)] + live: bool, + + #[argh(switch)] + magisk: bool, + + #[argh(switch)] + compile_split: bool, + + #[argh(switch)] + load_split: bool, + + #[argh(switch)] + print_rules: bool, + + #[argh(option)] + load: Option, + + #[argh(option)] + save: Option, + + #[argh(option)] + apply: Vec, + + #[argh(positional)] + polices: Vec, +} + +fn print_usage(cmd: &str) { + eprintln!( + r#"MagiskPolicy - SELinux Policy Patch Tool + +Usage: {} [--options...] [policy statements...] + +Options: + --help show help message for policy statements + --load FILE load monolithic sepolicy from FILE + --load-split load from precompiled sepolicy or compile + split cil policies + --compile-split compile split cil policies + --save FILE dump monolithic sepolicy to FILE + --live immediately load sepolicy into the kernel + --magisk apply built-in Magisk sepolicy rules + --apply FILE apply rules from FILE, read and parsed + line by line as policy statements + (multiple --apply are allowed) + --print-rules print all rules in the loaded sepolicy + +If neither --load, --load-split, nor --compile-split is specified, +it will load from current live policies (/sys/fs/selinux/policy) +"#, + cmd + ); + + SePolicy::print_statement_help(); +} + +#[unsafe(no_mangle)] +pub unsafe extern "C" fn main( + argc: i32, + argv: *const *const c_char, + _envp: *const *const c_char, +) -> i32 { + cmdline_logging(); + unsafe { + umask(0); + } + + let res: LoggedResult<()> = try { + let cmds = map_args(argc, argv)?; + if argc < 2 { + print_usage(cmds.first().unwrap_or(&"magiskpolicy")); + return 1; + } + let mut cli = Cli::from_args(&[cmds[0]], &cmds[1..]).on_early_exit(|| print_usage(cmds[0])); + + let mut sepol = match (&mut cli.load, cli.load_split, cli.compile_split) { + (Some(file), false, false) => SePolicy::from_file(Utf8CStr::from_string(file)), + (None, true, false) => SePolicy::from_split(), + (None, false, true) => SePolicy::compile_split(), + (None, false, false) => SePolicy::from_file(cstr!("/sys/fs/selinux/policy")), + _ => Err(log_err!("Multiple load source supplied"))?, + }; + if sepol._impl.is_null() { + Err(log_err!("Cannot load policy"))?; + } + + if cli.print_rules { + if cli.magisk + || !cli.apply.is_empty() + || !cli.polices.is_empty() + || cli.live + || cli.save.is_some() + { + Err(log_err!("Cannot print rules with other options"))?; + } + sepol.print_rules(); + return 0; + } + + if cli.magisk { + sepol.magisk_rules(); + } + + for file in &mut cli.apply { + sepol.load_rule_file(Utf8CStr::from_string(file)); + } + + for statement in &cli.polices { + sepol.load_rules_from_reader(&mut Cursor::new(statement)); + } + + if cli.live && !sepol.to_file(cstr!("/sys/fs/selinux/load")) { + Err(log_err!("Cannot apply policy"))?; + } + + if let Some(file) = &mut cli.save { + if !sepol.to_file(Utf8CStr::from_string(file)) { + Err(log_err!("Cannot dump policy to {}", file))?; + } + } + }; + if res.is_ok() { 0 } else { 1 } +} diff --git a/native/src/sepolicy/lib.rs b/native/src/sepolicy/lib.rs index 51efcfa66..ec22d0b29 100644 --- a/native/src/sepolicy/lib.rs +++ b/native/src/sepolicy/lib.rs @@ -10,6 +10,8 @@ use std::io::{BufRead, BufReader, Cursor}; use crate::ffi::SePolicy; +#[cfg(feature = "main")] +mod cli; mod rules; mod statement; @@ -88,8 +90,6 @@ pub mod ffi { fn load_rules(self: &mut SePolicy, rules: &CxxString); #[Self = SePolicy] fn xperm_to_string(perm: &Xperm) -> String; - #[Self = SePolicy] - fn print_statement_help(); } } diff --git a/native/src/sepolicy/main.cpp b/native/src/sepolicy/main.cpp deleted file mode 100644 index 54b5c1fec..000000000 --- a/native/src/sepolicy/main.cpp +++ /dev/null @@ -1,130 +0,0 @@ -#include -#include - -#include "include/sepolicy.hpp" - -using namespace std; - -[[noreturn]] static void usage(char *arg0) { - fprintf(stderr, -R"EOF(MagiskPolicy - SELinux Policy Patch Tool - -Usage: %s [--options...] [policy statements...] - -Options: - --help show help message for policy statements - --load FILE load monolithic sepolicy from FILE - --load-split load from precompiled sepolicy or compile - split cil policies - --compile-split compile split cil policies - --save FILE dump monolithic sepolicy to FILE - --live immediately load sepolicy into the kernel - --magisk apply built-in Magisk sepolicy rules - --apply FILE apply rules from FILE, read and parsed - line by line as policy statements - (multiple --apply are allowed) - --print-rules print all rules in the loaded sepolicy - -If neither --load, --load-split, nor --compile-split is specified, -it will load from current live policies (/sys/fs/selinux/policy) - -)EOF", arg0); - exit(1); -} - -int main(int argc, char *argv[]) { - cmdline_logging(); - const char *out_file = nullptr; - vector rule_files; - SePolicy sepol; - bool magisk = false; - bool live = false; - bool print = false; - - if (argc < 2) usage(argv[0]); - int i = 1; - for (; i < argc; ++i) { - // Parse options - if (argv[i][0] == '-' && argv[i][1] == '-') { - auto option = argv[i] + 2; - if (option == "live"sv) - live = true; - else if (option == "magisk"sv) - magisk = true; - else if (option == "print-rules"sv) - print = true; - else if (option == "load"sv) { - if (argv[i + 1] == nullptr) - usage(argv[0]); - sepol = SePolicy::from_file(argv[i + 1]); - if (!sepol.impl) { - fprintf(stderr, "Cannot load policy from %s\n", argv[i + 1]); - return 1; - } - ++i; - } else if (option == "load-split"sv) { - sepol = SePolicy::from_split(); - if (!sepol.impl) { - fprintf(stderr, "Cannot load split cil\n"); - return 1; - } - } else if (option == "compile-split"sv) { - sepol = SePolicy::compile_split(); - if (!sepol.impl) { - fprintf(stderr, "Cannot compile split cil\n"); - return 1; - } - } else if (option == "save"sv) { - if (argv[i + 1] == nullptr) - usage(argv[0]); - out_file = argv[i + 1]; - ++i; - } else if (option == "apply"sv) { - if (argv[i + 1] == nullptr) - usage(argv[0]); - rule_files.emplace_back(argv[i + 1]); - ++i; - } else if (option == "help"sv) { - SePolicy::print_statement_help(); - exit(0); - } else { - usage(argv[0]); - } - } else { - break; - } - } - - // Use current policy if nothing is loaded - if (!sepol.impl && !(sepol = SePolicy::from_file(SELINUX_POLICY)).impl) { - fprintf(stderr, "Cannot load policy from " SELINUX_POLICY "\n"); - return 1; - } - - if (print) { - sepol.print_rules(); - return 0; - } - - if (magisk) - sepol.magisk_rules(); - - if (!rule_files.empty()) - for (const auto &rule_file : rule_files) - sepol.load_rule_file(rule_file.data()); - - for (; i < argc; ++i) - sepol.parse_statement(argv[i]); - - if (live && !sepol.to_file(SELINUX_LOAD)) { - fprintf(stderr, "Cannot apply policy\n"); - return 1; - } - - if (out_file && !sepol.to_file(out_file)) { - fprintf(stderr, "Cannot dump policy to %s\n", out_file); - return 1; - } - - return 0; -}