mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-01-12 01:03:38 +00:00
Implement logging purely in Rust
This commit is contained in:
parent
8c2ad3883a
commit
7518092ad2
@ -29,7 +29,6 @@ LOCAL_SRC_FILES := \
|
|||||||
core/scripting.cpp \
|
core/scripting.cpp \
|
||||||
core/restorecon.cpp \
|
core/restorecon.cpp \
|
||||||
core/module.cpp \
|
core/module.cpp \
|
||||||
core/logging.cpp \
|
|
||||||
core/thread.cpp \
|
core/thread.cpp \
|
||||||
resetprop/persist.cpp \
|
resetprop/persist.cpp \
|
||||||
resetprop/resetprop.cpp \
|
resetprop/resetprop.cpp \
|
||||||
|
37
native/src/Cargo.lock
generated
37
native/src/Cargo.lock
generated
@ -75,7 +75,7 @@ version = "1.0.94"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.15",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -183,6 +183,8 @@ version = "0.0.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"base",
|
"base",
|
||||||
"cxx",
|
"cxx",
|
||||||
|
"num-derive",
|
||||||
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -217,6 +219,26 @@ version = "2.5.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-derive"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 1.0.109",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-traits"
|
||||||
|
version = "0.2.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "once_cell"
|
||||||
version = "1.17.1"
|
version = "1.17.1"
|
||||||
@ -332,6 +354,17 @@ dependencies = [
|
|||||||
"windows-sys 0.48.0",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "1.0.109"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.15"
|
version = "2.0.15"
|
||||||
@ -373,7 +406,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 2.0.15",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
9
native/src/base/consts.rs
Normal file
9
native/src/base/consts.rs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
// We expose constant values as macros so that all constants are literals
|
||||||
|
// An advantage for doing this is that we can use concat!() on these values
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! LOGFILE {
|
||||||
|
() => {
|
||||||
|
"/cache/magisk.log"
|
||||||
|
};
|
||||||
|
}
|
@ -2,11 +2,13 @@
|
|||||||
|
|
||||||
pub use libc;
|
pub use libc;
|
||||||
|
|
||||||
|
pub use consts::*;
|
||||||
pub use files::*;
|
pub use files::*;
|
||||||
pub use logging::*;
|
pub use logging::*;
|
||||||
pub use misc::*;
|
pub use misc::*;
|
||||||
pub use xwrap::*;
|
pub use xwrap::*;
|
||||||
|
|
||||||
|
mod consts;
|
||||||
mod files;
|
mod files;
|
||||||
mod logging;
|
mod logging;
|
||||||
mod misc;
|
mod misc;
|
||||||
|
@ -130,7 +130,7 @@ uint64_t parse_uint64_hex(std::string_view s);
|
|||||||
int parse_int(std::string_view s);
|
int parse_int(std::string_view s);
|
||||||
|
|
||||||
using thread_entry = void *(*)(void *);
|
using thread_entry = void *(*)(void *);
|
||||||
int new_daemon_thread(thread_entry entry, void *arg = nullptr);
|
extern "C" int new_daemon_thread(thread_entry entry, void *arg = nullptr);
|
||||||
|
|
||||||
static inline bool str_contains(std::string_view s, std::string_view ss) {
|
static inline bool str_contains(std::string_view s, std::string_view ss) {
|
||||||
return s.find(ss) != std::string::npos;
|
return s.find(ss) != std::string::npos;
|
||||||
|
@ -151,3 +151,24 @@ pub unsafe fn slice_from_ptr_mut<'a, T>(buf: *mut T, len: usize) -> &'a mut [T]
|
|||||||
slice::from_raw_parts_mut(buf, len)
|
slice::from_raw_parts_mut(buf, len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait FlatData {
|
||||||
|
fn as_raw_bytes(&self) -> &[u8]
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
unsafe {
|
||||||
|
let self_ptr = self as *const Self as *const u8;
|
||||||
|
slice::from_raw_parts(self_ptr, std::mem::size_of::<Self>())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn as_raw_bytes_mut(&mut self) -> &mut [u8]
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
unsafe {
|
||||||
|
let self_ptr = self as *mut Self as *mut u8;
|
||||||
|
slice::from_raw_parts_mut(self_ptr, std::mem::size_of::<Self>())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -10,3 +10,5 @@ path = "lib.rs"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
base = { path = "../base" }
|
base = { path = "../base" }
|
||||||
cxx = { path = "../external/cxx-rs" }
|
cxx = { path = "../external/cxx-rs" }
|
||||||
|
num-traits = "0.2"
|
||||||
|
num-derive = "0.3"
|
||||||
|
@ -373,7 +373,7 @@ static void post_fs_data() {
|
|||||||
if (!check_data())
|
if (!check_data())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
setup_logfile(true);
|
rust::get_magiskd().setup_logfile();
|
||||||
|
|
||||||
LOGI("** post-fs-data mode running\n");
|
LOGI("** post-fs-data mode running\n");
|
||||||
|
|
||||||
@ -413,7 +413,7 @@ early_abort:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void late_start() {
|
static void late_start() {
|
||||||
setup_logfile(false);
|
rust::get_magiskd().setup_logfile();
|
||||||
|
|
||||||
LOGI("** late_start service mode running\n");
|
LOGI("** late_start service mode running\n");
|
||||||
|
|
||||||
@ -425,7 +425,7 @@ static void late_start() {
|
|||||||
|
|
||||||
static void boot_complete() {
|
static void boot_complete() {
|
||||||
boot_state |= FLAG_BOOT_COMPLETE;
|
boot_state |= FLAG_BOOT_COMPLETE;
|
||||||
setup_logfile(false);
|
rust::get_magiskd().setup_logfile();
|
||||||
|
|
||||||
LOGI("** boot-complete triggered\n");
|
LOGI("** boot-complete triggered\n");
|
||||||
|
|
||||||
|
@ -9,8 +9,6 @@ extern std::atomic<ino_t> pkg_xml_ino;
|
|||||||
std::string find_preinit_device();
|
std::string find_preinit_device();
|
||||||
void unlock_blocks();
|
void unlock_blocks();
|
||||||
void reboot();
|
void reboot();
|
||||||
void start_log_daemon();
|
|
||||||
void setup_logfile(bool reset);
|
|
||||||
std::string read_certificate(int fd, int version = -1);
|
std::string read_certificate(int fd, int version = -1);
|
||||||
|
|
||||||
// Module stuffs
|
// Module stuffs
|
||||||
|
@ -186,7 +186,7 @@ static void handle_request_sync(int client, int code) {
|
|||||||
write_string(client, MAGISKTMP.data());
|
write_string(client, MAGISKTMP.data());
|
||||||
break;
|
break;
|
||||||
case MainRequest::START_DAEMON:
|
case MainRequest::START_DAEMON:
|
||||||
setup_logfile(true);
|
rust::get_magiskd().setup_logfile();
|
||||||
break;
|
break;
|
||||||
case MainRequest::STOP_DAEMON:
|
case MainRequest::STOP_DAEMON:
|
||||||
denylist_handler(-1, nullptr);
|
denylist_handler(-1, nullptr);
|
||||||
@ -298,7 +298,7 @@ static void switch_cgroup(const char *cgroup, int pid) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void daemon_entry() {
|
static void daemon_entry() {
|
||||||
magisk_logging();
|
android_logging();
|
||||||
|
|
||||||
// Block all signals
|
// Block all signals
|
||||||
sigset_t block_set;
|
sigset_t block_set;
|
||||||
@ -321,7 +321,7 @@ static void daemon_entry() {
|
|||||||
setsid();
|
setsid();
|
||||||
setcon(MAGISK_PROC_CON);
|
setcon(MAGISK_PROC_CON);
|
||||||
|
|
||||||
start_log_daemon();
|
rust::daemon_entry();
|
||||||
|
|
||||||
LOGI(NAME_WITH_VER(Magisk) " daemon started\n");
|
LOGI(NAME_WITH_VER(Magisk) " daemon started\n");
|
||||||
|
|
||||||
|
31
native/src/core/daemon.rs
Normal file
31
native/src/core/daemon.rs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
use crate::logging::{magisk_logging, zygisk_logging};
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::sync::{Mutex, OnceLock};
|
||||||
|
|
||||||
|
// Global magiskd singleton
|
||||||
|
pub static MAGISKD: OnceLock<MagiskD> = OnceLock::new();
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct MagiskD {
|
||||||
|
pub logd: Mutex<RefCell<Option<File>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn daemon_entry() {
|
||||||
|
let magiskd = MagiskD::default();
|
||||||
|
magiskd.start_log_daemon();
|
||||||
|
MAGISKD.set(magiskd).ok();
|
||||||
|
magisk_logging();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn zygisk_entry() {
|
||||||
|
let magiskd = MagiskD::default();
|
||||||
|
MAGISKD.set(magiskd).ok();
|
||||||
|
zygisk_logging();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_magiskd() -> &'static MagiskD {
|
||||||
|
MAGISKD.get().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MagiskD {}
|
@ -1,6 +1,8 @@
|
|||||||
pub use base;
|
pub use base;
|
||||||
|
use daemon::*;
|
||||||
use logging::*;
|
use logging::*;
|
||||||
|
|
||||||
|
mod daemon;
|
||||||
mod logging;
|
mod logging;
|
||||||
|
|
||||||
#[cxx::bridge]
|
#[cxx::bridge]
|
||||||
@ -13,4 +15,18 @@ pub mod ffi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cxx::bridge(namespace = "rust")]
|
||||||
|
pub mod ffi2 {
|
||||||
|
extern "Rust" {
|
||||||
|
fn daemon_entry();
|
||||||
|
fn zygisk_entry();
|
||||||
|
|
||||||
|
type 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 rust_test_entry() {}
|
fn rust_test_entry() {}
|
||||||
|
@ -1,160 +0,0 @@
|
|||||||
#include <sys/uio.h>
|
|
||||||
#include <android/log.h>
|
|
||||||
|
|
||||||
#include <magisk.hpp>
|
|
||||||
#include <base.hpp>
|
|
||||||
#include <daemon.hpp>
|
|
||||||
#include <stream.hpp>
|
|
||||||
|
|
||||||
#include "core.hpp"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
struct log_meta {
|
|
||||||
int prio;
|
|
||||||
int len;
|
|
||||||
int pid;
|
|
||||||
int tid;
|
|
||||||
};
|
|
||||||
|
|
||||||
atomic<int> logd_fd = -1;
|
|
||||||
|
|
||||||
void setup_logfile(bool reset) {
|
|
||||||
if (logd_fd < 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
iovec iov{};
|
|
||||||
log_meta meta = {
|
|
||||||
.prio = -1,
|
|
||||||
.len = reset
|
|
||||||
};
|
|
||||||
|
|
||||||
iov.iov_base = &meta;
|
|
||||||
iov.iov_len = sizeof(meta);
|
|
||||||
writev(logd_fd, &iov, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Maximum message length for pipes to transfer atomically
|
|
||||||
#define MAX_MSG_LEN (int) (PIPE_BUF - sizeof(log_meta))
|
|
||||||
|
|
||||||
static void *logfile_writer(void *arg) {
|
|
||||||
int pipefd = (long) arg;
|
|
||||||
|
|
||||||
run_finally close_pipes([=] {
|
|
||||||
// Close up all logging pipes when thread dies
|
|
||||||
close(pipefd);
|
|
||||||
close(logd_fd.exchange(-1));
|
|
||||||
});
|
|
||||||
|
|
||||||
struct {
|
|
||||||
void *data;
|
|
||||||
size_t len;
|
|
||||||
} tmp{};
|
|
||||||
stream_ptr strm = make_unique<byte_stream>(tmp.data, tmp.len);
|
|
||||||
bool switched = false;
|
|
||||||
|
|
||||||
log_meta meta{};
|
|
||||||
char buf[MAX_MSG_LEN];
|
|
||||||
char aux[64];
|
|
||||||
|
|
||||||
iovec iov[2];
|
|
||||||
iov[0].iov_base = aux;
|
|
||||||
iov[1].iov_base = buf;
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
// Read meta data
|
|
||||||
if (read(pipefd, &meta, sizeof(meta)) != sizeof(meta))
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
if (meta.prio < 0) {
|
|
||||||
if (!switched) {
|
|
||||||
run_finally free_tmp([&] {
|
|
||||||
free(tmp.data);
|
|
||||||
tmp.data = nullptr;
|
|
||||||
tmp.len = 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
rename(LOGFILE, LOGFILE ".bak");
|
|
||||||
int fd = open(LOGFILE, O_WRONLY | O_APPEND | O_CREAT | O_CLOEXEC, 0644);
|
|
||||||
if (fd < 0)
|
|
||||||
return nullptr;
|
|
||||||
if (tmp.data)
|
|
||||||
write(fd, tmp.data, tmp.len);
|
|
||||||
|
|
||||||
strm = make_unique<fd_stream>(fd);
|
|
||||||
switched = true;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read message
|
|
||||||
if (read(pipefd, buf, meta.len) != meta.len)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
timeval tv;
|
|
||||||
tm tm;
|
|
||||||
gettimeofday(&tv, nullptr);
|
|
||||||
localtime_r(&tv.tv_sec, &tm);
|
|
||||||
|
|
||||||
// Format detailed info
|
|
||||||
char type;
|
|
||||||
switch (meta.prio) {
|
|
||||||
case ANDROID_LOG_DEBUG:
|
|
||||||
type = 'D';
|
|
||||||
break;
|
|
||||||
case ANDROID_LOG_INFO:
|
|
||||||
type = 'I';
|
|
||||||
break;
|
|
||||||
case ANDROID_LOG_WARN:
|
|
||||||
type = 'W';
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
type = 'E';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
long ms = tv.tv_usec / 1000;
|
|
||||||
size_t off = strftime(aux, sizeof(aux), "%m-%d %T", &tm);
|
|
||||||
off += ssprintf(aux + off, sizeof(aux) - off,
|
|
||||||
".%03ld %5d %5d %c : ", ms, meta.pid, meta.tid, type);
|
|
||||||
|
|
||||||
iov[0].iov_len = off;
|
|
||||||
iov[1].iov_len = meta.len;
|
|
||||||
|
|
||||||
strm->writev(iov, 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void magisk_log_write(int prio, const char *msg, int len) {
|
|
||||||
if (logd_fd < 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Truncate
|
|
||||||
len = std::min(MAX_MSG_LEN, len);
|
|
||||||
|
|
||||||
log_meta meta = {
|
|
||||||
.prio = prio,
|
|
||||||
.len = len,
|
|
||||||
.pid = getpid(),
|
|
||||||
.tid = gettid()
|
|
||||||
};
|
|
||||||
|
|
||||||
iovec iov[2];
|
|
||||||
iov[0].iov_base = &meta;
|
|
||||||
iov[0].iov_len = sizeof(meta);
|
|
||||||
iov[1].iov_base = (void *) msg;
|
|
||||||
iov[1].iov_len = len;
|
|
||||||
|
|
||||||
if (writev(logd_fd, iov, 2) < 0) {
|
|
||||||
// Stop trying to write to file
|
|
||||||
close(logd_fd.exchange(-1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void start_log_daemon() {
|
|
||||||
int fds[2];
|
|
||||||
if (pipe2(fds, O_CLOEXEC) == 0) {
|
|
||||||
logd_fd = fds[1];
|
|
||||||
long fd = fds[0];
|
|
||||||
new_daemon_thread(logfile_writer, (void *) fd);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,8 +1,27 @@
|
|||||||
use base::ffi::LogLevel;
|
use std::cmp::min;
|
||||||
use base::*;
|
use std::ffi::{c_char, c_void};
|
||||||
use std::fmt::Arguments;
|
use std::fmt::Arguments;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::{IoSlice, Read, Write};
|
||||||
|
use std::os::fd::{AsRawFd, FromRawFd, RawFd};
|
||||||
|
use std::ptr::null_mut;
|
||||||
|
use std::{fs, io};
|
||||||
|
|
||||||
|
use num_derive::{FromPrimitive, ToPrimitive};
|
||||||
|
use num_traits::FromPrimitive;
|
||||||
|
|
||||||
|
use base::ffi::LogLevel;
|
||||||
|
use base::libc::{
|
||||||
|
getpid, gettid, gettimeofday, localtime_r, pipe2, pthread_sigmask, sigaddset, sigset_t,
|
||||||
|
sigtimedwait, timespec, timeval, tm, O_CLOEXEC, PIPE_BUF, SIGPIPE, SIG_BLOCK, SIG_SETMASK,
|
||||||
|
};
|
||||||
|
use base::*;
|
||||||
|
|
||||||
|
use crate::daemon::{MagiskD, MAGISKD};
|
||||||
|
use crate::logging::LogFile::{Actual, Buffer};
|
||||||
|
|
||||||
#[allow(dead_code, non_camel_case_types)]
|
#[allow(dead_code, non_camel_case_types)]
|
||||||
|
#[derive(FromPrimitive, ToPrimitive)]
|
||||||
#[repr(i32)]
|
#[repr(i32)]
|
||||||
enum ALogPriority {
|
enum ALogPriority {
|
||||||
ANDROID_LOG_UNKNOWN = 0,
|
ANDROID_LOG_UNKNOWN = 0,
|
||||||
@ -16,10 +35,14 @@ enum ALogPriority {
|
|||||||
ANDROID_LOG_SILENT,
|
ANDROID_LOG_SILENT,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ThreadEntry = extern "C" fn(*mut c_void) -> *mut c_void;
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
fn __android_log_write(prio: i32, tag: *const u8, msg: *const u8);
|
fn __android_log_write(prio: i32, tag: *const c_char, msg: *const u8);
|
||||||
fn magisk_log_write(prio: i32, msg: *const u8, len: i32);
|
fn strftime(buf: *mut c_char, len: usize, fmt: *const c_char, tm: *const tm) -> usize;
|
||||||
fn zygisk_log_write(prio: i32, msg: *const u8, len: i32);
|
|
||||||
|
fn zygisk_fetch_logd() -> RawFd;
|
||||||
|
fn new_daemon_thread(entry: ThreadEntry, arg: *mut c_void);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn level_to_prio(level: LogLevel) -> i32 {
|
fn level_to_prio(level: LogLevel) -> i32 {
|
||||||
@ -37,12 +60,12 @@ pub fn android_logging() {
|
|||||||
let mut buf: [u8; 4096] = [0; 4096];
|
let mut buf: [u8; 4096] = [0; 4096];
|
||||||
fmt_to_buf(&mut buf, args);
|
fmt_to_buf(&mut buf, args);
|
||||||
unsafe {
|
unsafe {
|
||||||
__android_log_write(level_to_prio(level), b"Magisk\0".as_ptr(), buf.as_ptr());
|
__android_log_write(level_to_prio(level), str_ptr!("Magisk"), buf.as_ptr());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn android_log_write(level: LogLevel, msg: &[u8]) {
|
fn android_log_write(level: LogLevel, msg: &[u8]) {
|
||||||
unsafe {
|
unsafe {
|
||||||
__android_log_write(level_to_prio(level), b"Magisk\0".as_ptr(), msg.as_ptr());
|
__android_log_write(level_to_prio(level), str_ptr!("Magisk"), msg.as_ptr());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,15 +85,15 @@ pub fn magisk_logging() {
|
|||||||
let mut buf: [u8; 4096] = [0; 4096];
|
let mut buf: [u8; 4096] = [0; 4096];
|
||||||
let len = fmt_to_buf(&mut buf, args);
|
let len = fmt_to_buf(&mut buf, args);
|
||||||
unsafe {
|
unsafe {
|
||||||
__android_log_write(level_to_prio(level), b"Magisk\0".as_ptr(), buf.as_ptr());
|
__android_log_write(level_to_prio(level), str_ptr!("Magisk"), buf.as_ptr());
|
||||||
magisk_log_write(level_to_prio(level), buf.as_ptr(), len as i32);
|
|
||||||
}
|
}
|
||||||
|
magisk_log_write(level_to_prio(level), &buf[..len]);
|
||||||
}
|
}
|
||||||
fn magisk_write(level: LogLevel, msg: &[u8]) {
|
fn magisk_write(level: LogLevel, msg: &[u8]) {
|
||||||
unsafe {
|
unsafe {
|
||||||
__android_log_write(level_to_prio(level), b"Magisk\0".as_ptr(), msg.as_ptr());
|
__android_log_write(level_to_prio(level), str_ptr!("Magisk"), msg.as_ptr());
|
||||||
magisk_log_write(level_to_prio(level), msg.as_ptr(), msg.len() as i32);
|
|
||||||
}
|
}
|
||||||
|
magisk_log_write(level_to_prio(level), &msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
let logger = Logger {
|
let logger = Logger {
|
||||||
@ -89,15 +112,15 @@ pub fn zygisk_logging() {
|
|||||||
let mut buf: [u8; 4096] = [0; 4096];
|
let mut buf: [u8; 4096] = [0; 4096];
|
||||||
let len = fmt_to_buf(&mut buf, args);
|
let len = fmt_to_buf(&mut buf, args);
|
||||||
unsafe {
|
unsafe {
|
||||||
__android_log_write(level_to_prio(level), b"Magisk\0".as_ptr(), buf.as_ptr());
|
__android_log_write(level_to_prio(level), str_ptr!("Magisk"), buf.as_ptr());
|
||||||
zygisk_log_write(level_to_prio(level), buf.as_ptr(), len as i32);
|
|
||||||
}
|
}
|
||||||
|
zygisk_log_write(level_to_prio(level), &buf[..len]);
|
||||||
}
|
}
|
||||||
fn zygisk_write(level: LogLevel, msg: &[u8]) {
|
fn zygisk_write(level: LogLevel, msg: &[u8]) {
|
||||||
unsafe {
|
unsafe {
|
||||||
__android_log_write(level_to_prio(level), b"Magisk\0".as_ptr(), msg.as_ptr());
|
__android_log_write(level_to_prio(level), str_ptr!("Magisk"), msg.as_ptr());
|
||||||
zygisk_log_write(level_to_prio(level), msg.as_ptr(), msg.len() as i32);
|
|
||||||
}
|
}
|
||||||
|
zygisk_log_write(level_to_prio(level), &msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
let logger = Logger {
|
let logger = Logger {
|
||||||
@ -110,3 +133,250 @@ pub fn zygisk_logging() {
|
|||||||
LOGGER = logger;
|
LOGGER = logger;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
#[repr(C)]
|
||||||
|
struct LogMeta {
|
||||||
|
prio: i32,
|
||||||
|
len: i32,
|
||||||
|
pid: i32,
|
||||||
|
tid: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
const MAX_MSG_LEN: usize = PIPE_BUF - std::mem::size_of::<LogMeta>();
|
||||||
|
|
||||||
|
fn do_magisk_log_write(logd: &mut File, prio: i32, msg: &[u8]) -> io::Result<usize> {
|
||||||
|
// Truncate message if needed
|
||||||
|
let len = min(MAX_MSG_LEN, msg.len());
|
||||||
|
let msg = &msg[..len];
|
||||||
|
|
||||||
|
let meta = LogMeta {
|
||||||
|
prio,
|
||||||
|
len: len as i32,
|
||||||
|
pid: unsafe { getpid() },
|
||||||
|
tid: unsafe { gettid() },
|
||||||
|
};
|
||||||
|
|
||||||
|
let io1 = IoSlice::new(meta.as_raw_bytes());
|
||||||
|
let io2 = IoSlice::new(msg);
|
||||||
|
logd.write_vectored(&[io1, io2])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn magisk_log_write(prio: i32, msg: &[u8]) {
|
||||||
|
let magiskd = match MAGISKD.get() {
|
||||||
|
None => return,
|
||||||
|
Some(s) => s,
|
||||||
|
};
|
||||||
|
|
||||||
|
let logd_cell = magiskd.logd.lock().unwrap();
|
||||||
|
let mut logd_ref = logd_cell.borrow_mut();
|
||||||
|
let logd = match logd_ref.as_mut() {
|
||||||
|
None => return,
|
||||||
|
Some(s) => s,
|
||||||
|
};
|
||||||
|
|
||||||
|
let result = do_magisk_log_write(logd, prio, &msg);
|
||||||
|
|
||||||
|
// If any error occurs, shut down the logd pipe
|
||||||
|
if result.is_err() {
|
||||||
|
*logd_ref = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn zygisk_log_write(prio: i32, msg: &[u8]) {
|
||||||
|
let magiskd = match MAGISKD.get() {
|
||||||
|
None => return,
|
||||||
|
Some(s) => s,
|
||||||
|
};
|
||||||
|
|
||||||
|
let logd_cell = magiskd.logd.lock().unwrap();
|
||||||
|
let mut logd_ref = logd_cell.borrow_mut();
|
||||||
|
if logd_ref.is_none() {
|
||||||
|
android_logging();
|
||||||
|
unsafe {
|
||||||
|
let fd = zygisk_fetch_logd();
|
||||||
|
if fd < 0 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*logd_ref = Some(File::from_raw_fd(fd));
|
||||||
|
}
|
||||||
|
// Only re-enable zygisk logging if success
|
||||||
|
zygisk_logging();
|
||||||
|
};
|
||||||
|
let logd = logd_ref.as_mut().unwrap();
|
||||||
|
|
||||||
|
// Block SIGPIPE
|
||||||
|
let mut mask: sigset_t;
|
||||||
|
let mut orig_mask: sigset_t;
|
||||||
|
unsafe {
|
||||||
|
mask = std::mem::zeroed();
|
||||||
|
orig_mask = std::mem::zeroed();
|
||||||
|
sigaddset(&mut mask, SIGPIPE);
|
||||||
|
pthread_sigmask(SIG_BLOCK, &mask, &mut orig_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = do_magisk_log_write(logd, prio, &msg);
|
||||||
|
|
||||||
|
// Consume SIGPIPE if exists, then restore mask
|
||||||
|
unsafe {
|
||||||
|
let mut ts: timespec = std::mem::zeroed();
|
||||||
|
sigtimedwait(&mask, null_mut(), &ts);
|
||||||
|
pthread_sigmask(SIG_SETMASK, &orig_mask, null_mut());
|
||||||
|
}
|
||||||
|
|
||||||
|
// If any error occurs, shut down the logd pipe
|
||||||
|
if result.is_err() {
|
||||||
|
*logd_ref = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The following is implementation for the logging daemon
|
||||||
|
|
||||||
|
enum LogFile<'a> {
|
||||||
|
Buffer(&'a mut Vec<u8>),
|
||||||
|
Actual(File),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LogFile<'_> {
|
||||||
|
fn as_write(&mut self) -> &mut dyn Write {
|
||||||
|
match self {
|
||||||
|
Buffer(e) => e,
|
||||||
|
Actual(ref mut e) => e,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FlatData for LogMeta {}
|
||||||
|
|
||||||
|
extern "C" fn logfile_writer(arg: *mut c_void) -> *mut c_void {
|
||||||
|
fn writer_loop(pipefd: RawFd) -> io::Result<()> {
|
||||||
|
let mut pipe = unsafe { File::from_raw_fd(pipefd) };
|
||||||
|
let mut tmp = Vec::new();
|
||||||
|
let mut logfile: LogFile = Buffer(&mut tmp);
|
||||||
|
|
||||||
|
let mut meta = LogMeta::default();
|
||||||
|
let mut buf: [u8; MAX_MSG_LEN] = [0; MAX_MSG_LEN];
|
||||||
|
let mut aux: [u8; 64] = [0; 64];
|
||||||
|
|
||||||
|
loop {
|
||||||
|
// Read request
|
||||||
|
pipe.read_exact(meta.as_raw_bytes_mut())?;
|
||||||
|
|
||||||
|
if meta.prio < 0 {
|
||||||
|
if matches!(logfile, LogFile::Buffer(_)) {
|
||||||
|
fs::rename(LOGFILE!(), concat!(LOGFILE!(), ".bak")).ok();
|
||||||
|
let mut out = File::create(LOGFILE!())?;
|
||||||
|
out.write_all(tmp.as_slice())?;
|
||||||
|
tmp = Vec::new();
|
||||||
|
logfile = Actual(out);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if meta.len < 0 || meta.len > buf.len() as i32 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the rest of the message
|
||||||
|
let msg = &mut buf[..(meta.len as usize)];
|
||||||
|
pipe.read_exact(msg)?;
|
||||||
|
|
||||||
|
// Start building the log string
|
||||||
|
|
||||||
|
let prio =
|
||||||
|
ALogPriority::from_i32(meta.prio).unwrap_or(ALogPriority::ANDROID_LOG_UNKNOWN);
|
||||||
|
let prio = match prio {
|
||||||
|
ALogPriority::ANDROID_LOG_VERBOSE => 'V',
|
||||||
|
ALogPriority::ANDROID_LOG_DEBUG => 'D',
|
||||||
|
ALogPriority::ANDROID_LOG_INFO => 'I',
|
||||||
|
ALogPriority::ANDROID_LOG_WARN => 'W',
|
||||||
|
ALogPriority::ANDROID_LOG_ERROR => 'E',
|
||||||
|
// Unsupported values, skip
|
||||||
|
_ => continue,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Note: the obvious better implementation is to use the rust chrono crate, however
|
||||||
|
// the crate cannot fetch the proper local timezone without pulling in a bunch of
|
||||||
|
// timezone handling code. To reduce final binary size, fallback to use libc.
|
||||||
|
let mut aux_len: usize;
|
||||||
|
unsafe {
|
||||||
|
let mut tv: timeval = std::mem::zeroed();
|
||||||
|
let mut tm: tm = std::mem::zeroed();
|
||||||
|
gettimeofday(&mut tv, null_mut());
|
||||||
|
localtime_r(&tv.tv_sec, &mut tm);
|
||||||
|
aux_len = strftime(
|
||||||
|
aux.as_mut_ptr().cast(),
|
||||||
|
aux.len(),
|
||||||
|
str_ptr!("%m-%d %T"),
|
||||||
|
&tm,
|
||||||
|
) as usize;
|
||||||
|
let ms = tv.tv_usec / 1000;
|
||||||
|
aux_len += bfmt!(
|
||||||
|
&mut aux[aux_len..],
|
||||||
|
".{:03} {:5} {:5} {} : ",
|
||||||
|
ms,
|
||||||
|
meta.pid,
|
||||||
|
meta.tid,
|
||||||
|
prio
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let io1 = IoSlice::new(&aux[..aux_len]);
|
||||||
|
let io2 = IoSlice::new(msg);
|
||||||
|
logfile.as_write().write_vectored(&[io1, io2])?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
writer_loop(arg as RawFd).ok();
|
||||||
|
// If any error occurs, shut down the logd pipe
|
||||||
|
if let Some(magiskd) = MAGISKD.get() {
|
||||||
|
magiskd.close_log_pipe();
|
||||||
|
}
|
||||||
|
null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MagiskD {
|
||||||
|
pub fn start_log_daemon(&self) {
|
||||||
|
let mut fds: [i32; 2] = [0; 2];
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_log_pipe(&self) -> RawFd {
|
||||||
|
let logd_cell = self.logd.lock().unwrap();
|
||||||
|
let logd_ref = logd_cell.borrow();
|
||||||
|
let logd = logd_ref.as_ref();
|
||||||
|
match logd {
|
||||||
|
None => -1,
|
||||||
|
Some(s) => s.as_raw_fd(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn close_log_pipe(&self) {
|
||||||
|
let guard = self.logd.lock().unwrap();
|
||||||
|
*guard.borrow_mut() = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setup_logfile(&self) {
|
||||||
|
let logd_cell = self.logd.lock().unwrap();
|
||||||
|
let mut logd_ref = logd_cell.borrow_mut();
|
||||||
|
let logd = match logd_ref.as_mut() {
|
||||||
|
None => return,
|
||||||
|
Some(s) => s,
|
||||||
|
};
|
||||||
|
|
||||||
|
let meta = LogMeta {
|
||||||
|
prio: -1,
|
||||||
|
len: 0,
|
||||||
|
pid: 0,
|
||||||
|
tid: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
logd.write_all(meta.as_raw_bytes()).ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -83,10 +83,6 @@ void clear_poll();
|
|||||||
// Thread pool
|
// Thread pool
|
||||||
void exec_task(std::function<void()> &&task);
|
void exec_task(std::function<void()> &&task);
|
||||||
|
|
||||||
// Logging
|
|
||||||
extern std::atomic<int> logd_fd;
|
|
||||||
extern "C" void magisk_log_write(int prio, const char *msg, int len);
|
|
||||||
|
|
||||||
// Daemon handlers
|
// Daemon handlers
|
||||||
void boot_stage_handler(int client, int code);
|
void boot_stage_handler(int client, int code);
|
||||||
void denylist_handler(int client, const sock_cred *cred);
|
void denylist_handler(int client, const sock_cred *cred);
|
||||||
|
@ -41,7 +41,7 @@ extern "C" void unload_first_stage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void zygisk_inject_entry(void *handle) {
|
extern "C" void zygisk_inject_entry(void *handle) {
|
||||||
zygisk_logging();
|
rust::zygisk_entry();
|
||||||
ZLOGD("load success\n");
|
ZLOGD("load success\n");
|
||||||
|
|
||||||
char *ld = getenv("LD_PRELOAD");
|
char *ld = getenv("LD_PRELOAD");
|
||||||
@ -62,7 +62,7 @@ extern "C" void zygisk_inject_entry(void *handle) {
|
|||||||
|
|
||||||
// The following code runs in zygote/app process
|
// The following code runs in zygote/app process
|
||||||
|
|
||||||
extern "C" void zygisk_log_write(int prio, const char *msg, int len) {
|
extern "C" int zygisk_fetch_logd() {
|
||||||
// If we don't have the log pipe set, request magiskd for it. This could actually happen
|
// If we don't have the log pipe set, request magiskd for it. This could actually happen
|
||||||
// multiple times in the zygote daemon (parent process) because we had to close this
|
// multiple times in the zygote daemon (parent process) because we had to close this
|
||||||
// file descriptor to prevent crashing.
|
// file descriptor to prevent crashing.
|
||||||
@ -77,37 +77,18 @@ extern "C" void zygisk_log_write(int prio, const char *msg, int len) {
|
|||||||
// add this FD into fds_to_ignore to pass the check. For other cases, we accomplish this by
|
// add this FD into fds_to_ignore to pass the check. For other cases, we accomplish this by
|
||||||
// hooking __android_log_close and closing it at the same time as the rest of logging FDs.
|
// hooking __android_log_close and closing it at the same time as the rest of logging FDs.
|
||||||
|
|
||||||
if (logd_fd < 0) {
|
if (int fd = zygisk_request(ZygiskRequest::GET_LOG_PIPE); fd >= 0) {
|
||||||
android_logging();
|
int log_pipe = -1;
|
||||||
if (int fd = zygisk_request(ZygiskRequest::GET_LOG_PIPE); fd >= 0) {
|
if (read_int(fd) == 0) {
|
||||||
int log_pipe = -1;
|
log_pipe = recv_fd(fd);
|
||||||
if (read_int(fd) == 0) {
|
}
|
||||||
log_pipe = recv_fd(fd);
|
close(fd);
|
||||||
}
|
if (log_pipe >= 0) {
|
||||||
close(fd);
|
return log_pipe;
|
||||||
if (log_pipe >= 0) {
|
|
||||||
// Only re-enable zygisk logging if possible
|
|
||||||
logd_fd = log_pipe;
|
|
||||||
zygisk_logging();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Block SIGPIPE
|
return -1;
|
||||||
sigset_t mask;
|
|
||||||
sigset_t orig_mask;
|
|
||||||
sigemptyset(&mask);
|
|
||||||
sigaddset(&mask, SIGPIPE);
|
|
||||||
pthread_sigmask(SIG_BLOCK, &mask, &orig_mask);
|
|
||||||
|
|
||||||
magisk_log_write(prio, msg, len);
|
|
||||||
|
|
||||||
// Consume SIGPIPE if exists, then restore mask
|
|
||||||
timespec ts{};
|
|
||||||
sigtimedwait(&mask, nullptr, &ts);
|
|
||||||
pthread_sigmask(SIG_SETMASK, &orig_mask, nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool should_load_modules(uint32_t flags) {
|
static inline bool should_load_modules(uint32_t flags) {
|
||||||
@ -340,7 +321,7 @@ static void get_process_info(int client, const sock_cred *cred) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void send_log_pipe(int fd) {
|
static void send_log_pipe(int fd) {
|
||||||
// There is race condition here, but we can't really do much about it...
|
int logd_fd = rust::get_magiskd().get_log_pipe();
|
||||||
if (logd_fd >= 0) {
|
if (logd_fd >= 0) {
|
||||||
write_int(fd, 0);
|
write_int(fd, 0);
|
||||||
send_fd(fd, logd_fd);
|
send_fd(fd, logd_fd);
|
||||||
|
@ -20,6 +20,8 @@ using namespace std;
|
|||||||
using jni_hook::hash_map;
|
using jni_hook::hash_map;
|
||||||
using jni_hook::tree_map;
|
using jni_hook::tree_map;
|
||||||
using xstring = jni_hook::string;
|
using xstring = jni_hook::string;
|
||||||
|
using rust::MagiskD;
|
||||||
|
using rust::get_magiskd;
|
||||||
|
|
||||||
// Extreme verbose logging
|
// Extreme verbose logging
|
||||||
//#define ZLOGV(...) ZLOGD(__VA_ARGS__)
|
//#define ZLOGV(...) ZLOGD(__VA_ARGS__)
|
||||||
@ -67,6 +69,7 @@ struct HookContext {
|
|||||||
AppSpecializeArgs_v3 *app;
|
AppSpecializeArgs_v3 *app;
|
||||||
ServerSpecializeArgs_v1 *server;
|
ServerSpecializeArgs_v1 *server;
|
||||||
} args;
|
} args;
|
||||||
|
const MagiskD &magiskd;
|
||||||
|
|
||||||
const char *process;
|
const char *process;
|
||||||
list<ZygiskModule> modules;
|
list<ZygiskModule> modules;
|
||||||
@ -94,7 +97,7 @@ struct HookContext {
|
|||||||
vector<IgnoreInfo> ignore_info;
|
vector<IgnoreInfo> ignore_info;
|
||||||
|
|
||||||
HookContext(JNIEnv *env, void *args) :
|
HookContext(JNIEnv *env, void *args) :
|
||||||
env(env), args{args}, process(nullptr), pid(-1), info_flags(0),
|
env(env), args{args}, magiskd(get_magiskd()), process(nullptr), pid(-1), info_flags(0),
|
||||||
hook_info_lock(PTHREAD_MUTEX_INITIALIZER) {
|
hook_info_lock(PTHREAD_MUTEX_INITIALIZER) {
|
||||||
static bool restored_env = false;
|
static bool restored_env = false;
|
||||||
if (!restored_env) {
|
if (!restored_env) {
|
||||||
@ -171,9 +174,9 @@ DCL_HOOK_FUNC(int, unshare, int flags) {
|
|||||||
DCL_HOOK_FUNC(void, android_log_close) {
|
DCL_HOOK_FUNC(void, android_log_close) {
|
||||||
if (g_ctx == nullptr) {
|
if (g_ctx == nullptr) {
|
||||||
// Happens during un-managed fork like nativeForkApp, nativeForkUsap
|
// Happens during un-managed fork like nativeForkApp, nativeForkUsap
|
||||||
close(logd_fd.exchange(-1));
|
get_magiskd().close_log_pipe();
|
||||||
} else if (!g_ctx->flags[SKIP_FD_SANITIZATION]) {
|
} else if (!g_ctx->flags[SKIP_FD_SANITIZATION]) {
|
||||||
close(logd_fd.exchange(-1));
|
g_ctx->magiskd.close_log_pipe();
|
||||||
if (g_ctx->is_child()) {
|
if (g_ctx->is_child()) {
|
||||||
// Switch to plain old android logging because we cannot talk
|
// Switch to plain old android logging because we cannot talk
|
||||||
// to magiskd to fetch our log pipe afterwards anyways.
|
// to magiskd to fetch our log pipe afterwards anyways.
|
||||||
@ -484,6 +487,7 @@ void HookContext::sanitize_fds() {
|
|||||||
int dfd = dirfd(dir.get());
|
int dfd = dirfd(dir.get());
|
||||||
for (dirent *entry; (entry = xreaddir(dir.get()));) {
|
for (dirent *entry; (entry = xreaddir(dir.get()));) {
|
||||||
int fd = parse_int(entry->d_name);
|
int fd = parse_int(entry->d_name);
|
||||||
|
int logd_fd = magiskd.get_log_pipe();
|
||||||
if ((fd < 0 || fd >= MAX_FD_SIZE || !allowed_fds[fd]) && fd != dfd && fd != logd_fd) {
|
if ((fd < 0 || fd >= MAX_FD_SIZE || !allowed_fds[fd]) && fd != dfd && fd != logd_fd) {
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
@ -570,7 +574,7 @@ void HookContext::app_specialize_post() {
|
|||||||
|
|
||||||
// Cleanups
|
// Cleanups
|
||||||
env->ReleaseStringUTFChars(args.app->nice_name, process);
|
env->ReleaseStringUTFChars(args.app->nice_name, process);
|
||||||
close(logd_fd.exchange(-1));
|
magiskd.close_log_pipe();
|
||||||
android_logging();
|
android_logging();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -690,8 +694,11 @@ void HookContext::nativeForkAndSpecialize_pre() {
|
|||||||
// if fds_to_ignore does not exist and there's no FileDescriptorTable::Create,
|
// if fds_to_ignore does not exist and there's no FileDescriptorTable::Create,
|
||||||
// we can skip fd sanitization
|
// we can skip fd sanitization
|
||||||
flags[SKIP_FD_SANITIZATION] = !dlsym(RTLD_DEFAULT, "_ZN19FileDescriptorTable6CreateEv");
|
flags[SKIP_FD_SANITIZATION] = !dlsym(RTLD_DEFAULT, "_ZN19FileDescriptorTable6CreateEv");
|
||||||
} else if (logd_fd >= 0) {
|
} else {
|
||||||
exempted_fds.push_back(logd_fd);
|
int logd_fd = magiskd.get_log_pipe();
|
||||||
|
if (logd_fd >= 0) {
|
||||||
|
exempted_fds.push_back(logd_fd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fork_pre();
|
fork_pre();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user