mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-04-29 22:14:27 +02:00
Move more daemon_start code into Rust
This commit is contained in:
parent
73840f8721
commit
d1829308e9
@ -16,7 +16,7 @@ impl Utf8CStr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remount_with_flags(&self, flags: c_ulong) -> OsResult<()> {
|
pub fn remount_mount_point_flags(&self, flags: c_ulong) -> OsResult<()> {
|
||||||
unsafe {
|
unsafe {
|
||||||
libc::mount(
|
libc::mount(
|
||||||
ptr::null(),
|
ptr::null(),
|
||||||
@ -29,6 +29,19 @@ impl Utf8CStr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn remount_mount_flags(&self, flags: c_ulong) -> OsResult<()> {
|
||||||
|
unsafe {
|
||||||
|
libc::mount(
|
||||||
|
ptr::null(),
|
||||||
|
self.as_ptr(),
|
||||||
|
ptr::null(),
|
||||||
|
libc::MS_REMOUNT | flags,
|
||||||
|
ptr::null(),
|
||||||
|
)
|
||||||
|
.check_os_err("remount", Some(self), None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn remount_with_data(&self, data: &Utf8CStr) -> OsResult<()> {
|
pub fn remount_with_data(&self, data: &Utf8CStr) -> OsResult<()> {
|
||||||
unsafe {
|
unsafe {
|
||||||
libc::mount(
|
libc::mount(
|
||||||
|
@ -325,29 +325,6 @@ static void handle_request(pollfd *pfd) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void switch_cgroup(const char *cgroup, int pid) {
|
|
||||||
char buf[32];
|
|
||||||
ssprintf(buf, sizeof(buf), "%s/cgroup.procs", cgroup);
|
|
||||||
if (access(buf, F_OK) != 0)
|
|
||||||
return;
|
|
||||||
int fd = xopen(buf, O_WRONLY | O_APPEND | O_CLOEXEC);
|
|
||||||
if (fd == -1)
|
|
||||||
return;
|
|
||||||
ssprintf(buf, sizeof(buf), "%d\n", pid);
|
|
||||||
xwrite(fd, buf, strlen(buf));
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int setcon(const char *con) {
|
|
||||||
int fd = open("/proc/self/attr/current", O_WRONLY | O_CLOEXEC);
|
|
||||||
if (fd < 0)
|
|
||||||
return fd;
|
|
||||||
size_t len = strlen(con) + 1;
|
|
||||||
int rc = write(fd, con, len);
|
|
||||||
close(fd);
|
|
||||||
return rc != len;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void daemon_entry() {
|
static void daemon_entry() {
|
||||||
android_logging();
|
android_logging();
|
||||||
|
|
||||||
@ -369,49 +346,15 @@ static void daemon_entry() {
|
|||||||
if (fd > STDERR_FILENO)
|
if (fd > STDERR_FILENO)
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
setsid();
|
|
||||||
setcon(MAGISK_PROC_CON);
|
|
||||||
|
|
||||||
rust::daemon_entry();
|
rust::daemon_entry();
|
||||||
SDK_INT = MagiskD::Get().sdk_int();
|
SDK_INT = MagiskD::Get().sdk_int();
|
||||||
|
|
||||||
// Escape from cgroup
|
|
||||||
int pid = getpid();
|
|
||||||
switch_cgroup("/acct", pid);
|
|
||||||
switch_cgroup("/dev/cg2_bpf", pid);
|
|
||||||
switch_cgroup("/sys/fs/cgroup", pid);
|
|
||||||
if (get_prop("ro.config.per_app_memcg") != "false") {
|
|
||||||
switch_cgroup("/dev/memcg/apps", pid);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get self stat
|
// Get self stat
|
||||||
xstat("/proc/self/exe", &self_st);
|
xstat("/proc/self/exe", &self_st);
|
||||||
|
|
||||||
// Samsung workaround #7887
|
|
||||||
if (access("/system_ext/app/mediatek-res/mediatek-res.apk", F_OK) == 0) {
|
|
||||||
set_prop("ro.vendor.mtk_model", "0");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cleanups
|
|
||||||
const char *tmp = get_magisk_tmp();
|
|
||||||
char path[64];
|
|
||||||
ssprintf(path, sizeof(path), "%s/" ROOTMNT, tmp);
|
|
||||||
if (access(path, F_OK) == 0) {
|
|
||||||
file_readline(true, path, [](string_view line) -> bool {
|
|
||||||
umount2(line.data(), MNT_DETACH);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (getenv("REMOUNT_ROOT")) {
|
|
||||||
xmount(nullptr, "/", nullptr, MS_REMOUNT | MS_RDONLY, nullptr);
|
|
||||||
unsetenv("REMOUNT_ROOT");
|
|
||||||
}
|
|
||||||
ssprintf(path, sizeof(path), "%s/" ROOTOVL, tmp);
|
|
||||||
rm_rf(path);
|
|
||||||
|
|
||||||
fd = xsocket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0);
|
fd = xsocket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0);
|
||||||
sockaddr_un addr = {.sun_family = AF_LOCAL};
|
sockaddr_un addr = {.sun_family = AF_LOCAL};
|
||||||
ssprintf(addr.sun_path, sizeof(addr.sun_path), "%s/" MAIN_SOCKET, tmp);
|
ssprintf(addr.sun_path, sizeof(addr.sun_path), "%s/" MAIN_SOCKET, get_magisk_tmp());
|
||||||
unlink(addr.sun_path);
|
unlink(addr.sun_path);
|
||||||
if (xbind(fd, (sockaddr *) &addr, sizeof(addr)))
|
if (xbind(fd, (sockaddr *) &addr, sizeof(addr)))
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -1,18 +1,21 @@
|
|||||||
use crate::consts::{MAGISK_FULL_VER, MAIN_CONFIG, SECURE_DIR};
|
use crate::consts::{MAGISK_FULL_VER, MAGISK_PROC_CON, MAIN_CONFIG, ROOTMNT, ROOTOVL, SECURE_DIR};
|
||||||
use crate::db::Sqlite3;
|
use crate::db::Sqlite3;
|
||||||
use crate::ffi::{
|
use crate::ffi::{
|
||||||
DbEntryKey, ModuleInfo, RequestCode, check_key_combo, disable_modules, exec_common_scripts,
|
DbEntryKey, ModuleInfo, RequestCode, check_key_combo, disable_modules, exec_common_scripts,
|
||||||
exec_module_scripts, get_magisk_tmp, initialize_denylist, setup_magisk_env,
|
exec_module_scripts, get_magisk_tmp, initialize_denylist, setup_magisk_env,
|
||||||
};
|
};
|
||||||
use crate::get_prop;
|
|
||||||
use crate::logging::{magisk_logging, setup_logfile, start_log_daemon};
|
use crate::logging::{magisk_logging, setup_logfile, start_log_daemon};
|
||||||
use crate::mount::{clean_mounts, setup_mounts};
|
use crate::mount::{clean_mounts, setup_mounts};
|
||||||
use crate::package::ManagerInfo;
|
use crate::package::ManagerInfo;
|
||||||
use crate::selinux::restore_tmpcon;
|
use crate::selinux::restore_tmpcon;
|
||||||
use crate::su::SuInfo;
|
use crate::su::SuInfo;
|
||||||
use base::libc::{O_CLOEXEC, O_RDONLY};
|
use crate::{get_prop, set_prop};
|
||||||
use base::{AtomicArc, BufReadExt, FsPathBuilder, ResultExt, Utf8CStr, cstr, error, info, libc};
|
use base::libc::{O_APPEND, O_CLOEXEC, O_RDONLY, O_WRONLY};
|
||||||
use std::io::BufReader;
|
use base::{
|
||||||
|
AtomicArc, BufReadExt, FsPathBuilder, ResultExt, Utf8CStr, Utf8CStrBuf, cstr, error, info, libc,
|
||||||
|
};
|
||||||
|
use std::fmt::Write as FmtWrite;
|
||||||
|
use std::io::{BufReader, Write};
|
||||||
use std::os::unix::net::UnixStream;
|
use std::os::unix::net::UnixStream;
|
||||||
use std::sync::atomic::{AtomicBool, AtomicU32, Ordering};
|
use std::sync::atomic::{AtomicBool, AtomicU32, Ordering};
|
||||||
use std::sync::{Mutex, OnceLock};
|
use std::sync::{Mutex, OnceLock};
|
||||||
@ -217,6 +220,14 @@ impl MagiskD {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn daemon_entry() {
|
pub fn daemon_entry() {
|
||||||
|
unsafe { libc::setsid() };
|
||||||
|
|
||||||
|
// Make sure the current context is magisk
|
||||||
|
if let Ok(mut current) = cstr!("/proc/self/attr/current").open(O_WRONLY | O_CLOEXEC) {
|
||||||
|
let con = cstr!(MAGISK_PROC_CON);
|
||||||
|
current.write_all(con.as_bytes_with_nul()).log_ok();
|
||||||
|
}
|
||||||
|
|
||||||
start_log_daemon();
|
start_log_daemon();
|
||||||
magisk_logging();
|
magisk_logging();
|
||||||
info!("Magisk {} daemon started", MAGISK_FULL_VER);
|
info!("Magisk {} daemon started", MAGISK_FULL_VER);
|
||||||
@ -226,13 +237,13 @@ pub fn daemon_entry() {
|
|||||||
|| get_prop(cstr!("ro.product.device"), false).contains("vsoc");
|
|| get_prop(cstr!("ro.product.device"), false).contains("vsoc");
|
||||||
|
|
||||||
// Load config status
|
// Load config status
|
||||||
let path = cstr::buf::new::<64>()
|
let magisk_tmp = get_magisk_tmp();
|
||||||
.join_path(get_magisk_tmp())
|
let mut tmp_path = cstr::buf::new::<64>()
|
||||||
|
.join_path(magisk_tmp)
|
||||||
.join_path(MAIN_CONFIG);
|
.join_path(MAIN_CONFIG);
|
||||||
let mut is_recovery = false;
|
let mut is_recovery = false;
|
||||||
if let Ok(file) = path.open(O_RDONLY | O_CLOEXEC) {
|
if let Ok(main_config) = tmp_path.open(O_RDONLY | O_CLOEXEC) {
|
||||||
let mut file = BufReader::new(file);
|
BufReader::new(main_config).foreach_props(|key, val| {
|
||||||
file.foreach_props(|key, val| {
|
|
||||||
if key == "RECOVERYMODE" {
|
if key == "RECOVERYMODE" {
|
||||||
is_recovery = val == "true";
|
is_recovery = val == "true";
|
||||||
return false;
|
return false;
|
||||||
@ -240,11 +251,11 @@ pub fn daemon_entry() {
|
|||||||
true
|
true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
tmp_path.truncate(magisk_tmp.len());
|
||||||
|
|
||||||
let mut sdk_int = -1;
|
let mut sdk_int = -1;
|
||||||
if let Ok(file) = cstr!("/system/build.prop").open(O_RDONLY | O_CLOEXEC) {
|
if let Ok(build_prop) = cstr!("/system/build.prop").open(O_RDONLY | O_CLOEXEC) {
|
||||||
let mut file = BufReader::new(file);
|
BufReader::new(build_prop).foreach_props(|key, val| {
|
||||||
file.foreach_props(|key, val| {
|
|
||||||
if key == "ro.build.version.sdk" {
|
if key == "ro.build.version.sdk" {
|
||||||
sdk_int = val.parse::<i32>().unwrap_or(-1);
|
sdk_int = val.parse::<i32>().unwrap_or(-1);
|
||||||
return false;
|
return false;
|
||||||
@ -262,6 +273,42 @@ pub fn daemon_entry() {
|
|||||||
|
|
||||||
restore_tmpcon().log_ok();
|
restore_tmpcon().log_ok();
|
||||||
|
|
||||||
|
// Escape from cgroup
|
||||||
|
let pid = unsafe { libc::getpid() };
|
||||||
|
switch_cgroup("/acct", pid);
|
||||||
|
switch_cgroup("/dev/cg2_bpf", pid);
|
||||||
|
switch_cgroup("/sys/fs/cgroup", pid);
|
||||||
|
if get_prop(cstr!("ro.config.per_app_memcg"), false) != "false" {
|
||||||
|
switch_cgroup("/dev/memcg/apps", pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Samsung workaround #7887
|
||||||
|
if cstr!("/system_ext/app/mediatek-res/mediatek-res.apk").exists() {
|
||||||
|
set_prop(cstr!("ro.vendor.mtk_model"), cstr!("0"), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup pre-init mounts
|
||||||
|
tmp_path.append_path(ROOTMNT);
|
||||||
|
if let Ok(mount_list) = tmp_path.open(O_RDONLY | O_CLOEXEC) {
|
||||||
|
BufReader::new(mount_list).foreach_lines(|line| {
|
||||||
|
let item = Utf8CStr::from_string(line);
|
||||||
|
item.unmount().log_ok();
|
||||||
|
true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
tmp_path.truncate(magisk_tmp.len());
|
||||||
|
|
||||||
|
// Remount rootfs as read-only if requested
|
||||||
|
if std::env::var_os("REMOUNT_ROOT").is_some() {
|
||||||
|
cstr!("/").remount_mount_flags(libc::MS_RDONLY).log_ok();
|
||||||
|
unsafe { std::env::remove_var("REMOUNT_ROOT") };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove all pre-init overlay files to free-up memory
|
||||||
|
tmp_path.append_path(ROOTOVL);
|
||||||
|
tmp_path.remove_all().log_ok();
|
||||||
|
tmp_path.truncate(magisk_tmp.len());
|
||||||
|
|
||||||
let magiskd = MagiskD {
|
let magiskd = MagiskD {
|
||||||
sdk_int,
|
sdk_int,
|
||||||
is_emulator,
|
is_emulator,
|
||||||
@ -272,6 +319,20 @@ pub fn daemon_entry() {
|
|||||||
MAGISKD.set(magiskd).ok();
|
MAGISKD.set(magiskd).ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn switch_cgroup(cgroup: &str, pid: i32) {
|
||||||
|
let mut buf = cstr::buf::new::<64>()
|
||||||
|
.join_path(cgroup)
|
||||||
|
.join_path("cgroup.procs");
|
||||||
|
if !buf.exists() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if let Ok(mut file) = buf.open(O_WRONLY | O_APPEND | O_CLOEXEC) {
|
||||||
|
buf.clear();
|
||||||
|
buf.write_fmt(format_args!("{}", pid)).ok();
|
||||||
|
file.write_all(buf.as_bytes()).log_ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn check_data() -> bool {
|
fn check_data() -> bool {
|
||||||
if let Ok(file) = cstr!("/proc/mounts").open(O_RDONLY | O_CLOEXEC) {
|
if let Ok(file) = cstr!("/proc/mounts").open(O_RDONLY | O_CLOEXEC) {
|
||||||
let mut mnt = false;
|
let mut mnt = false;
|
||||||
|
@ -137,6 +137,8 @@ pub mod ffi {
|
|||||||
#[cxx_name = "prop_cb"]
|
#[cxx_name = "prop_cb"]
|
||||||
type PropCb;
|
type PropCb;
|
||||||
unsafe fn get_prop_rs(name: *const c_char, persist: bool) -> String;
|
unsafe fn get_prop_rs(name: *const c_char, persist: bool) -> String;
|
||||||
|
#[cxx_name = "set_prop"]
|
||||||
|
unsafe fn set_prop_rs(name: *const c_char, value: *const c_char, skip_svc: bool) -> i32;
|
||||||
unsafe fn prop_cb_exec(
|
unsafe fn prop_cb_exec(
|
||||||
cb: Pin<&mut PropCb>,
|
cb: Pin<&mut PropCb>,
|
||||||
name: *const c_char,
|
name: *const c_char,
|
||||||
@ -277,3 +279,7 @@ impl SuRequest {
|
|||||||
pub fn get_prop(name: &Utf8CStr, persist: bool) -> String {
|
pub fn get_prop(name: &Utf8CStr, persist: bool) -> String {
|
||||||
unsafe { ffi::get_prop_rs(name.as_ptr(), persist) }
|
unsafe { ffi::get_prop_rs(name.as_ptr(), persist) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_prop(name: &Utf8CStr, value: &Utf8CStr, skip_svc: bool) -> bool {
|
||||||
|
unsafe { ffi::set_prop_rs(name.as_ptr(), value.as_ptr(), skip_svc) == 0 }
|
||||||
|
}
|
||||||
|
@ -74,7 +74,7 @@ pub fn setup_mounts() {
|
|||||||
let _: LoggedResult<()> = try {
|
let _: LoggedResult<()> = try {
|
||||||
module_mnt.mkdir(0o755)?;
|
module_mnt.mkdir(0o755)?;
|
||||||
cstr!(MODULEROOT).bind_mount_to(&module_mnt)?;
|
cstr!(MODULEROOT).bind_mount_to(&module_mnt)?;
|
||||||
module_mnt.remount_with_flags(libc::MS_RDONLY)?;
|
module_mnt.remount_mount_point_flags(libc::MS_RDONLY)?;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,11 +20,8 @@
|
|||||||
#define BBPATH INTLROOT "/busybox"
|
#define BBPATH INTLROOT "/busybox"
|
||||||
#define ROOTOVL INTLROOT "/rootdir"
|
#define ROOTOVL INTLROOT "/rootdir"
|
||||||
#define SHELLPTS INTLROOT "/pts"
|
#define SHELLPTS INTLROOT "/pts"
|
||||||
#define ROOTMNT ROOTOVL "/.mount_list"
|
|
||||||
#define SELINUXMOCK INTLROOT "/selinux"
|
|
||||||
#define MAIN_CONFIG INTLROOT "/config"
|
#define MAIN_CONFIG INTLROOT "/config"
|
||||||
#define MAIN_SOCKET DEVICEDIR "/socket"
|
#define MAIN_SOCKET DEVICEDIR "/socket"
|
||||||
#define LOG_PIPE DEVICEDIR "/log"
|
|
||||||
|
|
||||||
constexpr const char *applet_names[] = { "su", "resetprop", nullptr };
|
constexpr const char *applet_names[] = { "su", "resetprop", nullptr };
|
||||||
|
|
||||||
@ -39,7 +36,6 @@ constexpr const char *applet_names[] = { "su", "resetprop", nullptr };
|
|||||||
#define MAGISK_FILE_CON "u:object_r:" SEPOL_FILE_TYPE ":s0"
|
#define MAGISK_FILE_CON "u:object_r:" SEPOL_FILE_TYPE ":s0"
|
||||||
// Log pipe that only root and zygote can open
|
// Log pipe that only root and zygote can open
|
||||||
#define SEPOL_LOG_TYPE "magisk_log_file"
|
#define SEPOL_LOG_TYPE "magisk_log_file"
|
||||||
#define MAGISK_LOG_CON "u:object_r:" SEPOL_LOG_TYPE ":s0"
|
|
||||||
|
|
||||||
extern int SDK_INT;
|
extern int SDK_INT;
|
||||||
#define APP_DATA_DIR (SDK_INT >= 24 ? "/data/user_de" : "/data/user")
|
#define APP_DATA_DIR (SDK_INT >= 24 ? "/data/user_de" : "/data/user")
|
||||||
|
@ -32,6 +32,7 @@ pub const SELINUXMOCK: &str = concatcp!(INTERNAL_DIR, "/selinux");
|
|||||||
|
|
||||||
// Unconstrained domain the daemon and root processes run in
|
// Unconstrained domain the daemon and root processes run in
|
||||||
pub const SEPOL_PROC_DOMAIN: &str = "magisk";
|
pub const SEPOL_PROC_DOMAIN: &str = "magisk";
|
||||||
|
pub const MAGISK_PROC_CON: &str = concatcp!("u:r:", SEPOL_PROC_DOMAIN, ":s0");
|
||||||
// Unconstrained file type that anyone can access
|
// Unconstrained file type that anyone can access
|
||||||
pub const SEPOL_FILE_TYPE: &str = "magisk_file";
|
pub const SEPOL_FILE_TYPE: &str = "magisk_file";
|
||||||
// Log pipe that only root and zygote can open
|
// Log pipe that only root and zygote can open
|
||||||
|
Loading…
x
Reference in New Issue
Block a user