diff --git a/native/src/core/lib.rs b/native/src/core/lib.rs index 0b86c0583..905965475 100644 --- a/native/src/core/lib.rs +++ b/native/src/core/lib.rs @@ -125,15 +125,6 @@ pub mod ffi { gids: Vec, } - struct SuAppRequest<'a> { - uid: i32, - pid: i32, - eval_uid: i32, - mgr_pkg: &'a str, - mgr_uid: i32, - request: &'a SuRequest, - } - unsafe extern "C++" { #[namespace = "rust"] #[cxx_name = "Utf8CStr"] diff --git a/native/src/core/su/connect.rs b/native/src/core/su/connect.rs index 799ba4a55..8c76aeec9 100644 --- a/native/src/core/su/connect.rs +++ b/native/src/core/su/connect.rs @@ -1,10 +1,12 @@ +use super::SuInfo; +use super::db::RootSettings; use crate::consts::{INTERNAL_DIR, MAGISK_FILE_CON}; -use crate::daemon::{MagiskD, to_user_id}; -use crate::ffi::{SuAppRequest, SuPolicy, get_magisk_tmp}; +use crate::daemon::to_user_id; +use crate::ffi::{SuPolicy, SuRequest, get_magisk_tmp}; +use crate::socket::IpcRead; use ExtraVal::{Bool, Int, IntList, Str}; use base::{ - BytesExt, FileAttr, LibcReturn, LoggedResult, OsError, ResultExt, cstr, fork_dont_care, info, - libc, + BytesExt, FileAttr, LibcReturn, LoggedResult, OsError, ResultExt, cstr, fork_dont_care, libc, }; use libc::pollfd as PollFd; use num_traits::AsPrimitive; @@ -79,19 +81,21 @@ impl Extra { } } -impl MagiskD { - fn exec_cmd( - &self, - action: &'static str, - extras: &[Extra], - info: &SuAppRequest, - use_provider: bool, - ) { - let user = to_user_id(info.eval_uid); +pub(super) struct SuAppContext<'a> { + pub(super) cred: libc::ucred, + pub(super) request: &'a SuRequest, + pub(super) info: &'a SuInfo, + pub(super) settings: &'a mut RootSettings, + pub(super) sdk_int: i32, +} + +impl SuAppContext<'_> { + fn exec_cmd(&self, action: &'static str, extras: &[Extra], use_provider: bool) { + let user = to_user_id(self.info.eval_uid); let user = user.to_string(); if use_provider { - let provider = format!("content://{}.provider", info.mgr_pkg); + let provider = format!("content://{}.provider", self.info.mgr_pkg); let mut cmd = Command::new("/system/bin/app_process"); cmd.args([ "/system/bin", @@ -104,7 +108,7 @@ impl MagiskD { "--method", action, ]); - if self.sdk_int() >= 30 { + if self.sdk_int >= 30 { extras.iter().for_each(|e| e.add_bind(&mut cmd)) } else { extras.iter().for_each(|e| e.add_bind_legacy(&mut cmd)) @@ -126,7 +130,7 @@ impl MagiskD { "com.android.commands.am.Am", "start", "-p", - info.mgr_pkg, + &self.info.mgr_pkg, "--user", &user, "-a", @@ -152,21 +156,21 @@ impl MagiskD { } } - pub fn app_request(&self, info: &SuAppRequest) -> LoggedResult { + fn app_request(&mut self) { let mut fifo = cstr::buf::new::<64>(); fifo.write_fmt(format_args!( "{}/{}/su_request_{}", get_magisk_tmp(), INTERNAL_DIR, - info.pid + self.cred.pid )) .ok(); let fd: LoggedResult = try { let mut attr = FileAttr::new(); attr.st.st_mode = 0o600; - attr.st.st_uid = info.mgr_uid.as_(); - attr.st.st_gid = info.mgr_uid.as_(); + attr.st.st_uid = self.info.mgr_uid.as_(); + attr.st.st_gid = self.info.mgr_uid.as_(); attr.con.write_str(MAGISK_FILE_CON).ok(); fifo.mkfifo(0o600)?; @@ -179,14 +183,14 @@ impl MagiskD { }, Extra { key: "uid", - value: Int(info.eval_uid), + value: Int(self.info.eval_uid), }, Extra { key: "pid", - value: Int(info.pid), + value: Int(self.cred.pid), }, ]; - self.exec_cmd("request", &extras, info, false); + self.exec_cmd("request", &extras, false); // Open with O_RDWR to prevent FIFO open block let fd = fifo.open(libc::O_RDWR | libc::O_CLOEXEC)?; @@ -206,68 +210,72 @@ impl MagiskD { }; fifo.remove().log_ok(); - fd + + if let Ok(mut fd) = fd { + self.settings.policy = SuPolicy { + repr: fd + .read_decodable::() + .log() + .map(i32::from_be) + .unwrap_or(SuPolicy::Deny.repr), + }; + } else { + self.settings.policy = SuPolicy::Deny; + }; } - pub fn app_notify(&self, info: &SuAppRequest, policy: SuPolicy) { - if fork_dont_care() != 0 { - return; - } + fn app_notify(&self) { let extras = [ Extra { key: "from.uid", - value: Int(info.uid), + value: Int(self.cred.uid.as_()), }, Extra { key: "pid", - value: Int(info.pid), + value: Int(self.cred.pid.as_()), }, Extra { key: "policy", - value: Int(policy.repr), + value: Int(self.settings.policy.repr), }, ]; - self.exec_cmd("notify", &extras, info, true); - exit(0); + self.exec_cmd("notify", &extras, true); } - pub fn app_log(&self, info: &SuAppRequest, policy: SuPolicy, notify: bool) { - if fork_dont_care() != 0 { - return; - } - let command = if info.request.command.is_empty() { - &info.request.shell + fn app_log(&self) { + let command = if self.request.command.is_empty() { + &self.request.shell } else { - &info.request.command + &self.request.command }; let extras = [ Extra { key: "from.uid", - value: Int(info.uid), + value: Int(self.cred.uid.as_()), }, Extra { key: "to.uid", - value: Int(info.request.target_uid), + value: Int(self.request.target_uid), }, Extra { key: "pid", - value: Int(info.pid), + value: Int(self.cred.pid.as_()), }, Extra { key: "policy", - value: Int(policy.repr), + value: Int(self.settings.policy.repr), }, Extra { key: "target", - value: Int(info.request.target_pid), + value: Int(self.request.target_pid), }, Extra { key: "context", - value: Str(info.request.context.clone()), + value: Str(self.request.context.clone()), }, Extra { key: "gids", - value: IntList(info.request.gids.clone()), + value: IntList(self.request.gids.clone()), }, Extra { key: "command", @@ -275,10 +283,33 @@ impl MagiskD { }, Extra { key: "notify", - value: Bool(notify), + value: Bool(self.settings.notify), }, ]; - self.exec_cmd("log", &extras, info, true); + self.exec_cmd("log", &extras, true); + } + + pub(super) fn connect_app(&mut self) { + // If policy is undetermined, show dialog for user consent + if self.settings.policy == SuPolicy::Query { + self.app_request(); + } + + if !self.settings.log && !self.settings.notify { + return; + } + + if fork_dont_care() != 0 { + return; + } + + // Notify su usage to application + if self.settings.log { + self.app_log(); + } else if self.settings.notify { + self.app_notify(); + } + exit(0); } } diff --git a/native/src/core/su/daemon.rs b/native/src/core/su/daemon.rs index 98e30636b..1b36060e2 100644 --- a/native/src/core/su/daemon.rs +++ b/native/src/core/su/daemon.rs @@ -1,9 +1,10 @@ +use super::connect::SuAppContext; +use super::db::RootSettings; use crate::UCred; use crate::daemon::{AID_ROOT, AID_SHELL, MagiskD, to_app_id, to_user_id}; use crate::db::{DbSettings, MultiuserMode, RootAccess}; -use crate::ffi::{SuAppRequest, SuPolicy, SuRequest, exec_root_shell}; +use crate::ffi::{SuPolicy, SuRequest, exec_root_shell}; use crate::socket::IpcRead; -use crate::su::db::RootSettings; use base::{LoggedResult, ResultExt, WriteExt, debug, error, exit_on_error, libc, warn}; use std::os::fd::{FromRawFd, IntoRawFd}; use std::os::unix::net::UnixStream; @@ -29,11 +30,11 @@ impl Default for SuRequest { } pub struct SuInfo { - uid: i32, - eval_uid: i32, + pub(super) uid: i32, + pub(super) eval_uid: i32, + pub(super) mgr_pkg: String, + pub(super) mgr_uid: i32, cfg: DbSettings, - mgr_pkg: String, - mgr_uid: i32, access: Mutex, } @@ -129,37 +130,18 @@ impl MagiskD { }; let info = self.get_su_info(cred.uid as i32); - let app_req = SuAppRequest { - uid: cred.uid as i32, - pid: cred.pid, - eval_uid: info.eval_uid, - mgr_pkg: &info.mgr_pkg, - mgr_uid: info.mgr_uid, - request: &req, - }; - { let mut access = info.access.lock().unwrap(); - if access.settings.policy == SuPolicy::Query { - if let Ok(mut fd) = self.app_request(&app_req) { - access.settings.policy = SuPolicy { - repr: fd - .read_decodable::() - .log() - .map(i32::from_be) - .unwrap_or(SuPolicy::Deny.repr), - }; - } else { - access.settings.policy = SuPolicy::Deny; - } - } - - if access.settings.log { - self.app_log(&app_req, access.settings.policy, access.settings.notify); - } else if access.settings.notify { - self.app_notify(&app_req, access.settings.policy); - } + // Talk to su manager + let mut app = SuAppContext { + cred, + request: &req, + info: &info, + settings: &mut access.settings, + sdk_int: self.sdk_int(), + }; + app.connect_app(); // Before unlocking, refresh the timestamp access.refresh(); @@ -286,9 +268,9 @@ impl MagiskD { Arc::new(SuInfo { uid, eval_uid, - cfg, mgr_pkg, mgr_uid, + cfg, access: Mutex::new(AccessInfo::new(access)), }) };