Guard log FIFO with SELinux

This commit is contained in:
topjohnwu 2023-11-04 23:59:11 -07:00
parent 72b39594d3
commit ac5ceb18c8
7 changed files with 43 additions and 19 deletions

View File

@ -4,7 +4,9 @@
use base::Utf8CStr; use base::Utf8CStr;
use cert::read_certificate; use cert::read_certificate;
use daemon::{daemon_entry, find_apk_path, get_magiskd, MagiskD}; use daemon::{daemon_entry, find_apk_path, get_magiskd, MagiskD};
use logging::{android_logging, magisk_logging, zygisk_logging}; use logging::{
android_logging, magisk_logging, zygisk_close_logd, zygisk_get_logd, zygisk_logging,
};
use resetprop::{persist_delete_prop, persist_get_prop, persist_get_props, persist_set_prop}; use resetprop::{persist_delete_prop, persist_get_prop, persist_get_props, persist_set_prop};
mod cert; mod cert;
@ -30,6 +32,8 @@ pub mod ffi {
fn android_logging(); fn android_logging();
fn magisk_logging(); fn magisk_logging();
fn zygisk_logging(); fn zygisk_logging();
fn zygisk_close_logd();
fn zygisk_get_logd() -> i32;
fn find_apk_path(pkg: &[u8], data: &mut [u8]) -> usize; fn find_apk_path(pkg: &[u8], data: &mut [u8]) -> usize;
fn read_certificate(fd: i32, version: i32) -> Vec<u8>; fn read_certificate(fd: i32, version: i32) -> Vec<u8>;
unsafe fn persist_get_prop(name: *const c_char, prop_cb: Pin<&mut PropCb>); unsafe fn persist_get_prop(name: *const c_char, prop_cb: Pin<&mut PropCb>);

View File

@ -165,19 +165,13 @@ fn magisk_log_to_pipe(prio: i32, msg: &Utf8CStr) {
static ZYGISK_LOGD: AtomicI32 = AtomicI32::new(-1); static ZYGISK_LOGD: AtomicI32 = AtomicI32::new(-1);
#[no_mangle] pub fn zygisk_close_logd() {
extern "C" fn zygisk_close_logd() {
unsafe { unsafe {
libc::close(ZYGISK_LOGD.swap(-1, Ordering::Relaxed)); libc::close(ZYGISK_LOGD.swap(-1, Ordering::Relaxed));
} }
} }
#[no_mangle] pub fn zygisk_get_logd() -> i32 {
extern "C" fn zygisk_get_logd() -> i32 {
ZYGISK_LOGD.load(Ordering::Relaxed)
}
fn zygisk_log_to_pipe(prio: i32, msg: &Utf8CStr) {
// If we don't have the log pipe set, open the log pipe FIFO. This could actually happen // If we don't have the log pipe set, open the log pipe FIFO. 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.
@ -207,10 +201,18 @@ fn zygisk_log_to_pipe(prio: i32, msg: &Utf8CStr) {
libc::close(ZYGISK_LOGD.swap(fd, Ordering::Relaxed)); libc::close(ZYGISK_LOGD.swap(fd, Ordering::Relaxed));
} }
} else { } else {
// Cannot talk to pipe, abort return -1;
return;
} }
} }
fd
}
fn zygisk_log_to_pipe(prio: i32, msg: &Utf8CStr) {
let fd = zygisk_get_logd();
if fd < 0 {
// Cannot talk to pipe, abort
return;
}
// Block SIGPIPE // Block SIGPIPE
let mut mask: sigset_t; let mut mask: sigset_t;

View File

@ -135,5 +135,5 @@ void restore_tmpcon() {
setfilecon_at(dfd, entry->d_name, SYSTEM_CON); setfilecon_at(dfd, entry->d_name, SYSTEM_CON);
string logd = tmp + "/"s LOG_PIPE; string logd = tmp + "/"s LOG_PIPE;
setfilecon(logd.data(), MAGISK_FILE_CON); setfilecon(logd.data(), MAGISK_LOG_CON);
} }

View File

@ -38,6 +38,9 @@ constexpr const char *applet_names[] = { "su", "resetprop", nullptr };
// Unconstrained file type that anyone can access // Unconstrained file type that anyone can access
#define SEPOL_FILE_TYPE "magisk_file" #define SEPOL_FILE_TYPE "magisk_file"
#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
#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")

View File

@ -19,6 +19,8 @@ void sepolicy::magisk_rules() {
typeattribute(SEPOL_PROC_DOMAIN, "bluetoothdomain"); typeattribute(SEPOL_PROC_DOMAIN, "bluetoothdomain");
type(SEPOL_FILE_TYPE, "file_type"); type(SEPOL_FILE_TYPE, "file_type");
typeattribute(SEPOL_FILE_TYPE, "mlstrustedobject"); typeattribute(SEPOL_FILE_TYPE, "mlstrustedobject");
type(SEPOL_LOG_TYPE, "file_type");
typeattribute(SEPOL_LOG_TYPE, "mlstrustedobject");
// Make our root domain unconstrained // Make our root domain unconstrained
allow(SEPOL_PROC_DOMAIN, ALL, ALL, ALL); allow(SEPOL_PROC_DOMAIN, ALL, ALL, ALL);
@ -37,10 +39,17 @@ void sepolicy::magisk_rules() {
allow(ALL, SEPOL_FILE_TYPE, "lnk_file", ALL); allow(ALL, SEPOL_FILE_TYPE, "lnk_file", ALL);
allow(ALL, SEPOL_FILE_TYPE, "sock_file", ALL); allow(ALL, SEPOL_FILE_TYPE, "sock_file", ALL);
// Allow these processes to access MagiskSU // Only allow zygote to open log pipe
const char *clients[]{"zygote", "shell", allow("zygote", SEPOL_LOG_TYPE, "fifo_file", "open");
"system_app", "platform_app", "priv_app", allow("zygote", SEPOL_LOG_TYPE, "fifo_file", "read");
"untrusted_app", "untrusted_app_all"}; // Allow all processes to output logs
allow("domain", SEPOL_LOG_TYPE, "fifo_file", "write");
// Allow these processes to access MagiskSU and output logs
const char *clients[] {
"zygote", "shell", "system_app", "platform_app",
"priv_app", "untrusted_app", "untrusted_app_all"
};
for (auto type: clients) { for (auto type: clients) {
if (!exists(type)) if (!exists(type))
continue; continue;

View File

@ -167,6 +167,14 @@ DCL_HOOK_FUNC(int, unshare, int flags) {
return res; return res;
} }
// This is the last moment before the secontext of the process changes
DCL_HOOK_FUNC(int, selinux_android_setcontext,
uid_t uid, bool isSystemServer, const char *seinfo, const char *pkgname) {
// Pre-fetch logd before secontext transition
zygisk_get_logd();
return old_selinux_android_setcontext(uid, isSystemServer, seinfo, pkgname);
}
// Close file descriptors to prevent crashing // Close file descriptors to prevent crashing
DCL_HOOK_FUNC(void, android_log_close) { DCL_HOOK_FUNC(void, android_log_close) {
if (g_ctx == nullptr || !g_ctx->flags[SKIP_CLOSE_LOG_PIPE]) { if (g_ctx == nullptr || !g_ctx->flags[SKIP_CLOSE_LOG_PIPE]) {
@ -745,6 +753,7 @@ void hook_functions() {
PLT_HOOK_REGISTER(android_runtime_dev, android_runtime_inode, fork); PLT_HOOK_REGISTER(android_runtime_dev, android_runtime_inode, fork);
PLT_HOOK_REGISTER(android_runtime_dev, android_runtime_inode, unshare); PLT_HOOK_REGISTER(android_runtime_dev, android_runtime_inode, unshare);
PLT_HOOK_REGISTER(android_runtime_dev, android_runtime_inode, androidSetCreateThreadFunc); PLT_HOOK_REGISTER(android_runtime_dev, android_runtime_inode, androidSetCreateThreadFunc);
PLT_HOOK_REGISTER(android_runtime_dev, android_runtime_inode, selinux_android_setcontext);
PLT_HOOK_REGISTER_SYM(android_runtime_dev, android_runtime_inode, "__android_log_close", android_log_close); PLT_HOOK_REGISTER_SYM(android_runtime_dev, android_runtime_inode, "__android_log_close", android_log_close);
hook_commit(); hook_commit();

View File

@ -36,9 +36,6 @@ enum : int {
#define HIJACK_BIN HIJACK_BIN32 #define HIJACK_BIN HIJACK_BIN32
#endif #endif
extern "C" int zygisk_get_logd();
extern "C" void zygisk_close_logd();
// Unmap all pages matching the name // Unmap all pages matching the name
void unmap_all(const char *name); void unmap_all(const char *name);