Magisk/native/src/core/selinux.rs
2025-04-28 17:22:14 -07:00

109 lines
3.3 KiB
Rust

use crate::consts::{DATABIN, LOG_PIPE, MAGISK_LOG_CON, MODULEROOT, SECURE_DIR};
use crate::ffi::get_magisk_tmp;
use base::libc::{O_CLOEXEC, O_WRONLY};
use base::{Directory, FsPathBuilder, LoggedResult, ResultExt, Utf8CStr, Utf8CStrBuf, cstr, libc};
use std::io::Write;
const UNLABEL_CON: &Utf8CStr = cstr!("u:object_r:unlabeled:s0");
const SYSTEM_CON: &Utf8CStr = cstr!("u:object_r:system_file:s0");
const ADB_CON: &Utf8CStr = cstr!("u:object_r:adb_data_file:s0");
const ROOT_CON: &Utf8CStr = cstr!("u:object_r:rootfs:s0");
fn restore_syscon_from_unlabeled(
path: &mut dyn Utf8CStrBuf,
con: &mut dyn Utf8CStrBuf,
) -> LoggedResult<()> {
let dir_path_len = path.len();
if path.get_secontext(con).log().is_ok() && con.as_str() == UNLABEL_CON {
path.set_secontext(SYSTEM_CON)?;
}
let mut dir = Directory::open(path)?;
while let Some(ref e) = dir.read()? {
path.truncate(dir_path_len);
path.append_path(e.name());
if e.is_dir() {
restore_syscon_from_unlabeled(path, con)?;
} else if (e.is_file() || e.is_symlink())
&& path.get_secontext(con).log().is_ok()
&& con.as_str() == UNLABEL_CON
{
path.set_secontext(SYSTEM_CON)?;
}
}
Ok(())
}
fn restore_syscon(path: &mut dyn Utf8CStrBuf) -> LoggedResult<()> {
let dir_path_len = path.len();
path.set_secontext(SYSTEM_CON)?;
unsafe { libc::lchown(path.as_ptr(), 0, 0) };
let mut dir = Directory::open(path)?;
while let Some(ref e) = dir.read()? {
path.truncate(dir_path_len);
path.append_path(e.name());
if e.is_dir() {
restore_syscon(path)?;
} else if e.is_file() || e.is_symlink() {
path.set_secontext(SYSTEM_CON)?;
unsafe { libc::lchown(path.as_ptr(), 0, 0) };
}
}
Ok(())
}
pub(crate) fn restorecon() {
if let Ok(mut file) = cstr!("/sys/fs/selinux/context")
.open(O_WRONLY | O_CLOEXEC)
.log()
{
if file.write_all(ADB_CON.as_bytes_with_nul()).is_ok() {
cstr!(SECURE_DIR).set_secontext(ADB_CON).log_ok();
}
}
let mut path = cstr::buf::default();
let mut con = cstr::buf::new::<1024>();
path.push_str(MODULEROOT);
path.set_secontext(SYSTEM_CON).log_ok();
restore_syscon_from_unlabeled(&mut path, &mut con).log_ok();
path.clear();
path.push_str(DATABIN);
restore_syscon(&mut path).log_ok();
}
pub(crate) fn restore_tmpcon() -> LoggedResult<()> {
let tmp = get_magisk_tmp();
if tmp == "/sbin" {
tmp.set_secontext(ROOT_CON)?;
} else {
unsafe { libc::chmod(tmp.as_ptr(), 0o711) };
}
let mut path = cstr::buf::default();
let mut dir = Directory::open(tmp)?;
while let Some(ref e) = dir.read()? {
e.resolve_path(&mut path)?;
path.set_secontext(SYSTEM_CON)?;
}
path.clear();
path.append_path(tmp).append_path(LOG_PIPE);
path.set_secontext(cstr!(MAGISK_LOG_CON))?;
Ok(())
}
pub(crate) fn lgetfilecon(path: &Utf8CStr, con: &mut [u8]) -> bool {
let mut con = cstr::buf::wrap(con);
path.get_secontext(&mut con).is_ok()
}
pub(crate) fn setfilecon(path: &Utf8CStr, con: &Utf8CStr) -> bool {
path.follow_link().set_secontext(con).is_ok()
}
pub(crate) fn lsetfilecon(path: &Utf8CStr, con: &Utf8CStr) -> bool {
path.set_secontext(con).is_ok()
}