Skip to content

Commit

Permalink
Fix overlay.d context preservation
Browse files Browse the repository at this point in the history
  • Loading branch information
topjohnwu committed Feb 18, 2025
1 parent 0399cde commit b7e0161
Show file tree
Hide file tree
Showing 10 changed files with 208 additions and 193 deletions.
34 changes: 24 additions & 10 deletions native/src/base/cstr.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
use cxx::{type_id, ExternType};
use libc::c_char;
use std::borrow::Borrow;
use std::cmp::min;
use std::ffi::{CStr, FromBytesWithNulError, OsStr};
use std::fmt::{Arguments, Debug, Display, Formatter, Write};
use std::fmt::{Debug, Display, Formatter, Write};
use std::ops::{Deref, DerefMut};
use std::os::unix::ffi::OsStrExt;
use std::path::{Path, PathBuf};
use std::str::Utf8Error;
use std::{fmt, mem, slice, str};

use cxx::{type_id, ExternType};
use libc::c_char;
use thiserror::Error;

use crate::slice_from_ptr_mut;
Expand Down Expand Up @@ -263,6 +263,12 @@ impl From<String> for Utf8CString {
}
}

impl Borrow<Utf8CStr> for Utf8CString {
fn borrow(&self) -> &Utf8CStr {
self.deref()
}
}

// UTF-8 validated + null terminated reference to buffer
pub struct Utf8CStrBufRef<'a> {
used: usize,
Expand Down Expand Up @@ -359,7 +365,7 @@ impl Utf8CStr {
}

#[inline(always)]
pub unsafe fn from_bytes_unchecked(buf: &[u8]) -> &Utf8CStr {
pub const unsafe fn from_bytes_unchecked(buf: &[u8]) -> &Utf8CStr {
mem::transmute(buf)
}

Expand Down Expand Up @@ -432,6 +438,16 @@ impl DerefMut for Utf8CStr {
}
}

impl ToOwned for Utf8CStr {
type Owned = Utf8CString;

fn to_owned(&self) -> Utf8CString {
let mut s = Utf8CString::with_capacity(self.len() + 1);
s.push_str(self.as_str());
s
}
}

// Notice that we only implement ExternType on Utf8CStr *reference*
unsafe impl ExternType for &Utf8CStr {
type Id = type_id!("rust::Utf8CStr");
Expand Down Expand Up @@ -535,7 +551,8 @@ impl<const N: usize> FsPathBuf<N> {
fn inner(buf: &mut dyn Utf8CStrBuf, path: &str) {
if path.starts_with('/') {
buf.clear();
} else {
}
if !buf.is_empty() && !buf.ends_with('/') {
buf.push_str("/");
}
buf.push_str(path);
Expand All @@ -545,10 +562,7 @@ impl<const N: usize> FsPathBuf<N> {
}

pub fn join_fmt<T: Display>(mut self, name: T) -> Self {
fn inner(buf: &mut dyn Utf8CStrBuf, path: Arguments) {
buf.write_fmt(path).ok();
}
inner(self.0.deref_mut(), format_args!("/{}", name));
self.0.write_fmt(format_args!("/{}", name)).ok();
self
}
}
Expand Down
85 changes: 54 additions & 31 deletions native/src/base/files.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
use crate::cxx_extern::readlinkat_for_cxx;
use crate::{
cstr, cstr_buf, errno, error, FsPath, FsPathBuf, LibcReturn, Utf8CStr, Utf8CStrBuf,
Utf8CStrBufArr,
};
use crate::{cstr, cstr_buf, errno, error, FsPath, FsPathBuf, LibcReturn, Utf8CStr, Utf8CStrBuf};
use bytemuck::{bytes_of, bytes_of_mut, Pod};
use libc::{
c_uint, dirent, makedev, mode_t, EEXIST, ENOENT, F_OK, O_CLOEXEC, O_CREAT, O_PATH, O_RDONLY,
Expand Down Expand Up @@ -142,15 +139,15 @@ impl<T: Write> WriteExt for T {
pub struct FileAttr {
pub st: libc::stat,
#[cfg(feature = "selinux")]
pub con: Utf8CStrBufArr<128>,
pub con: crate::Utf8CStrBufArr<128>,
}

impl FileAttr {
fn new() -> Self {
FileAttr {
st: unsafe { mem::zeroed() },
#[cfg(feature = "selinux")]
con: Utf8CStrBufArr::new(),
con: crate::Utf8CStrBufArr::new(),
}
}

Expand Down Expand Up @@ -189,7 +186,6 @@ impl FileAttr {
}
}

#[cfg(feature = "selinux")]
const XATTR_NAME_SELINUX: &[u8] = b"security.selinux\0";

pub struct DirEntry<'a> {
Expand All @@ -199,7 +195,7 @@ pub struct DirEntry<'a> {
}

impl DirEntry<'_> {
pub fn d_name(&self) -> &CStr {
pub fn name(&self) -> &CStr {
unsafe {
CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts(
self.d_name.as_ptr().cast(),
Expand All @@ -211,7 +207,7 @@ impl DirEntry<'_> {
pub fn path(&self, buf: &mut dyn Utf8CStrBuf) -> io::Result<()> {
self.dir.path(buf)?;
buf.push_str("/");
buf.push_lossy(self.d_name().to_bytes());
buf.push_lossy(self.name().to_bytes());
Ok(())
}

Expand Down Expand Up @@ -267,7 +263,7 @@ impl DirEntry<'_> {
}

unsafe fn open_fd(&self, flags: i32) -> io::Result<RawFd> {
self.dir.open_raw_fd(self.d_name(), flags, 0)
self.dir.open_raw_fd(self.name(), flags, 0)
}

pub fn open_as_dir(&self) -> io::Result<Directory> {
Expand Down Expand Up @@ -295,6 +291,18 @@ impl DirEntry<'_> {
self.path(&mut path)?;
FsPath::from(&path).set_attr(attr)
}

pub fn get_secontext(&self, con: &mut dyn Utf8CStrBuf) -> io::Result<()> {
let mut path = cstr_buf::default();
self.path(&mut path)?;
FsPath::from(&path).get_secontext(con)
}

pub fn set_secontext(&self, con: &Utf8CStr) -> io::Result<()> {
let mut path = cstr_buf::default();
self.path(&mut path)?;
FsPath::from(&path).set_secontext(con)
}
}

impl Deref for DirEntry<'_> {
Expand Down Expand Up @@ -424,7 +432,7 @@ impl Directory {
let mut src = e.open_as_file(O_RDONLY)?;
let mut dest = unsafe {
File::from_raw_fd(dir.open_raw_fd(
e.d_name(),
e.name(),
O_WRONLY | O_CREAT | O_TRUNC,
0o777,
)?)
Expand All @@ -447,7 +455,7 @@ impl Directory {
pub fn move_into(&mut self, dir: &Directory) -> io::Result<()> {
let dir_fd = self.as_raw_fd();
while let Some(ref e) = self.read()? {
if e.is_dir() && dir.contains_path(e.d_name()) {
if e.is_dir() && dir.contains_path(e.name()) {
// Destination folder exists, needs recursive move
let mut src = e.open_as_dir()?;
let new_entry = DirEntry {
Expand Down Expand Up @@ -621,7 +629,7 @@ impl FsPath {
pub fn read_link(&self, buf: &mut dyn Utf8CStrBuf) -> io::Result<()> {
buf.clear();
unsafe {
let r = libc::readlink(self.as_ptr(), buf.as_mut_ptr().cast(), buf.capacity() - 1)
let r = libc::readlink(self.as_ptr(), buf.as_mut_ptr(), buf.capacity() - 1)
.check_os_err()? as isize;
*(buf.as_mut_ptr().offset(r) as *mut u8) = b'\0';
buf.set_len(r as usize);
Expand Down Expand Up @@ -698,16 +706,7 @@ impl FsPath {
libc::lstat(self.as_ptr(), &mut attr.st).as_os_err()?;

#[cfg(feature = "selinux")]
{
let sz = libc::lgetxattr(
self.as_ptr(),
XATTR_NAME_SELINUX.as_ptr().cast(),
attr.con.as_mut_ptr().cast(),
attr.con.capacity(),
)
.check_os_err()?;
attr.con.set_len((sz - 1) as usize);
}
self.get_secontext(&mut attr.con)?;
}
Ok(attr)
}
Expand All @@ -721,19 +720,43 @@ impl FsPath {

#[cfg(feature = "selinux")]
if !attr.con.is_empty() {
libc::lsetxattr(
self.as_ptr(),
XATTR_NAME_SELINUX.as_ptr().cast(),
attr.con.as_ptr().cast(),
attr.con.len() + 1,
0,
)
.as_os_err()?;
self.set_secontext(&attr.con)?;
}
}
Ok(())
}

pub fn get_secontext(&self, con: &mut dyn Utf8CStrBuf) -> io::Result<()> {
unsafe {
let sz = libc::lgetxattr(
self.as_ptr(),
XATTR_NAME_SELINUX.as_ptr().cast(),
con.as_mut_ptr().cast(),
con.capacity(),
)
.check_os_err()?;
if sz < 1 {
con.clear();
} else {
con.set_len((sz - 1) as usize);
}
}
Ok(())
}

pub fn set_secontext(&self, con: &Utf8CStr) -> io::Result<()> {
unsafe {
libc::lsetxattr(
self.as_ptr(),
XATTR_NAME_SELINUX.as_ptr().cast(),
con.as_ptr().cast(),
con.len() + 1,
0,
)
.as_os_err()
}
}

pub fn copy_to(&self, path: &FsPath) -> io::Result<()> {
let attr = self.get_attr()?;
if attr.is_dir() {
Expand Down
2 changes: 1 addition & 1 deletion native/src/core/package.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ fn find_apk_path(pkg: &str, buf: &mut dyn Utf8CStrBuf) -> io::Result<()> {
if !e.is_dir() {
return Ok(Skip);
}
let name_bytes = e.d_name().to_bytes();
let name_bytes = e.name().to_bytes();
if name_bytes.starts_with(pkg.as_bytes()) && name_bytes[pkg.len()] == b'-' {
// Found the APK path, we can abort now
e.path(buf)?;
Expand Down
2 changes: 1 addition & 1 deletion native/src/core/resetprop/persist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ pub fn persist_get_props(mut prop_cb: Pin<&mut PropCb>) {
let mut dir = Directory::open(cstr!(PERSIST_PROP_DIR))?;
dir.pre_order_walk(|e| {
if e.is_file() {
if let Ok(name) = Utf8CStr::from_cstr(e.d_name()) {
if let Ok(name) = Utf8CStr::from_cstr(e.name()) {
if let Ok(mut value) = file_get_prop(name) {
prop_cb.exec(name, Utf8CStr::from_string(&mut value));
}
Expand Down
2 changes: 2 additions & 0 deletions native/src/include/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,5 @@ pub const MODULEMNT: &str = concatcp!(INTERNAL_DIR, "/modules");
pub const WORKERDIR: &str = concatcp!(INTERNAL_DIR, "/worker");
pub const DEVICEDIR: &str = concatcp!(INTERNAL_DIR, "/device");
pub const PREINITDEV: &str = concatcp!(DEVICEDIR, "/preinit");
pub const ROOTOVL: &str = concatcp!(INTERNAL_DIR, "/rootdir");
pub const ROOTMNT: &str = concatcp!(ROOTOVL, "/.mount_list");
1 change: 1 addition & 0 deletions native/src/init/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ impl MagiskInit {
Self {
preinit_dev: String::new(),
mount_list: Vec::new(),
overlay_con: Vec::new(),
argv,
config: BootConfig {
skip_initramfs: false,
Expand Down
11 changes: 8 additions & 3 deletions native/src/init/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ use logging::setup_klog;
// Has to be pub so all symbols in that crate is included
pub use magiskpolicy;
use mount::{is_device_mounted, switch_root};
use rootdir::{collect_overlay_contexts, inject_magisk_rc, reset_overlay_contexts};
use rootdir::{inject_magisk_rc, OverlayAttr};

#[path = "../include/consts.rs"]
mod consts;
mod getinfo;
mod init;
mod logging;
Expand Down Expand Up @@ -43,6 +45,7 @@ pub mod ffi {
mount_list: Vec<String>,
argv: *mut *mut c_char,
config: BootConfig,
overlay_con: Vec<OverlayAttr>,
}

unsafe extern "C++" {
Expand All @@ -62,8 +65,6 @@ pub mod ffi {
fn inject_magisk_rc(fd: i32, tmp_dir: Utf8CStrRef);
fn switch_root(path: Utf8CStrRef);
fn is_device_mounted(dev: u64, target: Pin<&mut CxxString>) -> bool;
fn collect_overlay_contexts(src: Utf8CStrRef);
fn reset_overlay_contexts();
}

// BootConfig
Expand All @@ -78,8 +79,11 @@ pub mod ffi {

// MagiskInit
extern "Rust" {
type OverlayAttr;
fn patch_sepolicy(self: &MagiskInit, src: Utf8CStrRef, out: Utf8CStrRef);
fn parse_config_file(self: &mut MagiskInit);
fn mount_overlay(self: &mut MagiskInit, dest: Utf8CStrRef);
fn restore_overlay_contexts(self: &MagiskInit);
}
unsafe extern "C++" {
// Used in Rust
Expand All @@ -93,5 +97,6 @@ pub mod ffi {
fn mount_preinit_dir(self: &MagiskInit);
unsafe fn find_block(self: &MagiskInit, partname: *const c_char) -> u64;
fn hijack_sepolicy(self: &mut MagiskInit) -> bool;
unsafe fn patch_fissiond(self: &mut MagiskInit, tmp_path: *const c_char);
}
}
Loading

0 comments on commit b7e0161

Please sign in to comment.