diff --git a/native/src/core/daemon.rs b/native/src/core/daemon.rs index 14bb6602e..04c3b2633 100644 --- a/native/src/core/daemon.rs +++ b/native/src/core/daemon.rs @@ -17,6 +17,24 @@ pub struct MagiskD { is_emulator: bool, } +impl MagiskD { + pub fn is_emulator(&self) -> bool { + self.is_emulator + } +} + +mod cxx_extern { + use base::libc::c_char; + + extern "C" { + pub fn get_magisk_tmp() -> *const c_char; + } +} + +pub fn get_magisk_tmp() -> &'static Utf8CStr { + unsafe { Utf8CStr::from_ptr(cxx_extern::get_magisk_tmp()).unwrap_unchecked() } +} + pub fn daemon_entry() { let mut qemu = get_prop(cstr!("ro.kernel.qemu"), false); if qemu.is_empty() { @@ -43,12 +61,6 @@ pub fn get_magiskd() -> &'static MagiskD { unsafe { MAGISKD.get().unwrap_unchecked() } } -impl MagiskD { - pub fn is_emulator(&self) -> bool { - self.is_emulator - } -} - pub fn find_apk_path(pkg: &[u8], data: &mut [u8]) -> usize { use WalkResult::*; fn inner(pkg: &[u8], buf: &mut dyn Utf8CStrBuf) -> io::Result { diff --git a/native/src/core/logging.rs b/native/src/core/logging.rs index 97f325551..97a8d1066 100644 --- a/native/src/core/logging.rs +++ b/native/src/core/logging.rs @@ -3,7 +3,7 @@ use std::ffi::{c_char, c_void}; use std::fmt::Write as FmtWrite; use std::fs::File; use std::io::{IoSlice, Read, Write}; -use std::os::fd::{AsRawFd, FromRawFd, RawFd}; +use std::os::fd::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; use std::ptr::null_mut; use std::{fs, io}; @@ -12,15 +12,15 @@ use num_derive::{FromPrimitive, ToPrimitive}; use num_traits::FromPrimitive; use base::libc::{ - clock_gettime, getpid, gettid, localtime_r, pipe2, pthread_sigmask, sigaddset, sigset_t, - sigtimedwait, timespec, tm, CLOCK_REALTIME, O_CLOEXEC, PIPE_BUF, SIGPIPE, SIG_BLOCK, + clock_gettime, getpid, gettid, localtime_r, pthread_sigmask, sigaddset, sigset_t, sigtimedwait, + timespec, tm, CLOCK_REALTIME, O_CLOEXEC, O_RDWR, O_WRONLY, PIPE_BUF, SIGPIPE, SIG_BLOCK, SIG_SETMASK, }; use base::*; -use crate::daemon::{MagiskD, MAGISKD}; +use crate::daemon::{get_magisk_tmp, MagiskD, MAGISKD}; use crate::logging::LogFile::{Actual, Buffer}; -use crate::LOGFILE; +use crate::{LOGFILE, LOG_PIPE}; #[allow(dead_code, non_camel_case_types)] #[derive(FromPrimitive, ToPrimitive)] @@ -59,9 +59,7 @@ fn level_to_prio(level: LogLevel) -> i32 { pub fn android_logging() { fn android_log_write(level: LogLevel, msg: &Utf8CStr) { - unsafe { - __android_log_write(level_to_prio(level), raw_cstr!("Magisk"), msg.as_ptr()); - } + write_android_log(level_to_prio(level), msg); } let logger = Logger { @@ -76,9 +74,7 @@ pub fn android_logging() { pub fn magisk_logging() { fn magisk_log_write(level: LogLevel, msg: &Utf8CStr) { - unsafe { - __android_log_write(level_to_prio(level), raw_cstr!("Magisk"), msg.as_ptr()); - } + write_android_log(level_to_prio(level), msg); magisk_log_to_pipe(level_to_prio(level), msg); } @@ -94,9 +90,7 @@ pub fn magisk_logging() { pub fn zygisk_logging() { fn zygisk_log_write(level: LogLevel, msg: &Utf8CStr) { - unsafe { - __android_log_write(level_to_prio(level), raw_cstr!("Magisk"), msg.as_ptr()); - } + write_android_log(level_to_prio(level), msg); zygisk_log_to_pipe(level_to_prio(level), msg); } @@ -119,6 +113,19 @@ struct LogMeta { tid: i32, } +fn print_log_error(msg: &str, e: io::Error) { + let mut buf = Utf8CStrBufArr::default(); + buf.write_fmt(format_args_nl!("Error in {}: {}", msg, e)) + .ok(); + write_android_log(level_to_prio(LogLevel::Error), &buf); +} + +fn write_android_log(prio: i32, msg: &Utf8CStr) { + unsafe { + __android_log_write(prio, raw_cstr!("Magisk"), msg.as_ptr()); + } +} + const MAX_MSG_LEN: usize = PIPE_BUF - std::mem::size_of::(); fn write_log_to_pipe(logd: &mut File, prio: i32, msg: &Utf8CStr) -> io::Result { @@ -154,7 +161,8 @@ fn magisk_log_to_pipe(prio: i32, msg: &Utf8CStr) { let result = write_log_to_pipe(logd, prio, msg); // If any error occurs, shut down the logd pipe - if result.is_err() { + if let Err(e) = result { + print_log_error("magisk_log", e); *logd_ref = None; } } @@ -179,6 +187,8 @@ fn zygisk_log_to_pipe(prio: i32, msg: &Utf8CStr) { } let result = write_log_to_pipe(&mut logd, prio, msg); + // Make sure the file descriptor is not closed after out of scope + logd.into_raw_fd(); // Consume SIGPIPE if exists, then restore mask unsafe { @@ -189,7 +199,8 @@ fn zygisk_log_to_pipe(prio: i32, msg: &Utf8CStr) { } // If any error occurs, shut down the logd pipe - if result.is_err() { + if let Err(e) = result { + print_log_error("zygisk_log", e); unsafe { zygisk_close_logd(); } @@ -318,13 +329,19 @@ extern "C" fn logfile_writer(arg: *mut c_void) -> *mut c_void { impl MagiskD { pub fn start_log_daemon(&self) { - let mut fds: [i32; 2] = [0; 2]; + let mut buf = Utf8CStrBufArr::default(); + let path = FsPathBuf::new(&mut buf) + .join(get_magisk_tmp()) + .join(LOG_PIPE!()); + unsafe { - if pipe2(fds.as_mut_ptr(), O_CLOEXEC) == 0 { - let logd = self.logd.lock().unwrap(); - *logd.borrow_mut() = Some(File::from_raw_fd(fds[1])); - new_daemon_thread(logfile_writer, fds[0] as *mut c_void); - } + libc::mkfifo(path.as_ptr(), 0o200); + libc::chown(path.as_ptr(), 0, 0); + let read = libc::open(path.as_ptr(), O_RDWR | O_CLOEXEC); + let write = libc::open(path.as_ptr(), O_WRONLY | O_CLOEXEC); + let logd = self.logd.lock().unwrap(); + *logd.borrow_mut() = Some(File::from_raw_fd(write)); + new_daemon_thread(logfile_writer, read as *mut c_void); } } diff --git a/native/src/core/selinux.cpp b/native/src/core/selinux.cpp index db49407c0..61a719255 100644 --- a/native/src/core/selinux.cpp +++ b/native/src/core/selinux.cpp @@ -131,4 +131,7 @@ void restore_tmpcon() { for (dirent *entry; (entry = xreaddir(dir.get()));) setfilecon_at(dfd, entry->d_name, SYSTEM_CON); + + string logd = MAGISKTMP + "/" LOG_PIPE; + setfilecon(logd.data(), MAGISK_FILE_CON); } diff --git a/native/src/include/consts.rs b/native/src/include/consts.rs index a57d0272a..8fae0c4ba 100644 --- a/native/src/include/consts.rs +++ b/native/src/include/consts.rs @@ -6,3 +6,17 @@ macro_rules! LOGFILE { "/cache/magisk.log" }; } + +#[macro_export] +macro_rules! INTLROOT { + () => { + ".magisk" + }; +} + +#[macro_export] +macro_rules! LOG_PIPE { + () => { + concat!($crate::INTLROOT!(), "/log") + }; +} diff --git a/native/src/include/daemon.hpp b/native/src/include/daemon.hpp index ba3aaff4b..9f8a4983c 100644 --- a/native/src/include/daemon.hpp +++ b/native/src/include/daemon.hpp @@ -71,7 +71,7 @@ extern int app_process_32; extern int app_process_64; extern std::vector *module_list; -const char *get_magisk_tmp(); +extern "C" const char *get_magisk_tmp(); int connect_daemon(int req, bool create = false); // Poll control diff --git a/native/src/include/magisk.hpp b/native/src/include/magisk.hpp index 795a399dd..5ded1058f 100644 --- a/native/src/include/magisk.hpp +++ b/native/src/include/magisk.hpp @@ -26,6 +26,7 @@ extern std::string MAGISKTMP; #define SELINUXMOCK INTLROOT "/selinux" #define MAIN_CONFIG INTLROOT "/config" #define MAIN_SOCKET INTLROOT "/socket" +#define LOG_PIPE INTLROOT "/log" constexpr const char *applet_names[] = { "su", "resetprop", nullptr };