Reduce FFI across C++/Rust

This commit is contained in:
topjohnwu
2025-09-02 11:11:12 -07:00
committed by John Wu
parent 675b5f9565
commit bd657c354c
10 changed files with 127 additions and 158 deletions

View File

@@ -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<int> events;
vector<owned_fd> 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)) {

View File

@@ -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"

View File

@@ -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")]

View File

@@ -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;

View File

@@ -90,7 +90,7 @@ void init_thread_pool();
void exec_task(std::function<void()> &&task);
// Daemon handlers
void denylist_handler(int client, const sock_cred *cred);
void denylist_handler(int client);
// Scripting
void install_apk(Utf8CStr apk);

View File

@@ -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<i32>;
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"]

View File

@@ -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 {

View File

@@ -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

View File

@@ -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::<SuRequest>().log() {
Ok(req) => req,

View File

@@ -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();
}
}