mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-10-27 12:59:34 +00:00
Migrate magisk_main to Rust
This commit is contained in:
@@ -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 \
|
||||
|
||||
@@ -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<UnixStream> {
|
||||
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<UnixStream> {
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<rust::String> &args) {
|
||||
if (args.empty())
|
||||
usage();
|
||||
|
||||
// Convert rust strings into c strings
|
||||
size_t argc = args.size();
|
||||
std::vector<const char *> 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
|
||||
|
||||
@@ -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<ModuleInfo> &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<bool> denylist_enforced;
|
||||
int denylist_cli(int argc, char **argv);
|
||||
int denylist_cli(rust::Vec<rust::String> &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()); }
|
||||
|
||||
@@ -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<ModuleInfo>);
|
||||
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<ModuleInfo>);
|
||||
fn install_apk(apk: Utf8CStrRef);
|
||||
fn uninstall_pkg(apk: Utf8CStrRef);
|
||||
fn install_module(zip: Utf8CStrRef);
|
||||
|
||||
// Denylist
|
||||
fn denylist_cli(args: &mut Vec<String>) -> 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
|
||||
|
||||
@@ -1,156 +0,0 @@
|
||||
#include <sys/mount.h>
|
||||
#include <libgen.h>
|
||||
|
||||
#include <base.hpp>
|
||||
#include <consts.hpp>
|
||||
#include <core.hpp>
|
||||
#include <flags.h>
|
||||
|
||||
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();
|
||||
}
|
||||
298
native/src/core/magisk.rs
Normal file
298
native/src/core/magisk.rs
Normal file
@@ -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<String>,
|
||||
}
|
||||
|
||||
#[derive(FromArgs)]
|
||||
#[argh(subcommand, name = "--preinit-device")]
|
||||
struct PreInitDevice {}
|
||||
|
||||
impl MagiskAction {
|
||||
fn exec(self) -> LoggedResult<i32> {
|
||||
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)
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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, ")");
|
||||
|
||||
Reference in New Issue
Block a user