Implement su_daemon in Rust

This commit is contained in:
topjohnwu
2025-02-02 04:30:16 +08:00
committed by John Wu
parent ab86732c89
commit a786801141
15 changed files with 857 additions and 710 deletions

View File

@@ -6,12 +6,20 @@
#![feature(unix_socket_peek)]
#![allow(clippy::missing_safety_doc)]
use base::Utf8CStr;
use crate::ffi::SuRequest;
use crate::socket::Encodable;
use base::{libc, Utf8CStr};
use cxx::{type_id, ExternType};
use daemon::{daemon_entry, MagiskD};
use derive::Decodable;
use logging::{android_logging, setup_logfile, zygisk_close_logd, zygisk_get_logd, zygisk_logging};
use mount::{clean_mounts, find_preinit_device, revert_unmount};
use resetprop::{persist_delete_prop, persist_get_prop, persist_get_props, persist_set_prop};
use socket::{recv_fd, recv_fds, send_fd, send_fds};
use std::fs::File;
use std::mem::ManuallyDrop;
use std::ops::DerefMut;
use std::os::fd::FromRawFd;
use zygisk::zygisk_should_load_module;
#[path = "../include/consts.rs"]
@@ -53,44 +61,6 @@ pub mod ffi {
END,
}
extern "C++" {
include!("include/resetprop.hpp");
#[cxx_name = "prop_cb"]
type PropCb;
unsafe fn get_prop_rs(name: *const c_char, persist: bool) -> String;
unsafe fn prop_cb_exec(
cb: Pin<&mut PropCb>,
name: *const c_char,
value: *const c_char,
serial: u32,
);
}
unsafe extern "C++" {
#[namespace = "rust"]
#[cxx_name = "Utf8CStr"]
type Utf8CStrRef<'a> = base::ffi::Utf8CStrRef<'a>;
include!("include/core.hpp");
#[cxx_name = "get_magisk_tmp_rs"]
fn get_magisk_tmp() -> Utf8CStrRef<'static>;
#[cxx_name = "resolve_preinit_dir_rs"]
fn resolve_preinit_dir(base_dir: Utf8CStrRef) -> String;
fn setup_magisk_env() -> bool;
fn check_key_combo() -> bool;
fn disable_modules();
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 update_deny_flags(uid: i32, process: &str, flags: &mut u32);
fn initialize_denylist();
fn restore_zygisk_prop();
fn switch_mnt_ns(pid: i32) -> i32;
}
enum DbEntryKey {
RootAccess,
SuMultiuserMode,
@@ -167,27 +137,86 @@ pub mod ffi {
ProcessIsMagiskApp = 0x80000000,
}
#[derive(Decodable)]
struct SuRequest {
target_uid: i32,
target_pid: i32,
login: bool,
keep_env: bool,
shell: String,
command: String,
context: String,
gids: Vec<u32>,
}
struct SuAppRequest<'a> {
uid: i32,
pid: i32,
eval_uid: i32,
mgr_pkg: &'a str,
mgr_uid: i32,
request: &'a SuRequest,
}
extern "C++" {
include!("include/resetprop.hpp");
#[cxx_name = "prop_cb"]
type PropCb;
unsafe fn get_prop_rs(name: *const c_char, persist: bool) -> String;
unsafe fn prop_cb_exec(
cb: Pin<&mut PropCb>,
name: *const c_char,
value: *const c_char,
serial: u32,
);
}
unsafe extern "C++" {
#[namespace = "rust"]
#[cxx_name = "Utf8CStr"]
type Utf8CStrRef<'a> = base::ffi::Utf8CStrRef<'a>;
#[cxx_name = "ucred"]
type UCred = crate::UCred;
include!("include/core.hpp");
#[cxx_name = "get_magisk_tmp_rs"]
fn get_magisk_tmp() -> Utf8CStrRef<'static>;
#[cxx_name = "resolve_preinit_dir_rs"]
fn resolve_preinit_dir(base_dir: Utf8CStrRef) -> String;
fn setup_magisk_env() -> bool;
fn check_key_combo() -> bool;
fn disable_modules();
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 update_deny_flags(uid: i32, process: &str, flags: &mut u32);
fn initialize_denylist();
fn restore_zygisk_prop();
fn switch_mnt_ns(pid: i32) -> i32;
fn app_request(req: &SuAppRequest) -> i32;
fn app_notify(req: &SuAppRequest, policy: SuPolicy);
fn app_log(req: &SuAppRequest, policy: SuPolicy, notify: bool);
fn exec_root_shell(client: i32, pid: i32, req: &mut SuRequest, mode: MntNsMode);
include!("include/sqlite.hpp");
fn sqlite3_errstr(code: i32) -> *const c_char;
type sqlite3;
fn open_and_init_db() -> *mut sqlite3;
type DbValues;
type DbStatement;
fn sqlite3_errstr(code: i32) -> *const c_char;
fn open_and_init_db() -> *mut sqlite3;
fn get_int(self: &DbValues, index: i32) -> i32;
#[cxx_name = "get_str"]
fn get_text(self: &DbValues, index: i32) -> &str;
fn bind_text(self: Pin<&mut DbStatement>, index: i32, val: &str) -> i32;
fn bind_int64(self: Pin<&mut DbStatement>, index: i32, val: i64) -> i32;
}
extern "Rust" {
fn rust_test_entry();
fn android_logging();
fn zygisk_logging();
fn zygisk_close_logd();
@@ -205,11 +234,27 @@ pub mod ffi {
fn send_fds(socket: i32, fds: &[i32]) -> bool;
fn recv_fd(socket: i32) -> i32;
fn recv_fds(socket: i32) -> Vec<i32>;
unsafe fn write_to_fd(self: &SuRequest, fd: i32);
#[namespace = "rust"]
fn daemon_entry();
}
// Default constructors
extern "Rust" {
#[Self = DbSettings]
#[cxx_name = "New"]
fn default() -> DbSettings;
#[Self = RootSettings]
#[cxx_name = "New"]
fn default() -> RootSettings;
#[Self = SuRequest]
#[cxx_name = "New"]
fn default() -> SuRequest;
}
// FFI for MagiskD
extern "Rust" {
type MagiskD;
@@ -220,6 +265,7 @@ pub mod ffi {
fn zygisk_handler(&self, client: i32);
fn zygisk_reset(&self, restore: bool);
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 set_module_list(&self, module_list: Vec<ModuleInfo>);
@@ -234,14 +280,6 @@ pub mod ffi {
#[cxx_name = "get_root_settings"]
fn get_root_settings_for_cxx(&self, uid: i32, settings: &mut RootSettings) -> bool;
#[Self = DbSettings]
#[cxx_name = "New"]
fn default() -> DbSettings;
#[Self = RootSettings]
#[cxx_name = "New"]
fn default() -> RootSettings;
#[Self = MagiskD]
#[cxx_name = "Get"]
fn get() -> &'static MagiskD;
@@ -253,7 +291,20 @@ pub mod ffi {
}
}
fn rust_test_entry() {}
#[repr(transparent)]
pub struct UCred(pub libc::ucred);
unsafe impl ExternType for UCred {
type Id = type_id!("ucred");
type Kind = cxx::kind::Trivial;
}
impl SuRequest {
unsafe fn write_to_fd(&self, fd: i32) {
let mut w = ManuallyDrop::new(File::from_raw_fd(fd));
self.encode(w.deref_mut()).ok();
}
}
pub fn get_prop(name: &Utf8CStr, persist: bool) -> String {
unsafe { ffi::get_prop_rs(name.as_ptr(), persist) }