diff --git a/native/src/core/daemon.cpp b/native/src/core/daemon.cpp index da8e3a514..179b5a868 100644 --- a/native/src/core/daemon.cpp +++ b/native/src/core/daemon.cpp @@ -161,76 +161,6 @@ void write_string(int fd, string_view str) { xwrite(fd, str.data(), str.size()); } -static void handle_request_async(int client, int code, const sock_cred &cred) { - auto &daemon = MagiskD::Get(); - switch (code) { - case +RequestCode::DENYLIST: - denylist_handler(client, &cred); - break; - case +RequestCode::SUPERUSER: - daemon.su_daemon_handler(client, cred); - break; - case +RequestCode::ZYGOTE_RESTART: { - LOGI("** zygote restarted\n"); - daemon.prune_su_access(); - scan_deny_apps(); - daemon.zygisk_reset(false); - close(client); - break; - } - case +RequestCode::SQLITE_CMD: - daemon.db_exec(client); - break; - case +RequestCode::REMOVE_MODULES: { - int do_reboot = read_int(client); - remove_modules(); - write_int(client, 0); - close(client); - if (do_reboot) { - daemon.reboot(); - } - break; - } - case +RequestCode::ZYGISK: - daemon.zygisk_handler(client); - break; - default: - __builtin_unreachable(); - } -} - -static void handle_request_sync(int client, int code) { - switch (code) { - case +RequestCode::CHECK_VERSION: -#if MAGISK_DEBUG - write_string(client, MAGISK_VERSION ":MAGISK:D"); -#else - write_string(client, MAGISK_VERSION ":MAGISK:R"); -#endif - break; - case +RequestCode::CHECK_VERSION_CODE: - write_int(client, MAGISK_VER_CODE); - break; - case +RequestCode::START_DAEMON: - setup_logfile(); - break; - case +RequestCode::STOP_DAEMON: { - // Unmount all overlays - denylist_handler(-1, nullptr); - - // Restore native bridge property - MagiskD::Get().restore_zygisk_prop(); - - write_int(client, 0); - - // Terminate the daemon! - exit(0); - } - default: - __builtin_unreachable(); - } -} - static bool is_client(pid_t pid) { // Verify caller is the same as server char path[32]; @@ -244,16 +174,13 @@ static void handle_request(pollfd *pfd) { // Verify client credentials sock_cred cred; - bool is_root; - bool is_zygote; - int code; if (!get_client_cred(client, &cred)) { // Client died return; } - is_root = cred.uid == AID_ROOT; - is_zygote = cred.context == "u:r:zygote:s0"; + bool is_root = cred.uid == AID_ROOT; + bool is_zygote = cred.context == "u:r:zygote:s0"; if (!is_root && !is_zygote && !is_client(cred.pid)) { // Unsupported client state @@ -261,7 +188,7 @@ static void handle_request(pollfd *pfd) { return; } - code = read_int(client); + int code = read_int(client); if (code < 0 || code >= +RequestCode::END || code == +RequestCode::_SYNC_BARRIER_ || code == +RequestCode::_STAGE_BARRIER_) { @@ -303,9 +230,11 @@ static void handle_request(pollfd *pfd) { write_int(client, +RespondCode::OK); if (code < +RequestCode::_SYNC_BARRIER_) { - handle_request_sync(client, code); + MagiskD::Get().handle_request_sync(client.release(), code); } else if (code < +RequestCode::_STAGE_BARRIER_) { - exec_task([=, fd = client.release()] { handle_request_async(fd, code, cred); }); + exec_task([=, fd = client.release()] { + MagiskD::Get().handle_request_async(fd, code, cred); + }); } else { exec_task([=, fd = client.release()] { MagiskD::Get().boot_stage_handler(fd, code); @@ -499,7 +428,7 @@ void unlock_blocks() { bool check_key_combo() { uint8_t bitmask[(KEY_MAX + 1) / 8]; - vector events; + vector events; constexpr char name[] = "/dev/.ev"; // First collect candidate events that accepts volume down @@ -513,19 +442,17 @@ bool check_key_combo() { memset(bitmask, 0, sizeof(bitmask)); ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(bitmask)), bitmask); if (test_bit(KEY_VOLUMEDOWN, bitmask)) - events.push_back(fd); + events.emplace_back(fd); else close(fd); } if (events.empty()) return false; - run_finally fin([&]{ std::for_each(events.begin(), events.end(), close); }); - // Check if volume down key is held continuously for more than 3 seconds for (int i = 0; i < 300; ++i) { bool pressed = false; - for (const int &fd : events) { + for (int fd : events) { memset(bitmask, 0, sizeof(bitmask)); ioctl(fd, EVIOCGKEY(sizeof(bitmask)), bitmask); if (test_bit(KEY_VOLUMEDOWN, bitmask)) { diff --git a/native/src/core/daemon.rs b/native/src/core/daemon.rs index 1632e6050..ac73c32a9 100644 --- a/native/src/core/daemon.rs +++ b/native/src/core/daemon.rs @@ -1,24 +1,33 @@ -use crate::consts::{MAGISK_FULL_VER, MAGISK_PROC_CON, MAIN_CONFIG, ROOTMNT, ROOTOVL, SECURE_DIR}; +use crate::UCred; +use crate::consts::{ + MAGISK_FULL_VER, MAGISK_PROC_CON, MAGISK_VER_CODE, MAGISK_VERSION, MAIN_CONFIG, ROOTMNT, + ROOTOVL, SECURE_DIR, +}; use crate::db::Sqlite3; use crate::ffi::{ - DbEntryKey, ModuleInfo, RequestCode, check_key_combo, exec_common_scripts, exec_module_scripts, - get_magisk_tmp, initialize_denylist, setup_magisk_env, + DbEntryKey, ModuleInfo, RequestCode, check_key_combo, denylist_handler, exec_common_scripts, + exec_module_scripts, get_magisk_tmp, initialize_denylist, scan_deny_apps, setup_magisk_env, }; use crate::logging::{magisk_logging, setup_logfile, start_log_daemon}; -use crate::module::disable_modules; +use crate::module::{disable_modules, remove_modules}; use crate::mount::{clean_mounts, setup_preinit_dir}; use crate::package::ManagerInfo; use crate::resetprop::{get_prop, set_prop}; use crate::selinux::restore_tmpcon; +use crate::socket::IpcWrite; use crate::su::SuInfo; use crate::zygisk::ZygiskState; +use base::const_format::concatcp; use base::libc::{O_APPEND, O_CLOEXEC, O_RDONLY, O_WRONLY}; use base::{ - AtomicArc, BufReadExt, FsPathBuilder, ResultExt, Utf8CStr, Utf8CStrBuf, cstr, error, info, libc, + AtomicArc, BufReadExt, FsPathBuilder, ReadExt, ResultExt, Utf8CStr, Utf8CStrBuf, WriteExt, + cstr, error, info, libc, }; use std::fmt::Write as FmtWrite; +use std::fs::File; use std::io::{BufReader, Write}; -use std::process::Command; +use std::os::fd::{FromRawFd, IntoRawFd, OwnedFd}; +use std::process::{Command, exit}; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Mutex, OnceLock}; @@ -175,6 +184,8 @@ impl MagiskD { } pub fn boot_stage_handler(&self, client: i32, code: i32) { + // Take ownership + let client = unsafe { OwnedFd::from_raw_fd(client) }; // Make sure boot stage execution is always serialized let mut state = self.boot_stage_lock.lock().unwrap(); @@ -187,10 +198,9 @@ impl MagiskD { } state.set(BootState::PostFsDataDone); } - unsafe { libc::close(client) }; } RequestCode::LATE_START => { - unsafe { libc::close(client) }; + drop(client); if state.contains(BootState::PostFsDataDone) && !state.contains(BootState::SafeMode) { self.late_start(); @@ -198,15 +208,85 @@ impl MagiskD { } } RequestCode::BOOT_COMPLETE => { - unsafe { libc::close(client) }; + drop(client); if state.contains(BootState::PostFsDataDone) { state.set(BootState::BootComplete); self.boot_complete() } } - _ => { - unsafe { libc::close(client) }; + _ => {} + } + } + + pub fn handle_request_sync(&self, client: i32, code: i32) { + // Take ownership + let mut client = unsafe { File::from_raw_fd(client) }; + let code = RequestCode { repr: code }; + match code { + RequestCode::CHECK_VERSION => { + #[cfg(debug_assertions)] + let s = concatcp!(MAGISK_VERSION, ":MAGISK:D"); + #[cfg(not(debug_assertions))] + let s = concatcp!(MAGISK_VERSION, ":MAGISK:R"); + + client.write_encodable(s).log_ok(); } + RequestCode::CHECK_VERSION_CODE => { + client.write_pod(&MAGISK_VER_CODE).log_ok(); + } + RequestCode::START_DAEMON => { + setup_logfile(); + } + RequestCode::STOP_DAEMON => { + // Unmount all overlays + denylist_handler(-1); + + // Restore native bridge property + self.zygisk.lock().unwrap().restore_prop(); + + client.write_pod(&0).log_ok(); + + // Terminate the daemon! + exit(0); + } + _ => {} + } + } + + pub fn handle_request_async(&self, client: i32, code: i32, cred: &UCred) { + // Take ownership + let client = unsafe { OwnedFd::from_raw_fd(client) }; + let code = RequestCode { repr: code }; + match code { + RequestCode::DENYLIST => { + denylist_handler(client.into_raw_fd()); + } + RequestCode::SUPERUSER => { + self.su_daemon_handler(client, cred); + } + RequestCode::ZYGOTE_RESTART => { + info!("** zygote restarted"); + self.prune_su_access(); + scan_deny_apps(); + self.zygisk.lock().unwrap().reset(false); + } + RequestCode::SQLITE_CMD => { + self.db_exec_for_cli(client).ok(); + } + RequestCode::REMOVE_MODULES => { + let mut file = File::from(client); + let mut do_reboot: i32 = 0; + file.read_pod(&mut do_reboot).log_ok(); + remove_modules(); + file.write_pod(&0).log_ok(); + if do_reboot != 0 { + self.reboot(); + } + } + RequestCode::ZYGISK => { + self.zygisk_handler(client); + } + _ => {} } } @@ -231,7 +311,7 @@ pub fn daemon_entry() { start_log_daemon(); magisk_logging(); - info!("Magisk {} daemon started", MAGISK_FULL_VER); + info!("Magisk {MAGISK_FULL_VER} daemon started"); let is_emulator = get_prop(cstr!("ro.kernel.qemu")) == "1" || get_prop(cstr!("ro.boot.qemu")) == "1" diff --git a/native/src/core/db.rs b/native/src/core/db.rs index 42d0fd9ae..2032695bd 100644 --- a/native/src/core/db.rs +++ b/native/src/core/db.rs @@ -11,7 +11,7 @@ use num_traits::FromPrimitive; use std::ffi::c_void; use std::fs::File; use std::io::{BufReader, BufWriter}; -use std::os::fd::{FromRawFd, OwnedFd, RawFd}; +use std::os::fd::OwnedFd; use std::pin::Pin; use std::ptr; use std::ptr::NonNull; @@ -302,7 +302,7 @@ impl MagiskD { .sql_result() } - fn db_exec_for_client(&self, fd: OwnedFd) -> LoggedResult<()> { + pub fn db_exec_for_cli(&self, fd: OwnedFd) -> LoggedResult<()> { let mut file = File::from(fd); let mut reader = BufReader::new(&mut file); let sql: String = reader.read_decodable()?; @@ -328,12 +328,6 @@ impl MagiskD { pub fn set_db_setting_for_cxx(&self, key: DbEntryKey, value: i32) -> bool { self.set_db_setting(key, value).log().is_ok() } - - pub fn db_exec_for_cxx(&self, client_fd: RawFd) { - // Take ownership - let fd = unsafe { OwnedFd::from_raw_fd(client_fd) }; - self.db_exec_for_client(fd).ok(); - } } #[unsafe(export_name = "sql_exec_rs")] diff --git a/native/src/core/deny/cli.cpp b/native/src/core/deny/cli.cpp index d54c21bc4..dc7c38857 100644 --- a/native/src/core/deny/cli.cpp +++ b/native/src/core/deny/cli.cpp @@ -26,7 +26,7 @@ Actions: exit(1); } -void denylist_handler(int client, const sock_cred *cred) { +void denylist_handler(int client) { if (client < 0) { revert_unmount(); return; diff --git a/native/src/core/include/core.hpp b/native/src/core/include/core.hpp index 2e80282e9..d8921ae04 100644 --- a/native/src/core/include/core.hpp +++ b/native/src/core/include/core.hpp @@ -90,7 +90,7 @@ void init_thread_pool(); void exec_task(std::function &&task); // Daemon handlers -void denylist_handler(int client, const sock_cred *cred); +void denylist_handler(int client); // Scripting void install_apk(Utf8CStr apk); diff --git a/native/src/core/lib.rs b/native/src/core/lib.rs index 2bbf9ab3c..d920a090f 100644 --- a/native/src/core/lib.rs +++ b/native/src/core/lib.rs @@ -12,12 +12,11 @@ use base::libc; use cxx::{ExternType, type_id}; use daemon::{MagiskD, daemon_entry}; use derive::Decodable; -use logging::{android_logging, setup_logfile, zygisk_close_logd, zygisk_get_logd, zygisk_logging}; -use module::remove_modules; +use logging::{android_logging, zygisk_close_logd, zygisk_get_logd, zygisk_logging}; use mount::{find_preinit_device, revert_unmount}; use resetprop::{get_prop, resetprop_main}; use selinux::{lgetfilecon, lsetfilecon, restorecon, setfilecon}; -use socket::{recv_fd, recv_fds, send_fd, send_fds}; +use socket::{recv_fd, recv_fds, send_fd}; use std::fs::File; use std::mem::ManuallyDrop; use std::ops::DerefMut; @@ -151,6 +150,10 @@ pub mod ffi { fn switch_mnt_ns(pid: i32) -> i32; fn exec_root_shell(client: i32, pid: i32, req: &mut SuRequest, mode: MntNsMode); + // Denylist + fn denylist_handler(client: i32); + fn scan_deny_apps(); + include!("include/sqlite.hpp"); type sqlite3; @@ -171,13 +174,10 @@ pub mod ffi { fn zygisk_logging(); fn zygisk_close_logd(); fn zygisk_get_logd() -> i32; - fn setup_logfile(); fn find_preinit_device() -> String; fn revert_unmount(pid: i32); - fn remove_modules(); fn zygisk_should_load_module(flags: u32) -> bool; fn send_fd(socket: i32, fd: i32) -> bool; - fn send_fds(socket: i32, fds: &[i32]) -> bool; fn recv_fd(socket: i32) -> i32; fn recv_fds(socket: i32) -> Vec; fn write_to_fd(self: &SuRequest, fd: i32); @@ -206,23 +206,14 @@ pub mod ffi { // FFI for MagiskD extern "Rust" { type MagiskD; - fn reboot(&self); fn sdk_int(&self) -> i32; fn zygisk_enabled(&self) -> bool; fn boot_stage_handler(&self, client: i32, code: i32); - fn zygisk_handler(&self, client: i32); - fn zygisk_reset(&self, restore: bool); - fn restore_zygisk_prop(&self); - fn prune_su_access(&self); - fn su_daemon_handler(&self, client: i32, cred: &UCred); - #[cxx_name = "get_manager"] - unsafe fn get_manager_for_cxx(&self, user: i32, ptr: *mut CxxString, install: bool) -> i32; - + fn handle_request_sync(&self, client: i32, code: i32); + fn handle_request_async(&self, client: i32, code: i32, cred: &UCred); fn get_db_setting(&self, key: DbEntryKey) -> i32; #[cxx_name = "set_db_setting"] fn set_db_setting_for_cxx(&self, key: DbEntryKey, value: i32) -> bool; - #[cxx_name = "db_exec"] - fn db_exec_for_cxx(&self, client_fd: i32); #[Self = MagiskD] #[cxx_name = "Get"] diff --git a/native/src/core/package.rs b/native/src/core/package.rs index f7b674031..df6202ec1 100644 --- a/native/src/core/package.rs +++ b/native/src/core/package.rs @@ -8,13 +8,11 @@ use base::{ Utf8CString, cstr, error, fd_get_attr, warn, }; use bit_set::BitSet; -use cxx::CxxString; use std::collections::BTreeMap; use std::fs::File; use std::io; use std::io::{Cursor, Read, Seek, SeekFrom}; use std::os::fd::AsRawFd; -use std::pin::Pin; use std::time::Duration; const EOCD_MAGIC: u32 = 0x06054B50; @@ -474,19 +472,6 @@ impl MagiskD { let _ = info.get_manager(self, 0, true); } - pub unsafe fn get_manager_for_cxx(&self, user: i32, ptr: *mut CxxString, install: bool) -> i32 { - unsafe { - let mut info = self.manager_info.lock().unwrap(); - let (uid, pkg) = info.get_manager(self, user, install); - if let Some(str) = ptr.as_mut() { - let mut str = Pin::new_unchecked(str); - str.as_mut().clear(); - str.push_str(pkg); - } - uid - } - } - // app_id = app_no + AID_APP_START // app_no range: [0, 9999] pub fn get_app_no_list(&self) -> BitSet { diff --git a/native/src/core/socket.rs b/native/src/core/socket.rs index 6df6c79c1..789f5e0c4 100644 --- a/native/src/core/socket.rs +++ b/native/src/core/socket.rs @@ -236,11 +236,6 @@ pub fn send_fd(socket: RawFd, fd: RawFd) -> bool { } } -pub fn send_fds(socket: RawFd, fds: &[RawFd]) -> bool { - let mut socket = ManuallyDrop::new(unsafe { UnixStream::from_raw_fd(socket) }); - socket.send_fds(fds).log().is_ok() -} - pub fn recv_fd(socket: RawFd) -> RawFd { let mut socket = ManuallyDrop::new(unsafe { UnixStream::from_raw_fd(socket) }); socket diff --git a/native/src/core/su/daemon.rs b/native/src/core/su/daemon.rs index 1b36060e2..87675da6a 100644 --- a/native/src/core/su/daemon.rs +++ b/native/src/core/su/daemon.rs @@ -6,11 +6,14 @@ use crate::db::{DbSettings, MultiuserMode, RootAccess}; use crate::ffi::{SuPolicy, SuRequest, exec_root_shell}; use crate::socket::IpcRead; use base::{LoggedResult, ResultExt, WriteExt, debug, error, exit_on_error, libc, warn}; -use std::os::fd::{FromRawFd, IntoRawFd}; +use std::os::fd::{IntoRawFd, OwnedFd}; use std::os::unix::net::UnixStream; use std::sync::{Arc, Mutex}; use std::time::{Duration, Instant}; +#[allow(unused_imports)] +use std::os::fd::AsRawFd; + const DEFAULT_SHELL: &str = "/system/bin/sh"; impl Default for SuRequest { @@ -111,14 +114,16 @@ impl AccessInfo { } impl MagiskD { - pub fn su_daemon_handler(&self, client: i32, cred: &UCred) { + pub fn su_daemon_handler(&self, client: OwnedFd, cred: &UCred) { let cred = cred.0; debug!( "su: request from uid=[{}], pid=[{}], client=[{}]", - cred.uid, cred.pid, client + cred.uid, + cred.pid, + client.as_raw_fd() ); - let mut client = unsafe { UnixStream::from_raw_fd(client) }; + let mut client = UnixStream::from(client); let mut req = match client.read_decodable::().log() { Ok(req) => req, diff --git a/native/src/core/zygisk/daemon.rs b/native/src/core/zygisk/daemon.rs index fe5ef5905..a469b345b 100644 --- a/native/src/core/zygisk/daemon.rs +++ b/native/src/core/zygisk/daemon.rs @@ -9,7 +9,7 @@ use base::{ libc, log_err, raw_cstr, warn, }; use std::fmt::Write; -use std::os::fd::{AsRawFd, FromRawFd, RawFd}; +use std::os::fd::{AsRawFd, OwnedFd, RawFd}; use std::os::unix::net::UnixStream; use std::ptr; use std::sync::atomic::Ordering; @@ -146,7 +146,7 @@ impl ZygiskState { } } - fn restore_prop(&mut self) { + pub fn restore_prop(&mut self) { let mut orig = "0".to_string(); if self.lib_name.len() > ZYGISKLDR.len() { orig = self.lib_name[ZYGISKLDR.len()..].to_string(); @@ -157,8 +157,8 @@ impl ZygiskState { } impl MagiskD { - pub fn zygisk_handler(&self, client: i32) { - let mut client = unsafe { UnixStream::from_raw_fd(client) }; + pub fn zygisk_handler(&self, client: OwnedFd) { + let mut client = UnixStream::from(client); let _: LoggedResult<()> = try { let code = ZygiskRequest { repr: client.read_decodable()?, @@ -255,12 +255,4 @@ impl MagiskD { pub fn zygisk_enabled(&self) -> bool { self.zygisk_enabled.load(Ordering::Acquire) } - - pub fn zygisk_reset(&self, restore: bool) { - self.zygisk.lock().unwrap().reset(restore); - } - - pub fn restore_zygisk_prop(&self) { - self.zygisk.lock().unwrap().restore_prop(); - } }