From f75d15c6f66d65ac93486426880e81a3a44eae06 Mon Sep 17 00:00:00 2001 From: Nullptr Date: Wed, 8 Feb 2023 16:38:39 +0800 Subject: [PATCH] Linker namespace --- README.md | 6 ++-- zygiskd/src/dl.rs | 82 +++++++++++++++++++++++++++++++++++++++++++ zygiskd/src/main.rs | 1 + zygiskd/src/zygisk.rs | 11 ++---- 4 files changed, 89 insertions(+), 11 deletions(-) create mode 100644 zygiskd/src/dl.rs diff --git a/README.md b/README.md index a41cfa5..3cc87b4 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,9 @@ Warning: The current version of Zygisksu is UNSTABLE. You may suffer boot loop o ## Requirements -+ Minimal KernelSU version: 15 -+ Minimal ksud version: 7b32c0e ++ Minimal KernelSU version: 10575 ++ Minimal ksud version: 10200 ++ Full SELinux patch support (If non-gki kernel) ## Compatibility @@ -22,6 +23,7 @@ Warning: The current version of Zygisksu is UNSTABLE. You may suffer boot loop o - [x] [Inject] Basic Zygisk loader - [x] [Inject] Stabilize injector - [x] [Inject] Unload +- [x] [Daemon] Linker namespace - [ ] [Daemon] Separate zygiskd process - [ ] [Daemon] Handle 64 bit only devices - [ ] [Daemon] Handle zygote death diff --git a/zygiskd/src/dl.rs b/zygiskd/src/dl.rs new file mode 100644 index 0000000..b212dd7 --- /dev/null +++ b/zygiskd/src/dl.rs @@ -0,0 +1,82 @@ +use anyhow::{bail, Result}; +use std::ffi::{c_char, c_void}; +use nix::libc; + +const ANDROID_NAMESPACE_TYPE_SHARED: u64 = 0x2; +const ANDROID_DLEXT_USE_NAMESPACE: u64 = 0x200; + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +struct AndroidNamespace { + _unused: [u8; 0], +} + +#[repr(C)] +struct AndroidDlextinfo { + pub flags: u64, + pub reserved_addr: *mut c_void, + pub reserved_size: libc::size_t, + pub relro_fd: libc::c_int, + pub library_fd: libc::c_int, + pub library_fd_offset: libc::off64_t, + pub library_namespace: *mut AndroidNamespace, +} + +extern "C" { + fn android_dlopen_ext( + filename: *const c_char, + flags: libc::c_int, + extinfo: *const AndroidDlextinfo, + ) -> *mut c_void; +} + +type AndroidCreateNamespaceFn = unsafe extern "C" fn( + *const c_char, // name + *const c_char, // ld_library_path + *const c_char, // default_library_path + u64, // type + *const c_char, // permitted_when_isolated_path + *mut AndroidNamespace, // parent + *const c_void, // caller_addr +) -> *mut AndroidNamespace; + +pub unsafe fn dlopen(path: &str, flags: i32) -> Result<*mut c_void> { + let filename = std::ffi::CString::new(path)?; + let filename = filename.as_ptr() as *mut _; + let dir = libc::dirname(filename); + let mut info = AndroidDlextinfo { + flags: 0, + reserved_addr: std::ptr::null_mut(), + reserved_size: 0, + relro_fd: 0, + library_fd: 0, + library_fd_offset: 0, + library_namespace: std::ptr::null_mut(), + }; + + let android_create_namespace_fn = libc::dlsym( + libc::RTLD_DEFAULT, + std::ffi::CString::new("__loader_android_create_namespace")?.as_ptr(), + ); + let android_create_namespace_fn: AndroidCreateNamespaceFn = std::mem::transmute(android_create_namespace_fn); + let ns = android_create_namespace_fn( + filename, dir, std::ptr::null(), + ANDROID_NAMESPACE_TYPE_SHARED, + std::ptr::null(), std::ptr::null_mut(), + &dlopen as *const _ as *const c_void, + ); + if ns != std::ptr::null_mut() { + info.flags = ANDROID_DLEXT_USE_NAMESPACE; + info.library_namespace = ns; + log::debug!("Open {} with namespace {:p}", path, ns); + } else { + log::debug!("Cannot create namespace for {}", path); + }; + + let result = android_dlopen_ext(filename, flags, &info); + if result.is_null() { + let e = std::ffi::CStr::from_ptr(libc::dlerror()).to_string_lossy(); + bail!("dlopen failed: {}", e); + } + Ok(result) +} diff --git a/zygiskd/src/main.rs b/zygiskd/src/main.rs index 0a5f1d8..8010f3f 100644 --- a/zygiskd/src/main.rs +++ b/zygiskd/src/main.rs @@ -1,6 +1,7 @@ #![allow(dead_code)] mod constants; +mod dl; mod utils; mod watchdog; mod zygisk; diff --git a/zygiskd/src/zygisk.rs b/zygiskd/src/zygisk.rs index e47c7c7..1ef263a 100644 --- a/zygiskd/src/zygisk.rs +++ b/zygiskd/src/zygisk.rs @@ -1,6 +1,6 @@ use crate::constants::DaemonSocketAction; use crate::utils::{restore_native_bridge, UnixStreamExt}; -use crate::{constants, utils}; +use crate::{constants, dl, utils}; use anyhow::{bail, Result}; use memfd::Memfd; use nix::{ @@ -151,14 +151,7 @@ fn create_memfd(name: &str, so_path: &PathBuf) -> Result { fn preload_module(memfd: &Memfd) -> Result> { unsafe { let path = format!("/proc/self/fd/{}", memfd.as_raw_fd()); - let filename = std::ffi::CString::new(path)?; - let handle = libc::dlopen(filename.as_ptr(), libc::RTLD_LAZY); - if handle.is_null() { - let e = std::ffi::CStr::from_ptr(libc::dlerror()) - .to_string_lossy() - .into_owned(); - bail!("dlopen failed: {}", e); - } + let handle = dl::dlopen(&path, libc::RTLD_NOW)?; let symbol = std::ffi::CString::new("zygisk_companion_entry")?; let entry = dlsym(handle, symbol.as_ptr()); if entry.is_null() {