diff --git a/native/src/Android.mk b/native/src/Android.mk index bd51aaa86..37e2fce53 100644 --- a/native/src/Android.mk +++ b/native/src/Android.mk @@ -16,7 +16,6 @@ LOCAL_STATIC_LIBRARIES := \ LOCAL_SRC_FILES := \ core/applets.cpp \ - core/magisk.cpp \ core/scripting.cpp \ core/sqlite.cpp \ core/utils.cpp \ diff --git a/native/src/core/daemon.rs b/native/src/core/daemon.rs index 6eb69c21e..43b16fb17 100644 --- a/native/src/core/daemon.rs +++ b/native/src/core/daemon.rs @@ -12,21 +12,20 @@ use crate::module::remove_modules; use crate::package::ManagerInfo; use crate::resetprop::{get_prop, set_prop}; use crate::selinux::restore_tmpcon; -use crate::socket::IpcWrite; +use crate::socket::{IpcRead, IpcWrite}; use crate::su::SuInfo; use crate::thread::ThreadPool; use crate::zygisk::ZygiskState; use base::const_format::concatcp; use base::{ - AtomicArc, BufReadExt, FileAttr, FsPathBuilder, ReadExt, ResultExt, Utf8CStr, Utf8CStrBuf, - WriteExt, cstr, error, fork_dont_care, info, libc, set_nice_name, + AtomicArc, BufReadExt, FileAttr, FsPathBuilder, LoggedResult, ReadExt, ResultExt, Utf8CStr, + Utf8CStrBuf, WriteExt, cstr, fork_dont_care, info, libc, log_err, set_nice_name, }; -use nix::unistd::getuid; use nix::{ fcntl::OFlag, mount::MsFlags, sys::signal::SigSet, - unistd::{dup2_stderr, dup2_stdin, dup2_stdout, getpid, setsid}, + unistd::{dup2_stderr, dup2_stdin, dup2_stdout, getpid, getuid, setsid}, }; use num_traits::AsPrimitive; use std::fmt::Write as _; @@ -134,14 +133,13 @@ impl MagiskD { self.zygisk.lock().unwrap().reset(false); } RequestCode::SQLITE_CMD => { - self.db_exec_for_cli(client.into()).ok(); + self.db_exec_for_cli(client).ok(); } RequestCode::REMOVE_MODULES => { - let mut do_reboot: i32 = 0; - client.read_pod(&mut do_reboot).log_ok(); + let do_reboot: bool = client.read_decodable().log().unwrap_or_default(); remove_modules(); client.write_pod(&0).log_ok(); - if do_reboot != 0 { + if do_reboot { self.reboot(); } } @@ -422,29 +420,26 @@ fn daemon_entry() { } } -pub fn connect_daemon(code: RequestCode, create: bool) -> RawFd { +pub fn connect_daemon(code: RequestCode, create: bool) -> LoggedResult { let sock_path = cstr::buf::new::<64>() .join_path(get_magisk_tmp()) .join_path(MAIN_SOCKET); - fn send_request(code: RequestCode, mut socket: UnixStream) -> RawFd { + fn send_request(code: RequestCode, mut socket: UnixStream) -> LoggedResult { socket.write_pod(&code.repr).log_ok(); let mut res = -1; socket.read_pod(&mut res).log_ok(); let res = RespondCode { repr: res }; match res { - RespondCode::OK => socket.into_raw_fd(), + RespondCode::OK => Ok(socket), RespondCode::ROOT_REQUIRED => { - error!("Root is required for this operation"); - -1 + log_err!("Root is required for this operation") } RespondCode::ACCESS_DENIED => { - error!("Accessed denied"); - -1 + log_err!("Accessed denied") } _ => { - error!("Daemon error"); - -1 + log_err!("Daemon error") } } } @@ -453,16 +448,14 @@ pub fn connect_daemon(code: RequestCode, create: bool) -> RawFd { Ok(socket) => send_request(code, socket), Err(e) => { if !create || !getuid().is_root() { - error!("Cannot connect to daemon: {e}"); - return -1; + return log_err!("Cannot connect to daemon: {e}"); } let mut buf = cstr::buf::new::<64>(); if cstr!("/proc/self/exe").read_link(&mut buf).is_err() || !buf.starts_with(get_magisk_tmp().as_str()) { - error!("Start daemon on magisk tmpfs"); - return -1; + return log_err!("Start daemon on magisk tmpfs"); } // Fork a process and run the daemon @@ -482,3 +475,9 @@ pub fn connect_daemon(code: RequestCode, create: bool) -> RawFd { } } } + +pub fn connect_daemon_for_cxx(code: RequestCode, create: bool) -> RawFd { + connect_daemon(code, create) + .map(IntoRawFd::into_raw_fd) + .unwrap_or(-1) +} diff --git a/native/src/core/db.rs b/native/src/core/db.rs index 2032695bd..bcde1aa15 100644 --- a/native/src/core/db.rs +++ b/native/src/core/db.rs @@ -9,9 +9,8 @@ use base::{LoggedResult, ResultExt, Utf8CStr}; use num_derive::FromPrimitive; use num_traits::FromPrimitive; use std::ffi::c_void; -use std::fs::File; use std::io::{BufReader, BufWriter}; -use std::os::fd::OwnedFd; +use std::os::unix::net::UnixStream; use std::pin::Pin; use std::ptr; use std::ptr::NonNull; @@ -302,8 +301,7 @@ impl MagiskD { .sql_result() } - pub fn db_exec_for_cli(&self, fd: OwnedFd) -> LoggedResult<()> { - let mut file = File::from(fd); + pub fn db_exec_for_cli(&self, mut file: UnixStream) -> LoggedResult<()> { let mut reader = BufReader::new(&mut file); let sql: String = reader.read_decodable()?; let mut writer = BufWriter::new(&mut file); diff --git a/native/src/core/deny/cli.cpp b/native/src/core/deny/cli.cpp index fe6c3bfd6..e7c75b4fd 100644 --- a/native/src/core/deny/cli.cpp +++ b/native/src/core/deny/cli.cpp @@ -62,28 +62,35 @@ void denylist_handler(int client) { close(client); } -int denylist_cli(int argc, char **argv) { - if (argc < 2) +int denylist_cli(rust::Vec &args) { + if (args.empty()) usage(); + // Convert rust strings into c strings + size_t argc = args.size(); + std::vector argv; + ranges::transform(args, std::back_inserter(argv), [](rust::String &arg) { return arg.c_str(); }); + // End with nullptr + argv.push_back(nullptr); + int req; - if (argv[1] == "enable"sv) + if (argv[0] == "enable"sv) req = DenyRequest::ENFORCE; - else if (argv[1] == "disable"sv) + else if (argv[0] == "disable"sv) req = DenyRequest::DISABLE; - else if (argv[1] == "add"sv) + else if (argv[0] == "add"sv) req = DenyRequest::ADD; - else if (argv[1] == "rm"sv) + else if (argv[0] == "rm"sv) req = DenyRequest::REMOVE; - else if (argv[1] == "ls"sv) + else if (argv[0] == "ls"sv) req = DenyRequest::LIST; - else if (argv[1] == "status"sv) + else if (argv[0] == "status"sv) req = DenyRequest::STATUS; - else if (argv[1] == "exec"sv && argc > 2) { + else if (argv[0] == "exec"sv && argc > 1) { xunshare(CLONE_NEWNS); xmount(nullptr, "/", nullptr, MS_PRIVATE | MS_REC, nullptr); revert_unmount(); - execvp(argv[2], argv + 2); + execvp(argv[1], (char **) argv.data() + 1); exit(1); } else { usage(); @@ -93,8 +100,8 @@ int denylist_cli(int argc, char **argv) { int fd = connect_daemon(RequestCode::DENYLIST); write_int(fd, req); if (req == DenyRequest::ADD || req == DenyRequest::REMOVE) { - write_string(fd, argv[2]); - write_string(fd, argv[3] ? argv[3] : ""); + write_string(fd, argv[1]); + write_string(fd, argv[2] ? argv[2] : ""); } // Get response diff --git a/native/src/core/include/core.hpp b/native/src/core/include/core.hpp index 8923454c6..ee42f1ae4 100644 --- a/native/src/core/include/core.hpp +++ b/native/src/core/include/core.hpp @@ -24,7 +24,6 @@ inline int connect_daemon(RequestCode req) { } // Multi-call entrypoints -int magisk_main(int argc, char *argv[]); int su_client_main(int argc, char *argv[]); int zygisk_main(int argc, char *argv[]); @@ -68,13 +67,13 @@ void install_apk(Utf8CStr apk); void uninstall_pkg(Utf8CStr pkg); void exec_common_scripts(Utf8CStr stage); void exec_module_scripts(Utf8CStr stage, const rust::Vec &module_list); -void exec_script(const char *script); +void exec_script(Utf8CStr script); void clear_pkg(const char *pkg, int user_id); -[[noreturn]] void install_module(const char *file); +[[noreturn]] void install_module(Utf8CStr file); // Denylist extern std::atomic denylist_enforced; -int denylist_cli(int argc, char **argv); +int denylist_cli(rust::Vec &args); void denylist_handler(int client); void initialize_denylist(); void scan_deny_apps(); @@ -90,4 +89,3 @@ inline Utf8CStr get_magisk_tmp_rs() { return get_magisk_tmp(); } inline rust::String resolve_preinit_dir_rs(Utf8CStr base_dir) { return resolve_preinit_dir(base_dir.c_str()); } -inline void exec_script_rs(Utf8CStr script) { exec_script(script.c_str()); } diff --git a/native/src/core/lib.rs b/native/src/core/lib.rs index 765a33386..111f11cf5 100644 --- a/native/src/core/lib.rs +++ b/native/src/core/lib.rs @@ -9,9 +9,10 @@ use crate::ffi::SuRequest; use crate::socket::Encodable; -use daemon::{MagiskD, connect_daemon}; +use daemon::{MagiskD, connect_daemon_for_cxx}; use derive::Decodable; use logging::{android_logging, zygisk_close_logd, zygisk_get_logd, zygisk_logging}; +use magisk::magisk_main; use mount::{find_preinit_device, revert_unmount}; use resetprop::{get_prop, resetprop_main}; use selinux::{lgetfilecon, lsetfilecon, restorecon, setfilecon}; @@ -29,6 +30,7 @@ mod consts; mod daemon; mod db; mod logging; +mod magisk; mod module; mod mount; mod package; @@ -146,18 +148,22 @@ pub mod ffi { #[cxx_name = "resolve_preinit_dir_rs"] fn resolve_preinit_dir(base_dir: Utf8CStrRef) -> String; fn check_key_combo() -> bool; - #[cxx_name = "exec_script_rs"] - fn exec_script(script: Utf8CStrRef); - fn exec_common_scripts(stage: Utf8CStrRef); - fn exec_module_scripts(state: Utf8CStrRef, modules: &Vec); - fn install_apk(apk: Utf8CStrRef); - fn uninstall_pkg(apk: Utf8CStrRef); + fn unlock_blocks(); fn update_deny_flags(uid: i32, process: &str, flags: &mut u32); fn initialize_denylist(); fn switch_mnt_ns(pid: i32) -> i32; fn exec_root_shell(client: i32, pid: i32, req: &mut SuRequest, mode: MntNsMode); + // Scripting + fn exec_script(script: Utf8CStrRef); + fn exec_common_scripts(stage: Utf8CStrRef); + fn exec_module_scripts(state: Utf8CStrRef, modules: &Vec); + fn install_apk(apk: Utf8CStrRef); + fn uninstall_pkg(apk: Utf8CStrRef); + fn install_module(zip: Utf8CStrRef); + // Denylist + fn denylist_cli(args: &mut Vec) -> i32; fn denylist_handler(client: i32); fn scan_deny_apps(); @@ -198,7 +204,9 @@ pub mod ffi { fn get_prop(name: Utf8CStrRef) -> String; unsafe fn resetprop_main(argc: i32, argv: *mut *mut c_char) -> i32; - fn connect_daemon(code: RequestCode, create: bool) -> i32; + #[cxx_name = "connect_daemon"] + fn connect_daemon_for_cxx(code: RequestCode, create: bool) -> i32; + unsafe fn magisk_main(argc: i32, argv: *mut *mut c_char) -> i32; } // Default constructors diff --git a/native/src/core/magisk.cpp b/native/src/core/magisk.cpp deleted file mode 100644 index 335575bcd..000000000 --- a/native/src/core/magisk.cpp +++ /dev/null @@ -1,156 +0,0 @@ -#include -#include - -#include -#include -#include -#include - -using namespace std; - -[[noreturn]] static void usage() { - fprintf(stderr, -R"EOF(Magisk - Multi-purpose Utility - -Usage: magisk [applet [arguments]...] - or: magisk [options]... - -Options: - -c print current binary version - -v print running daemon version - -V print running daemon version code - --list list all available applets - --remove-modules [-n] remove all modules, reboot if -n is not provided - --install-module ZIP install a module zip file - -Advanced Options (Internal APIs): - --daemon manually start magisk daemon - --stop remove all magisk changes and stop daemon - --[init trigger] callback on init triggers. Valid triggers: - post-fs-data, service, boot-complete, zygote-restart - --unlock-blocks set BLKROSET flag to OFF for all block devices - --restorecon restore selinux context on Magisk files - --clone-attr SRC DEST clone permission, owner, and selinux context - --clone SRC DEST clone SRC to DEST - --sqlite SQL exec SQL commands to Magisk database - --path print Magisk tmpfs mount path - --denylist ARGS denylist config CLI - --preinit-device resolve a device to store preinit files - -Available applets: -)EOF"); - - for (int i = 0; applet_names[i]; ++i) - fprintf(stderr, i ? ", %s" : " %s", applet_names[i]); - fprintf(stderr, "\n\n"); - exit(1); -} - -#define quote(s) #s -#define str(s) quote(s) - -int magisk_main(int argc, char *argv[]) { - if (argc < 2) - usage(); - if (argv[1] == "-c"sv) { -#if MAGISK_DEBUG - printf(MAGISK_VERSION ":MAGISK:D (" str(MAGISK_VER_CODE) ")\n"); -#else - printf(MAGISK_VERSION ":MAGISK:R (" str(MAGISK_VER_CODE) ")\n"); -#endif - return 0; - } else if (argv[1] == "-v"sv) { - int fd = connect_daemon(RequestCode::CHECK_VERSION); - string v = read_string(fd); - printf("%s\n", v.data()); - return 0; - } else if (argv[1] == "-V"sv) { - int fd = connect_daemon(RequestCode::CHECK_VERSION_CODE); - printf("%d\n", read_int(fd)); - return 0; - } else if (argv[1] == "--list"sv) { - for (int i = 0; applet_names[i]; ++i) - printf("%s\n", applet_names[i]); - return 0; - } else if (argv[1] == "--unlock-blocks"sv) { - unlock_blocks(); - return 0; - } else if (argv[1] == "--restorecon"sv) { - restorecon(); - return 0; - } else if (argc >= 4 && argv[1] == "--clone-attr"sv) { - clone_attr(argv[2], argv[3]); - return 0; - } else if (argc >= 4 && argv[1] == "--clone"sv) { - cp_afc(argv[2], argv[3]); - return 0; - } else if (argv[1] == "--daemon"sv) { - close(connect_daemon(RequestCode::START_DAEMON, true)); - return 0; - } else if (argv[1] == "--stop"sv) { - int fd = connect_daemon(RequestCode::STOP_DAEMON); - return read_int(fd); - } else if (argv[1] == "--post-fs-data"sv) { - int fd = connect_daemon(RequestCode::POST_FS_DATA, true); - struct pollfd pfd = { fd, POLLIN, 0 }; - poll(&pfd, 1, 1000 * POST_FS_DATA_WAIT_TIME); - return 0; - } else if (argv[1] == "--service"sv) { - close(connect_daemon(RequestCode::LATE_START, true)); - return 0; - } else if (argv[1] == "--boot-complete"sv) { - close(connect_daemon(RequestCode::BOOT_COMPLETE)); - return 0; - } else if (argv[1] == "--zygote-restart"sv) { - close(connect_daemon(RequestCode::ZYGOTE_RESTART)); - return 0; - } else if (argv[1] == "--denylist"sv) { - return denylist_cli(argc - 1, argv + 1); - } else if (argc >= 3 && argv[1] == "--sqlite"sv) { - int fd = connect_daemon(RequestCode::SQLITE_CMD); - write_string(fd, argv[2]); - string res; - for (;;) { - read_string(fd, res); - if (res.empty()) - return 0; - printf("%s\n", res.data()); - } - } else if (argv[1] == "--remove-modules"sv) { - int do_reboot; - if (argc == 3 && argv[2] == "-n"sv) { - do_reboot = 0; - } else if (argc == 2) { - do_reboot = 1; - } else { - usage(); - } - int fd = connect_daemon(RequestCode::REMOVE_MODULES); - write_int(fd, do_reboot); - return read_int(fd); - } else if (argv[1] == "--path"sv) { - const char *path = get_magisk_tmp(); - if (path[0] != '\0') { - printf("%s\n", path); - return 0; - } - return 1; - } else if (argc >= 3 && argv[1] == "--install-module"sv) { - install_module(argv[2]); - } else if (argv[1] == "--preinit-device"sv) { - auto name = find_preinit_device(); - if (!name.empty()) { - printf("%s\n", name.c_str()); - return 0; - } - return 1; - } -#if 0 - /* Entry point for testing stuffs */ - else if (argv[1] == "--test"sv) { - rust_test_entry(); - return 0; - } -#endif - usage(); -} diff --git a/native/src/core/magisk.rs b/native/src/core/magisk.rs new file mode 100644 index 000000000..88411e881 --- /dev/null +++ b/native/src/core/magisk.rs @@ -0,0 +1,298 @@ +use crate::consts::{APPLET_NAMES, MAGISK_VER_CODE, MAGISK_VERSION, POST_FS_DATA_WAIT_TIME}; +use crate::daemon::connect_daemon; +use crate::ffi::{RequestCode, denylist_cli, get_magisk_tmp, install_module, unlock_blocks}; +use crate::mount::find_preinit_device; +use crate::selinux::restorecon; +use crate::socket::{Decodable, Encodable}; +use argh::FromArgs; +use base::{CmdArgs, EarlyExitExt, LoggedResult, Utf8CString, clone_attr}; +use nix::poll::{PollFd, PollFlags, PollTimeout}; +use std::ffi::c_char; +use std::os::fd::AsFd; +use std::process::exit; + +fn print_usage() { + eprintln!( + r#"Magisk - Multi-purpose Utility + +Usage: magisk [applet [arguments]...] + or: magisk [options]... + +Options: + -c print current binary version + -v print running daemon version + -V print running daemon version code + --list list all available applets + --remove-modules [-n] remove all modules, reboot if -n is not provided + --install-module ZIP install a module zip file + +Advanced Options (Internal APIs): + --daemon manually start magisk daemon + --stop remove all magisk changes and stop daemon + --[init trigger] callback on init triggers. Valid triggers: + post-fs-data, service, boot-complete, zygote-restart + --unlock-blocks set BLKROSET flag to OFF for all block devices + --restorecon restore selinux context on Magisk files + --clone-attr SRC DEST clone permission, owner, and selinux context + --clone SRC DEST clone SRC to DEST + --sqlite SQL exec SQL commands to Magisk database + --path print Magisk tmpfs mount path + --denylist ARGS denylist config CLI + --preinit-device resolve a device to store preinit files + +Available applets: + {} +"#, + APPLET_NAMES.join(", ") + ); +} + +#[derive(FromArgs)] +struct Cli { + #[argh(subcommand)] + action: MagiskAction, +} + +#[derive(FromArgs)] +#[argh(subcommand)] +enum MagiskAction { + LocalVersion(LocalVersion), + Version(Version), + VersionCode(VersionCode), + List(ListApplets), + RemoveModules(RemoveModules), + InstallModule(InstallModule), + Daemon(StartDaemon), + Stop(StopDaemon), + PostFsData(PostFsData), + Service(ServiceCmd), + BootComplete(BootComplete), + ZygoteRestart(ZygoteRestart), + UnlockBlocks(UnlockBlocks), + RestoreCon(RestoreCon), + CloneAttr(CloneAttr), + CloneFile(CloneFile), + Sqlite(Sqlite), + Path(PathCmd), + DenyList(DenyList), + PreInitDevice(PreInitDevice), +} + +#[derive(FromArgs)] +#[argh(subcommand, name = "-c")] +struct LocalVersion {} + +#[derive(FromArgs)] +#[argh(subcommand, name = "-v")] +struct Version {} + +#[derive(FromArgs)] +#[argh(subcommand, name = "-V")] +struct VersionCode {} + +#[derive(FromArgs)] +#[argh(subcommand, name = "--list")] +struct ListApplets {} + +#[derive(FromArgs)] +#[argh(subcommand, name = "--remove-modules")] +struct RemoveModules { + #[argh(switch, short = 'n')] + no_reboot: bool, +} + +#[derive(FromArgs)] +#[argh(subcommand, name = "--install-module")] +struct InstallModule { + #[argh(positional)] + zip: Utf8CString, +} + +#[derive(FromArgs)] +#[argh(subcommand, name = "--daemon")] +struct StartDaemon {} + +#[derive(FromArgs)] +#[argh(subcommand, name = "--stop")] +struct StopDaemon {} + +#[derive(FromArgs)] +#[argh(subcommand, name = "--post-fs-data")] +struct PostFsData {} + +#[derive(FromArgs)] +#[argh(subcommand, name = "--service")] +struct ServiceCmd {} + +#[derive(FromArgs)] +#[argh(subcommand, name = "--boot-complete")] +struct BootComplete {} + +#[derive(FromArgs)] +#[argh(subcommand, name = "--zygote-restart")] +struct ZygoteRestart {} + +#[derive(FromArgs)] +#[argh(subcommand, name = "--unlock-blocks")] +struct UnlockBlocks {} + +#[derive(FromArgs)] +#[argh(subcommand, name = "--restorecon")] +struct RestoreCon {} + +#[derive(FromArgs)] +#[argh(subcommand, name = "--clone-attr")] +struct CloneAttr { + #[argh(positional)] + from: Utf8CString, + #[argh(positional)] + to: Utf8CString, +} + +#[derive(FromArgs)] +#[argh(subcommand, name = "--clone")] +struct CloneFile { + #[argh(positional)] + from: Utf8CString, + #[argh(positional)] + to: Utf8CString, +} + +#[derive(FromArgs)] +#[argh(subcommand, name = "--sqlite")] +struct Sqlite { + #[argh(positional)] + sql: String, +} + +#[derive(FromArgs)] +#[argh(subcommand, name = "--path")] +struct PathCmd {} + +#[derive(FromArgs)] +#[argh(subcommand, name = "--denylist")] +struct DenyList { + #[argh(positional, greedy)] + args: Vec, +} + +#[derive(FromArgs)] +#[argh(subcommand, name = "--preinit-device")] +struct PreInitDevice {} + +impl MagiskAction { + fn exec(self) -> LoggedResult { + use MagiskAction::*; + match self { + LocalVersion(_) => { + #[cfg(debug_assertions)] + println!("{MAGISK_VERSION}:MAGISK:D ({MAGISK_VER_CODE})"); + #[cfg(not(debug_assertions))] + println!("{MAGISK_VERSION}:MAGISK:R ({MAGISK_VER_CODE})"); + } + Version(_) => { + let mut fd = connect_daemon(RequestCode::CHECK_VERSION, false)?; + let ver = String::decode(&mut fd)?; + println!("{ver}"); + } + VersionCode(_) => { + let mut fd = connect_daemon(RequestCode::CHECK_VERSION_CODE, false)?; + let ver = i32::decode(&mut fd)?; + println!("{ver}"); + } + List(_) => { + for name in APPLET_NAMES { + println!("{name}"); + } + } + RemoveModules(self::RemoveModules { no_reboot }) => { + let mut fd = connect_daemon(RequestCode::REMOVE_MODULES, false)?; + let do_reboot = !no_reboot; + do_reboot.encode(&mut fd)?; + return Ok(i32::decode(&mut fd)?); + } + InstallModule(self::InstallModule { zip }) => { + install_module(&zip); + } + Daemon(_) => { + let _ = connect_daemon(RequestCode::START_DAEMON, true)?; + } + Stop(_) => { + let mut fd = connect_daemon(RequestCode::STOP_DAEMON, false)?; + return Ok(i32::decode(&mut fd)?); + } + PostFsData(_) => { + let fd = connect_daemon(RequestCode::POST_FS_DATA, true)?; + let mut pfd = [PollFd::new(fd.as_fd(), PollFlags::POLLIN)]; + nix::poll::poll( + &mut pfd, + PollTimeout::try_from(POST_FS_DATA_WAIT_TIME * 1000)?, + )?; + } + Service(_) => { + let _ = connect_daemon(RequestCode::LATE_START, true)?; + } + BootComplete(_) => { + let _ = connect_daemon(RequestCode::BOOT_COMPLETE, false)?; + } + ZygoteRestart(_) => { + let _ = connect_daemon(RequestCode::ZYGOTE_RESTART, false)?; + } + UnlockBlocks(_) => { + unlock_blocks(); + } + RestoreCon(_) => { + restorecon(); + } + CloneAttr(self::CloneAttr { from, to }) => { + clone_attr(&from, &to)?; + } + CloneFile(self::CloneFile { from, to }) => { + from.copy_to(&to)?; + } + Sqlite(self::Sqlite { sql }) => { + let mut fd = connect_daemon(RequestCode::SQLITE_CMD, false)?; + sql.encode(&mut fd)?; + loop { + let line = String::decode(&mut fd)?; + if line.is_empty() { + return Ok(0); + } + println!("{line}"); + } + } + Path(_) => { + let tmp = get_magisk_tmp(); + if tmp.is_empty() { + return Ok(1); + } else { + println!("{tmp}"); + } + } + DenyList(self::DenyList { mut args }) => { + return Ok(denylist_cli(&mut args)); + } + PreInitDevice(_) => { + let name = find_preinit_device(); + if name.is_empty() { + return Ok(1); + } else { + println!("{name}"); + } + } + }; + Ok(0) + } +} + +pub fn magisk_main(argc: i32, argv: *mut *mut c_char) -> i32 { + if argc < 2 { + print_usage(); + exit(1); + } + let mut cmds = CmdArgs::new(argc, argv.cast()).0; + // We need to manually inject "--" so that all actions can be treated as subcommands + cmds.insert(1, "--"); + let cli = Cli::from_args(&cmds[..1], &cmds[1..]).on_early_exit(print_usage); + cli.action.exec().unwrap_or(1) +} diff --git a/native/src/core/scripting.cpp b/native/src/core/scripting.cpp index e98d7e115..7db172d45 100644 --- a/native/src/core/scripting.cpp +++ b/native/src/core/scripting.cpp @@ -29,12 +29,12 @@ static void set_script_env() { setenv("ZYGISK_ENABLED", "1", 1); }; -void exec_script(const char *script) { +void exec_script(Utf8CStr script) { exec_t exec { .pre_exec = set_script_env, .fork = fork_no_orphan }; - exec_command_sync(exec, BBEXEC_CMD, script); + exec_command_sync(exec, BBEXEC_CMD, script.c_str()); } static timespec pfs_timeout; @@ -205,17 +205,17 @@ install_module exit 0 )EOF"; -void install_module(const char *file) { +void install_module(Utf8CStr file) { if (getuid() != 0) abort(stderr, "Run this command with root"); if (access(DATABIN, F_OK) || access(bbpath(), X_OK) || access(DATABIN "/util_functions.sh", F_OK)) abort(stderr, "Incomplete Magisk install"); - if (access(file, F_OK)) - abort(stderr, "'%s' does not exist", file); + if (access(file.c_str(), F_OK)) + abort(stderr, "'%s' does not exist", file.c_str()); - char *zip = realpath(file, nullptr); + char *zip = realpath(file.c_str(), nullptr); setenv("OUTFD", "1", 1); setenv("ZIPFILE", zip, 1); setenv("ASH_STANDALONE", "1", 1); diff --git a/native/src/include/consts.rs b/native/src/include/consts.rs index c7dc6531a..41eb12a66 100644 --- a/native/src/include/consts.rs +++ b/native/src/include/consts.rs @@ -4,6 +4,9 @@ use base::const_format::concatcp; #[path = "../../out/generated/flags.rs"] mod flags; +pub const POST_FS_DATA_WAIT_TIME: i32 = 40; +pub const APPLET_NAMES: &[&str] = &["su", "resetprop"]; + // versions pub use flags::*; pub const MAGISK_FULL_VER: &str = concatcp!(MAGISK_VERSION, "(", MAGISK_VER_CODE, ")");