Files
Magisk/native/src/core/lib.rs
2025-09-15 14:25:18 -07:00

234 lines
5.8 KiB
Rust

#![feature(try_blocks)]
#![feature(let_chains)]
#![feature(fn_traits)]
#![feature(unix_socket_ancillary_data)]
#![feature(unix_socket_peek)]
#![feature(default_field_values)]
#![feature(peer_credentials_unix_socket)]
#![allow(clippy::missing_safety_doc)]
use crate::ffi::SuRequest;
use crate::socket::Encodable;
use daemon::{MagiskD, daemon_entry};
use derive::Decodable;
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};
use std::fs::File;
use std::mem::ManuallyDrop;
use std::ops::DerefMut;
use std::os::fd::FromRawFd;
use su::{get_pty_num, pump_tty};
use zygisk::zygisk_should_load_module;
mod bootstages;
#[path = "../include/consts.rs"]
mod consts;
mod daemon;
mod db;
mod logging;
mod module;
mod mount;
mod package;
mod resetprop;
mod selinux;
mod socket;
mod su;
mod thread;
mod zygisk;
#[allow(clippy::needless_lifetimes)]
#[cxx::bridge]
pub mod ffi {
#[repr(i32)]
enum RequestCode {
START_DAEMON,
CHECK_VERSION,
CHECK_VERSION_CODE,
STOP_DAEMON,
_SYNC_BARRIER_,
SUPERUSER,
ZYGOTE_RESTART,
DENYLIST,
SQLITE_CMD,
REMOVE_MODULES,
ZYGISK,
_STAGE_BARRIER_,
POST_FS_DATA,
LATE_START,
BOOT_COMPLETE,
END,
}
#[repr(i32)]
enum RespondCode {
ERROR = -1,
OK = 0,
ROOT_REQUIRED,
ACCESS_DENIED,
END,
}
enum DbEntryKey {
RootAccess,
SuMultiuserMode,
SuMntNs,
DenylistConfig,
ZygiskConfig,
BootloopCount,
SuManager,
}
#[repr(i32)]
enum MntNsMode {
Global,
Requester,
Isolate,
}
#[repr(i32)]
enum SuPolicy {
Query,
Deny,
Allow,
Restrict,
}
struct ModuleInfo {
name: String,
z32: i32,
z64: i32,
}
#[repr(i32)]
enum ZygiskRequest {
GetInfo,
ConnectCompanion,
GetModDir,
}
#[repr(u32)]
enum ZygiskStateFlags {
ProcessGrantedRoot = 0x00000001,
ProcessOnDenyList = 0x00000002,
DenyListEnforced = 0x40000000,
ProcessIsMagiskApp = 0x80000000,
}
#[derive(Decodable)]
struct SuRequest {
target_uid: i32,
target_pid: i32,
login: bool,
keep_env: bool,
drop_cap: bool,
shell: String,
command: String,
context: String,
gids: Vec<u32>,
}
unsafe extern "C++" {
#[cxx_name = "Utf8CStr"]
type Utf8CStrRef<'a> = base::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 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 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);
// Denylist
fn denylist_handler(client: i32);
fn scan_deny_apps();
include!("include/sqlite.hpp");
type 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 android_logging();
fn zygisk_logging();
fn zygisk_close_logd();
fn zygisk_get_logd() -> i32;
fn find_preinit_device() -> String;
fn revert_unmount(pid: i32);
fn zygisk_should_load_module(flags: u32) -> bool;
fn send_fd(socket: i32, fd: i32) -> bool;
fn recv_fd(socket: i32) -> i32;
fn recv_fds(socket: i32) -> Vec<i32>;
fn write_to_fd(self: &SuRequest, fd: i32);
fn pump_tty(ptmx: i32, pump_stdin: bool);
fn get_pty_num(fd: i32) -> i32;
fn restorecon();
fn lgetfilecon(path: Utf8CStrRef, con: &mut [u8]) -> bool;
fn setfilecon(path: Utf8CStrRef, con: Utf8CStrRef) -> bool;
fn lsetfilecon(path: Utf8CStrRef, con: Utf8CStrRef) -> bool;
fn get_prop(name: Utf8CStrRef) -> String;
unsafe fn resetprop_main(argc: i32, argv: *mut *mut c_char) -> i32;
fn daemon_entry();
}
// Default constructors
extern "Rust" {
#[Self = SuRequest]
#[cxx_name = "New"]
fn default() -> SuRequest;
}
// FFI for MagiskD
extern "Rust" {
type MagiskD;
fn sdk_int(&self) -> i32;
fn zygisk_enabled(&self) -> bool;
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;
#[Self = MagiskD]
#[cxx_name = "Get"]
fn get() -> &'static MagiskD;
}
}
impl SuRequest {
fn write_to_fd(&self, fd: i32) {
unsafe {
let mut w = ManuallyDrop::new(File::from_raw_fd(fd));
self.encode(w.deref_mut()).ok();
}
}
}