mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-11-28 20:45:24 +00:00
C++/Rust 2 way binding for MagiskD
This commit is contained in:
parent
6c0966b795
commit
8d5b9e5329
@ -325,3 +325,9 @@ void exec_command_async(Args &&...args) {
|
|||||||
};
|
};
|
||||||
exec_command(exec);
|
exec_command(exec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
constexpr auto operator+(T e) noexcept ->
|
||||||
|
std::enable_if_t<std::is_enum<T>::value, std::underlying_type_t<T>> {
|
||||||
|
return static_cast<std::underlying_type_t<T>>(e);
|
||||||
|
}
|
||||||
|
@ -14,17 +14,6 @@
|
|||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
// Boot stage state
|
|
||||||
enum : int {
|
|
||||||
FLAG_NONE = 0,
|
|
||||||
FLAG_POST_FS_DATA_DONE = (1 << 0),
|
|
||||||
FLAG_LATE_START_DONE = (1 << 1),
|
|
||||||
FLAG_BOOT_COMPLETE = (1 << 2),
|
|
||||||
FLAG_SAFE_MODE = (1 << 3),
|
|
||||||
};
|
|
||||||
|
|
||||||
static int boot_state = FLAG_NONE;
|
|
||||||
|
|
||||||
bool zygisk_enabled = false;
|
bool zygisk_enabled = false;
|
||||||
|
|
||||||
/*********
|
/*********
|
||||||
@ -243,31 +232,6 @@ static bool magisk_env() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool check_data() {
|
|
||||||
bool mnt = false;
|
|
||||||
file_readline("/proc/mounts", [&](string_view s) {
|
|
||||||
if (str_contains(s, " /data ") && !str_contains(s, "tmpfs")) {
|
|
||||||
mnt = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
if (!mnt)
|
|
||||||
return false;
|
|
||||||
auto crypto = get_prop("ro.crypto.state");
|
|
||||||
if (!crypto.empty()) {
|
|
||||||
if (crypto != "encrypted") {
|
|
||||||
// Unencrypted, we can directly access data
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
// Encrypted, check whether vold is started
|
|
||||||
return !get_prop("init.svc.vold").empty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// ro.crypto.state is not set, assume it's unencrypted
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void unlock_blocks() {
|
void unlock_blocks() {
|
||||||
int fd, dev, OFF = 0;
|
int fd, dev, OFF = 0;
|
||||||
|
|
||||||
@ -341,10 +305,7 @@ static bool check_key_combo() {
|
|||||||
extern int disable_deny();
|
extern int disable_deny();
|
||||||
|
|
||||||
void MagiskD::post_fs_data() const {
|
void MagiskD::post_fs_data() const {
|
||||||
if (!check_data())
|
as_rust().setup_logfile();
|
||||||
return;
|
|
||||||
|
|
||||||
setup_logfile();
|
|
||||||
|
|
||||||
LOGI("** post-fs-data mode running\n");
|
LOGI("** post-fs-data mode running\n");
|
||||||
|
|
||||||
@ -364,7 +325,7 @@ void MagiskD::post_fs_data() const {
|
|||||||
|
|
||||||
if (get_prop("persist.sys.safemode", true) == "1" ||
|
if (get_prop("persist.sys.safemode", true) == "1" ||
|
||||||
get_prop("ro.sys.safemode") == "1" || check_key_combo()) {
|
get_prop("ro.sys.safemode") == "1" || check_key_combo()) {
|
||||||
boot_state |= FLAG_SAFE_MODE;
|
as_rust().enable_safe_mode();
|
||||||
// Disable all modules and denylist so next boot will be clean
|
// Disable all modules and denylist so next boot will be clean
|
||||||
disable_modules();
|
disable_modules();
|
||||||
disable_deny();
|
disable_deny();
|
||||||
@ -380,23 +341,19 @@ void MagiskD::post_fs_data() const {
|
|||||||
early_abort:
|
early_abort:
|
||||||
// We still do magic mount because root itself might need it
|
// We still do magic mount because root itself might need it
|
||||||
load_modules();
|
load_modules();
|
||||||
boot_state |= FLAG_POST_FS_DATA_DONE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MagiskD::late_start() const {
|
void MagiskD::late_start() const {
|
||||||
setup_logfile();
|
as_rust().setup_logfile();
|
||||||
|
|
||||||
LOGI("** late_start service mode running\n");
|
LOGI("** late_start service mode running\n");
|
||||||
|
|
||||||
exec_common_scripts("service");
|
exec_common_scripts("service");
|
||||||
exec_module_scripts("service");
|
exec_module_scripts("service");
|
||||||
|
|
||||||
boot_state |= FLAG_LATE_START_DONE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MagiskD::boot_complete() const {
|
void MagiskD::boot_complete() const {
|
||||||
boot_state |= FLAG_BOOT_COMPLETE;
|
as_rust().setup_logfile();
|
||||||
setup_logfile();
|
|
||||||
|
|
||||||
LOGI("** boot-complete triggered\n");
|
LOGI("** boot-complete triggered\n");
|
||||||
|
|
||||||
@ -410,30 +367,3 @@ void MagiskD::boot_complete() const {
|
|||||||
|
|
||||||
reset_zygisk(true);
|
reset_zygisk(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void boot_stage_handler(int client, int code) {
|
|
||||||
// Make sure boot stage execution is always serialized
|
|
||||||
static pthread_mutex_t stage_lock = PTHREAD_MUTEX_INITIALIZER;
|
|
||||||
mutex_guard lock(stage_lock);
|
|
||||||
MagiskD daemon;
|
|
||||||
|
|
||||||
switch (code) {
|
|
||||||
case MainRequest::POST_FS_DATA:
|
|
||||||
if ((boot_state & FLAG_POST_FS_DATA_DONE) == 0)
|
|
||||||
daemon.post_fs_data();
|
|
||||||
close(client);
|
|
||||||
break;
|
|
||||||
case MainRequest::LATE_START:
|
|
||||||
close(client);
|
|
||||||
if ((boot_state & FLAG_POST_FS_DATA_DONE) && (boot_state & FLAG_SAFE_MODE) == 0)
|
|
||||||
daemon.late_start();
|
|
||||||
break;
|
|
||||||
case MainRequest::BOOT_COMPLETE:
|
|
||||||
close(client);
|
|
||||||
if ((boot_state & FLAG_SAFE_MODE) == 0)
|
|
||||||
daemon.boot_complete();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
__builtin_unreachable();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -128,8 +128,20 @@ static void poll_ctrl_handler(pollfd *pfd) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const MagiskD &MagiskD::get() {
|
||||||
|
return *reinterpret_cast<const MagiskD*>(&rust::get_magiskd());
|
||||||
|
}
|
||||||
|
|
||||||
|
const rust::MagiskD &MagiskD::as_rust() const {
|
||||||
|
return *reinterpret_cast<const rust::MagiskD*>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MagiskD::boot_stage_handler(int client, int code) const {
|
||||||
|
as_rust().boot_stage_handler(client, code);
|
||||||
|
}
|
||||||
|
|
||||||
void MagiskD::reboot() const {
|
void MagiskD::reboot() const {
|
||||||
if (is_recovery())
|
if (as_rust().is_recovery())
|
||||||
exec_command_sync("/system/bin/reboot", "recovery");
|
exec_command_sync("/system/bin/reboot", "recovery");
|
||||||
else
|
else
|
||||||
exec_command_sync("/system/bin/reboot");
|
exec_command_sync("/system/bin/reboot");
|
||||||
@ -137,34 +149,33 @@ void MagiskD::reboot() const {
|
|||||||
|
|
||||||
static void handle_request_async(int client, int code, const sock_cred &cred) {
|
static void handle_request_async(int client, int code, const sock_cred &cred) {
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case MainRequest::DENYLIST:
|
case +RequestCode::DENYLIST:
|
||||||
denylist_handler(client, &cred);
|
denylist_handler(client, &cred);
|
||||||
break;
|
break;
|
||||||
case MainRequest::SUPERUSER:
|
case +RequestCode::SUPERUSER:
|
||||||
su_daemon_handler(client, &cred);
|
su_daemon_handler(client, &cred);
|
||||||
break;
|
break;
|
||||||
case MainRequest::ZYGOTE_RESTART:
|
case +RequestCode::ZYGOTE_RESTART:
|
||||||
LOGI("** zygote restarted\n");
|
LOGI("** zygote restarted\n");
|
||||||
pkg_xml_ino = 0;
|
pkg_xml_ino = 0;
|
||||||
prune_su_access();
|
prune_su_access();
|
||||||
reset_zygisk(false);
|
reset_zygisk(false);
|
||||||
close(client);
|
close(client);
|
||||||
break;
|
break;
|
||||||
case MainRequest::SQLITE_CMD:
|
case +RequestCode::SQLITE_CMD:
|
||||||
exec_sql(client);
|
exec_sql(client);
|
||||||
break;
|
break;
|
||||||
case MainRequest::REMOVE_MODULES: {
|
case +RequestCode::REMOVE_MODULES: {
|
||||||
int do_reboot = read_int(client);
|
int do_reboot = read_int(client);
|
||||||
remove_modules();
|
remove_modules();
|
||||||
write_int(client, 0);
|
write_int(client, 0);
|
||||||
close(client);
|
close(client);
|
||||||
if (do_reboot) {
|
if (do_reboot) {
|
||||||
MagiskD daemon;
|
MagiskD::get().reboot();
|
||||||
daemon.reboot();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MainRequest::ZYGISK:
|
case +RequestCode::ZYGISK:
|
||||||
zygisk_handler(client, &cred);
|
zygisk_handler(client, &cred);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -174,20 +185,20 @@ static void handle_request_async(int client, int code, const sock_cred &cred) {
|
|||||||
|
|
||||||
static void handle_request_sync(int client, int code) {
|
static void handle_request_sync(int client, int code) {
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case MainRequest::CHECK_VERSION:
|
case +RequestCode::CHECK_VERSION:
|
||||||
#if MAGISK_DEBUG
|
#if MAGISK_DEBUG
|
||||||
write_string(client, MAGISK_VERSION ":MAGISK:D");
|
write_string(client, MAGISK_VERSION ":MAGISK:D");
|
||||||
#else
|
#else
|
||||||
write_string(client, MAGISK_VERSION ":MAGISK:R");
|
write_string(client, MAGISK_VERSION ":MAGISK:R");
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case MainRequest::CHECK_VERSION_CODE:
|
case +RequestCode::CHECK_VERSION_CODE:
|
||||||
write_int(client, MAGISK_VER_CODE);
|
write_int(client, MAGISK_VER_CODE);
|
||||||
break;
|
break;
|
||||||
case MainRequest::START_DAEMON:
|
case +RequestCode::START_DAEMON:
|
||||||
rust::get_magiskd().setup_logfile();
|
rust::get_magiskd().setup_logfile();
|
||||||
break;
|
break;
|
||||||
case MainRequest::STOP_DAEMON: {
|
case +RequestCode::STOP_DAEMON: {
|
||||||
// Unmount all overlays
|
// Unmount all overlays
|
||||||
denylist_handler(-1, nullptr);
|
denylist_handler(-1, nullptr);
|
||||||
|
|
||||||
@ -236,42 +247,42 @@ static void handle_request(pollfd *pfd) {
|
|||||||
|
|
||||||
if (!is_root && !is_zygote && !is_client(cred.pid)) {
|
if (!is_root && !is_zygote && !is_client(cred.pid)) {
|
||||||
// Unsupported client state
|
// Unsupported client state
|
||||||
write_int(client, MainResponse::ACCESS_DENIED);
|
write_int(client, +RespondCode::ACCESS_DENIED);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
code = read_int(client);
|
code = read_int(client);
|
||||||
if (code < 0 || code >= MainRequest::END ||
|
if (code < 0 || code >= +RequestCode::END ||
|
||||||
code == MainRequest::_SYNC_BARRIER_ ||
|
code == +RequestCode::_SYNC_BARRIER_ ||
|
||||||
code == MainRequest::_STAGE_BARRIER_) {
|
code == +RequestCode::_STAGE_BARRIER_) {
|
||||||
// Unknown request code
|
// Unknown request code
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check client permissions
|
// Check client permissions
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case MainRequest::POST_FS_DATA:
|
case +RequestCode::POST_FS_DATA:
|
||||||
case MainRequest::LATE_START:
|
case +RequestCode::LATE_START:
|
||||||
case MainRequest::BOOT_COMPLETE:
|
case +RequestCode::BOOT_COMPLETE:
|
||||||
case MainRequest::ZYGOTE_RESTART:
|
case +RequestCode::ZYGOTE_RESTART:
|
||||||
case MainRequest::SQLITE_CMD:
|
case +RequestCode::SQLITE_CMD:
|
||||||
case MainRequest::DENYLIST:
|
case +RequestCode::DENYLIST:
|
||||||
case MainRequest::STOP_DAEMON:
|
case +RequestCode::STOP_DAEMON:
|
||||||
if (!is_root) {
|
if (!is_root) {
|
||||||
write_int(client, MainResponse::ROOT_REQUIRED);
|
write_int(client, +RespondCode::ROOT_REQUIRED);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MainRequest::REMOVE_MODULES:
|
case +RequestCode::REMOVE_MODULES:
|
||||||
if (!is_root && cred.uid != AID_SHELL) {
|
if (!is_root && cred.uid != AID_SHELL) {
|
||||||
write_int(client, MainResponse::ACCESS_DENIED);
|
write_int(client, +RespondCode::ACCESS_DENIED);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MainRequest::ZYGISK:
|
case +RequestCode::ZYGISK:
|
||||||
if (!is_zygote) {
|
if (!is_zygote) {
|
||||||
// Invalid client context
|
// Invalid client context
|
||||||
write_int(client, MainResponse::ACCESS_DENIED);
|
write_int(client, +RespondCode::ACCESS_DENIED);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -279,14 +290,16 @@ static void handle_request(pollfd *pfd) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
write_int(client, MainResponse::OK);
|
write_int(client, +RespondCode::OK);
|
||||||
|
|
||||||
if (code < MainRequest::_SYNC_BARRIER_) {
|
if (code < +RequestCode::_SYNC_BARRIER_) {
|
||||||
handle_request_sync(client, code);
|
handle_request_sync(client, code);
|
||||||
} else if (code < MainRequest::_STAGE_BARRIER_) {
|
} else if (code < +RequestCode::_STAGE_BARRIER_) {
|
||||||
exec_task([=, fd = client.release()] { handle_request_async(fd, code, cred); });
|
exec_task([=, fd = client.release()] { handle_request_async(fd, code, cred); });
|
||||||
} else {
|
} else {
|
||||||
exec_task([=, fd = client.release()] { boot_stage_handler(fd, code); });
|
exec_task([=, fd = client.release()] {
|
||||||
|
MagiskD::get().boot_stage_handler(fd, code);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -460,20 +473,20 @@ int connect_daemon(int req, bool create) {
|
|||||||
}
|
}
|
||||||
write_int(fd, req);
|
write_int(fd, req);
|
||||||
int res = read_int(fd);
|
int res = read_int(fd);
|
||||||
if (res < MainResponse::ERROR || res >= MainResponse::END)
|
if (res < +RespondCode::ERROR || res >= +RespondCode::END)
|
||||||
res = MainResponse::ERROR;
|
res = +RespondCode::ERROR;
|
||||||
switch (res) {
|
switch (res) {
|
||||||
case MainResponse::OK:
|
case +RespondCode::OK:
|
||||||
break;
|
break;
|
||||||
case MainResponse::ERROR:
|
case +RespondCode::ERROR:
|
||||||
LOGE("Daemon error\n");
|
LOGE("Daemon error\n");
|
||||||
close(fd);
|
close(fd);
|
||||||
return -1;
|
return -1;
|
||||||
case MainResponse::ROOT_REQUIRED:
|
case +RespondCode::ROOT_REQUIRED:
|
||||||
LOGE("Root is required for this operation\n");
|
LOGE("Root is required for this operation\n");
|
||||||
close(fd);
|
close(fd);
|
||||||
return -1;
|
return -1;
|
||||||
case MainResponse::ACCESS_DENIED:
|
case +RespondCode::ACCESS_DENIED:
|
||||||
LOGE("Access denied\n");
|
LOGE("Access denied\n");
|
||||||
close(fd);
|
close(fd);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1,23 +1,51 @@
|
|||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io;
|
|
||||||
use std::io::BufReader;
|
use std::io::BufReader;
|
||||||
|
use std::sync::atomic::{AtomicU32, Ordering};
|
||||||
use std::sync::{Mutex, OnceLock};
|
use std::sync::{Mutex, OnceLock};
|
||||||
|
use std::{io, mem};
|
||||||
|
|
||||||
use base::libc::{O_CLOEXEC, O_RDONLY};
|
use base::libc::{O_CLOEXEC, O_RDONLY};
|
||||||
use base::{
|
use base::{
|
||||||
cstr, BufReadExt, Directory, FsPathBuf, ResultExt, Utf8CStr, Utf8CStrBuf, Utf8CStrBufArr,
|
cstr, libc, open_fd, BufReadExt, Directory, FsPathBuf, ResultExt, Utf8CStr, Utf8CStrBuf,
|
||||||
Utf8CStrBufRef, WalkResult,
|
Utf8CStrBufArr, Utf8CStrBufRef, WalkResult,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::ffi::{CxxMagiskD, RequestCode};
|
||||||
use crate::logging::magisk_logging;
|
use crate::logging::magisk_logging;
|
||||||
use crate::{get_prop, MAIN_CONFIG};
|
use crate::{get_prop, MAIN_CONFIG};
|
||||||
|
|
||||||
// Global magiskd singleton
|
// Global magiskd singleton
|
||||||
pub static MAGISKD: OnceLock<MagiskD> = OnceLock::new();
|
pub static MAGISKD: OnceLock<MagiskD> = OnceLock::new();
|
||||||
|
|
||||||
|
#[repr(u32)]
|
||||||
|
enum BootState {
|
||||||
|
PostFsDataDone = (1 << 0),
|
||||||
|
LateStartDone = (1 << 1),
|
||||||
|
BootComplete = (1 << 2),
|
||||||
|
SafeMode = (1 << 3),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
#[repr(transparent)]
|
||||||
|
struct BootStateFlags(AtomicU32);
|
||||||
|
|
||||||
|
impl BootStateFlags {
|
||||||
|
fn contains(&self, stage: BootState) -> bool {
|
||||||
|
let v = self.0.load(Ordering::Relaxed);
|
||||||
|
(v & stage as u32) != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set(&self, stage: BootState) {
|
||||||
|
let v = self.0.load(Ordering::Relaxed);
|
||||||
|
self.0.store(v | stage as u32, Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct MagiskD {
|
pub struct MagiskD {
|
||||||
pub logd: Mutex<Option<File>>,
|
pub logd: Mutex<Option<File>>,
|
||||||
|
boot_stage_lock: Mutex<()>,
|
||||||
|
boot_state_flags: BootStateFlags,
|
||||||
is_emulator: bool,
|
is_emulator: bool,
|
||||||
is_recovery: bool,
|
is_recovery: bool,
|
||||||
}
|
}
|
||||||
@ -30,6 +58,50 @@ impl MagiskD {
|
|||||||
pub fn is_recovery(&self) -> bool {
|
pub fn is_recovery(&self) -> bool {
|
||||||
self.is_recovery
|
self.is_recovery
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn enable_safe_mode(&self) {
|
||||||
|
self.boot_state_flags.set(BootState::SafeMode)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn boot_stage_handler(&self, client: i32, code: i32) {
|
||||||
|
// Make sure boot stage execution is always serialized
|
||||||
|
let _guard = self.boot_stage_lock.lock().unwrap();
|
||||||
|
|
||||||
|
let code = RequestCode { repr: code };
|
||||||
|
match code {
|
||||||
|
RequestCode::POST_FS_DATA => {
|
||||||
|
if check_data() && !self.boot_state_flags.contains(BootState::PostFsDataDone) {
|
||||||
|
self.as_cxx().post_fs_data();
|
||||||
|
self.boot_state_flags.set(BootState::PostFsDataDone);
|
||||||
|
}
|
||||||
|
unsafe { libc::close(client) };
|
||||||
|
}
|
||||||
|
RequestCode::LATE_START => {
|
||||||
|
unsafe { libc::close(client) };
|
||||||
|
if self.boot_state_flags.contains(BootState::PostFsDataDone)
|
||||||
|
&& !self.boot_state_flags.contains(BootState::SafeMode)
|
||||||
|
{
|
||||||
|
self.as_cxx().late_start();
|
||||||
|
self.boot_state_flags.set(BootState::LateStartDone);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RequestCode::BOOT_COMPLETE => {
|
||||||
|
unsafe { libc::close(client) };
|
||||||
|
if !self.boot_state_flags.contains(BootState::SafeMode) {
|
||||||
|
self.boot_state_flags.set(BootState::BootComplete);
|
||||||
|
self.as_cxx().boot_complete()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unsafe { libc::close(client) };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn as_cxx(&self) -> &CxxMagiskD {
|
||||||
|
unsafe { mem::transmute(self) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mod cxx_extern {
|
mod cxx_extern {
|
||||||
@ -69,15 +141,46 @@ pub fn daemon_entry() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let magiskd = MagiskD {
|
let magiskd = MagiskD {
|
||||||
logd: Default::default(),
|
|
||||||
is_emulator,
|
is_emulator,
|
||||||
is_recovery,
|
is_recovery,
|
||||||
|
..Default::default()
|
||||||
};
|
};
|
||||||
magiskd.start_log_daemon();
|
magiskd.start_log_daemon();
|
||||||
MAGISKD.set(magiskd).ok();
|
MAGISKD.set(magiskd).ok();
|
||||||
magisk_logging();
|
magisk_logging();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_data() -> bool {
|
||||||
|
if let Ok(fd) = open_fd!(cstr!("/proc/mounts"), O_RDONLY | O_CLOEXEC) {
|
||||||
|
let file = File::from(fd);
|
||||||
|
let mut mnt = false;
|
||||||
|
BufReader::new(file).foreach_lines(|line| {
|
||||||
|
if line.contains(" /data ") && !line.contains("tmpfs") {
|
||||||
|
mnt = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
true
|
||||||
|
});
|
||||||
|
if !mnt {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
let crypto = get_prop(cstr!("ro.crypto.state"), false);
|
||||||
|
return if !crypto.is_empty() {
|
||||||
|
if crypto != "encrypted" {
|
||||||
|
// Unencrypted, we can directly access data
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
// Encrypted, check whether vold is started
|
||||||
|
!get_prop(cstr!("init.svc.vold"), false).is_empty()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// ro.crypto.state is not set, assume it's unencrypted
|
||||||
|
true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_magiskd() -> &'static MagiskD {
|
pub fn get_magiskd() -> &'static MagiskD {
|
||||||
unsafe { MAGISKD.get().unwrap_unchecked() }
|
unsafe { MAGISKD.get().unwrap_unchecked() }
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,7 @@ int denylist_cli(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Send request
|
// Send request
|
||||||
int fd = connect_daemon(MainRequest::DENYLIST);
|
int fd = connect_daemon(+RequestCode::DENYLIST);
|
||||||
write_int(fd, req);
|
write_int(fd, req);
|
||||||
if (req == DenyRequest::ADD || req == DenyRequest::REMOVE) {
|
if (req == DenyRequest::ADD || req == DenyRequest::REMOVE) {
|
||||||
write_string(fd, argv[2]);
|
write_string(fd, argv[2]);
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
#include "socket.hpp"
|
#include "socket.hpp"
|
||||||
#include "../core-rs.hpp"
|
|
||||||
|
|
||||||
#define AID_ROOT 0
|
#define AID_ROOT 0
|
||||||
#define AID_SHELL 2000
|
#define AID_SHELL 2000
|
||||||
@ -19,11 +18,17 @@
|
|||||||
#define to_app_id(uid) (uid % AID_USER_OFFSET)
|
#define to_app_id(uid) (uid % AID_USER_OFFSET)
|
||||||
#define to_user_id(uid) (uid / AID_USER_OFFSET)
|
#define to_user_id(uid) (uid / AID_USER_OFFSET)
|
||||||
|
|
||||||
|
namespace rust {
|
||||||
|
struct MagiskD;
|
||||||
|
}
|
||||||
|
|
||||||
struct MagiskD {
|
struct MagiskD {
|
||||||
|
// Make sure only references can exist
|
||||||
|
~MagiskD() = delete;
|
||||||
|
|
||||||
// Binding to Rust
|
// Binding to Rust
|
||||||
void setup_logfile() const noexcept { impl.setup_logfile(); }
|
static const MagiskD &get();
|
||||||
bool is_emulator() const noexcept { return impl.is_emulator(); }
|
void boot_stage_handler(int client, int code) const;
|
||||||
bool is_recovery() const noexcept { return impl.is_recovery(); }
|
|
||||||
|
|
||||||
// C++ implementation
|
// C++ implementation
|
||||||
void reboot() const;
|
void reboot() const;
|
||||||
@ -32,46 +37,17 @@ struct MagiskD {
|
|||||||
void boot_complete() const;
|
void boot_complete() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const rust::MagiskD &impl = rust::get_magiskd();
|
const rust::MagiskD &as_rust() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Daemon command codes
|
|
||||||
namespace MainRequest {
|
|
||||||
enum : int {
|
|
||||||
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,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return codes for daemon
|
// Return codes for daemon
|
||||||
namespace MainResponse {
|
enum class RespondCode : int {
|
||||||
enum : int {
|
|
||||||
ERROR = -1,
|
ERROR = -1,
|
||||||
OK = 0,
|
OK = 0,
|
||||||
ROOT_REQUIRED,
|
ROOT_REQUIRED,
|
||||||
ACCESS_DENIED,
|
ACCESS_DENIED,
|
||||||
END
|
END
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
struct module_info {
|
struct module_info {
|
||||||
std::string name;
|
std::string name;
|
||||||
@ -139,3 +115,6 @@ int denylist_cli(int argc, char **argv);
|
|||||||
void initialize_denylist();
|
void initialize_denylist();
|
||||||
bool is_deny_target(int uid, std::string_view process);
|
bool is_deny_target(int uid, std::string_view process);
|
||||||
void revert_unmount();
|
void revert_unmount();
|
||||||
|
|
||||||
|
// Include last to prevent recursive include issues
|
||||||
|
#include "../core-rs.hpp"
|
||||||
|
@ -18,6 +18,31 @@ mod resetprop;
|
|||||||
|
|
||||||
#[cxx::bridge]
|
#[cxx::bridge]
|
||||||
pub mod ffi {
|
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,
|
||||||
|
}
|
||||||
|
|
||||||
extern "C++" {
|
extern "C++" {
|
||||||
include!("include/resetprop.hpp");
|
include!("include/resetprop.hpp");
|
||||||
|
|
||||||
@ -27,6 +52,16 @@ pub mod ffi {
|
|||||||
unsafe fn prop_cb_exec(cb: Pin<&mut PropCb>, name: *const c_char, value: *const c_char);
|
unsafe fn prop_cb_exec(cb: Pin<&mut PropCb>, name: *const c_char, value: *const c_char);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe extern "C++" {
|
||||||
|
include!("include/core.hpp");
|
||||||
|
|
||||||
|
#[cxx_name = "MagiskD"]
|
||||||
|
type CxxMagiskD;
|
||||||
|
fn post_fs_data(self: &CxxMagiskD);
|
||||||
|
fn late_start(self: &CxxMagiskD);
|
||||||
|
fn boot_complete(self: &CxxMagiskD);
|
||||||
|
}
|
||||||
|
|
||||||
extern "Rust" {
|
extern "Rust" {
|
||||||
fn rust_test_entry();
|
fn rust_test_entry();
|
||||||
fn android_logging();
|
fn android_logging();
|
||||||
@ -48,11 +83,11 @@ pub mod ffi {
|
|||||||
|
|
||||||
type MagiskD;
|
type MagiskD;
|
||||||
fn get_magiskd() -> &'static MagiskD;
|
fn get_magiskd() -> &'static MagiskD;
|
||||||
fn get_log_pipe(self: &MagiskD) -> i32;
|
|
||||||
fn close_log_pipe(self: &MagiskD);
|
|
||||||
fn setup_logfile(self: &MagiskD);
|
fn setup_logfile(self: &MagiskD);
|
||||||
fn is_emulator(self: &MagiskD) -> bool;
|
fn is_emulator(self: &MagiskD) -> bool;
|
||||||
fn is_recovery(self: &MagiskD) -> bool;
|
fn is_recovery(self: &MagiskD) -> bool;
|
||||||
|
fn boot_stage_handler(self: &MagiskD, client: i32, code: i32);
|
||||||
|
fn enable_safe_mode(self: &MagiskD);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ use std::ffi::{c_char, c_void};
|
|||||||
use std::fmt::Write as FmtWrite;
|
use std::fmt::Write as FmtWrite;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{IoSlice, Read, Write};
|
use std::io::{IoSlice, Read, Write};
|
||||||
use std::os::fd::{AsRawFd, FromRawFd, RawFd};
|
use std::os::fd::{FromRawFd, RawFd};
|
||||||
use std::ptr::null_mut;
|
use std::ptr::null_mut;
|
||||||
use std::sync::atomic::{AtomicI32, Ordering};
|
use std::sync::atomic::{AtomicI32, Ordering};
|
||||||
use std::{fs, io};
|
use std::{fs, io};
|
||||||
@ -382,14 +382,6 @@ impl MagiskD {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_log_pipe(&self) -> RawFd {
|
|
||||||
self.logd
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.as_ref()
|
|
||||||
.map_or(-1, |s| s.as_raw_fd())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn close_log_pipe(&self) {
|
pub fn close_log_pipe(&self) {
|
||||||
*self.logd.lock().unwrap() = None;
|
*self.logd.lock().unwrap() = None;
|
||||||
}
|
}
|
||||||
|
@ -58,12 +58,12 @@ int magisk_main(int argc, char *argv[]) {
|
|||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
} else if (argv[1] == "-v"sv) {
|
} else if (argv[1] == "-v"sv) {
|
||||||
int fd = connect_daemon(MainRequest::CHECK_VERSION);
|
int fd = connect_daemon(+RequestCode::CHECK_VERSION);
|
||||||
string v = read_string(fd);
|
string v = read_string(fd);
|
||||||
printf("%s\n", v.data());
|
printf("%s\n", v.data());
|
||||||
return 0;
|
return 0;
|
||||||
} else if (argv[1] == "-V"sv) {
|
} else if (argv[1] == "-V"sv) {
|
||||||
int fd = connect_daemon(MainRequest::CHECK_VERSION_CODE);
|
int fd = connect_daemon(+RequestCode::CHECK_VERSION_CODE);
|
||||||
printf("%d\n", read_int(fd));
|
printf("%d\n", read_int(fd));
|
||||||
return 0;
|
return 0;
|
||||||
} else if (argv[1] == "--list"sv) {
|
} else if (argv[1] == "--list"sv) {
|
||||||
@ -83,29 +83,29 @@ int magisk_main(int argc, char *argv[]) {
|
|||||||
cp_afc(argv[2], argv[3]);
|
cp_afc(argv[2], argv[3]);
|
||||||
return 0;
|
return 0;
|
||||||
} else if (argv[1] == "--daemon"sv) {
|
} else if (argv[1] == "--daemon"sv) {
|
||||||
close(connect_daemon(MainRequest::START_DAEMON, true));
|
close(connect_daemon(+RequestCode::START_DAEMON, true));
|
||||||
return 0;
|
return 0;
|
||||||
} else if (argv[1] == "--stop"sv) {
|
} else if (argv[1] == "--stop"sv) {
|
||||||
int fd = connect_daemon(MainRequest::STOP_DAEMON);
|
int fd = connect_daemon(+RequestCode::STOP_DAEMON);
|
||||||
return read_int(fd);
|
return read_int(fd);
|
||||||
} else if (argv[1] == "--post-fs-data"sv) {
|
} else if (argv[1] == "--post-fs-data"sv) {
|
||||||
int fd = connect_daemon(MainRequest::POST_FS_DATA, true);
|
int fd = connect_daemon(+RequestCode::POST_FS_DATA, true);
|
||||||
struct pollfd pfd = { fd, POLLIN, 0 };
|
struct pollfd pfd = { fd, POLLIN, 0 };
|
||||||
poll(&pfd, 1, 1000 * POST_FS_DATA_WAIT_TIME);
|
poll(&pfd, 1, 1000 * POST_FS_DATA_WAIT_TIME);
|
||||||
return 0;
|
return 0;
|
||||||
} else if (argv[1] == "--service"sv) {
|
} else if (argv[1] == "--service"sv) {
|
||||||
close(connect_daemon(MainRequest::LATE_START, true));
|
close(connect_daemon(+RequestCode::LATE_START, true));
|
||||||
return 0;
|
return 0;
|
||||||
} else if (argv[1] == "--boot-complete"sv) {
|
} else if (argv[1] == "--boot-complete"sv) {
|
||||||
close(connect_daemon(MainRequest::BOOT_COMPLETE));
|
close(connect_daemon(+RequestCode::BOOT_COMPLETE));
|
||||||
return 0;
|
return 0;
|
||||||
} else if (argv[1] == "--zygote-restart"sv) {
|
} else if (argv[1] == "--zygote-restart"sv) {
|
||||||
close(connect_daemon(MainRequest::ZYGOTE_RESTART));
|
close(connect_daemon(+RequestCode::ZYGOTE_RESTART));
|
||||||
return 0;
|
return 0;
|
||||||
} else if (argv[1] == "--denylist"sv) {
|
} else if (argv[1] == "--denylist"sv) {
|
||||||
return denylist_cli(argc - 1, argv + 1);
|
return denylist_cli(argc - 1, argv + 1);
|
||||||
} else if (argc >= 3 && argv[1] == "--sqlite"sv) {
|
} else if (argc >= 3 && argv[1] == "--sqlite"sv) {
|
||||||
int fd = connect_daemon(MainRequest::SQLITE_CMD);
|
int fd = connect_daemon(+RequestCode::SQLITE_CMD);
|
||||||
write_string(fd, argv[2]);
|
write_string(fd, argv[2]);
|
||||||
string res;
|
string res;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@ -123,7 +123,7 @@ int magisk_main(int argc, char *argv[]) {
|
|||||||
} else {
|
} else {
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
int fd = connect_daemon(MainRequest::REMOVE_MODULES);
|
int fd = connect_daemon(+RequestCode::REMOVE_MODULES);
|
||||||
write_int(fd, do_reboot);
|
write_int(fd, do_reboot);
|
||||||
return read_int(fd);
|
return read_int(fd);
|
||||||
} else if (argv[1] == "--path"sv) {
|
} else if (argv[1] == "--path"sv) {
|
||||||
|
@ -189,7 +189,7 @@ int su_client_main(int argc, char *argv[]) {
|
|||||||
int ptmx, fd;
|
int ptmx, fd;
|
||||||
|
|
||||||
// Connect to client
|
// Connect to client
|
||||||
fd = connect_daemon(MainRequest::SUPERUSER);
|
fd = connect_daemon(+RequestCode::SUPERUSER);
|
||||||
|
|
||||||
// Send su_request
|
// Send su_request
|
||||||
xwrite(fd, &su_req, sizeof(su_req_base));
|
xwrite(fd, &su_req, sizeof(su_req_base));
|
||||||
|
@ -39,7 +39,7 @@ void hookJniNativeMethods(JNIEnv *env, const char *clz, JNINativeMethod *methods
|
|||||||
int remote_get_info(int uid, const char *process, uint32_t *flags, std::vector<int> &fds);
|
int remote_get_info(int uid, const char *process, uint32_t *flags, std::vector<int> &fds);
|
||||||
|
|
||||||
inline int zygisk_request(int req) {
|
inline int zygisk_request(int req) {
|
||||||
int fd = connect_daemon(MainRequest::ZYGISK);
|
int fd = connect_daemon(+RequestCode::ZYGISK);
|
||||||
if (fd < 0) return fd;
|
if (fd < 0) return fd;
|
||||||
write_int(fd, req);
|
write_int(fd, req);
|
||||||
return fd;
|
return fd;
|
||||||
|
Loading…
Reference in New Issue
Block a user