Skip to content

Commit 04bf0b4

Browse files
committed
Use rust to implement collect/reset overlay context
1 parent c40dfae commit 04bf0b4

File tree

5 files changed

+56
-55
lines changed

5 files changed

+56
-55
lines changed

native/src/external/crt0

Submodule crt0 updated 1 file

native/src/init/lib.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
#![feature(format_args_nl)]
2+
#![feature(once_cell_try)]
23

34
use logging::setup_klog;
45
use mount::{is_device_mounted, switch_root};
5-
use rootdir::inject_magisk_rc;
6+
use rootdir::{inject_magisk_rc, collect_overlay_contexts, reset_overlay_contexts};
67
// Has to be pub so all symbols in that crate is included
78
pub use magiskpolicy;
89

@@ -18,6 +19,8 @@ pub mod ffi {
1819
fn inject_magisk_rc(fd: i32, tmp_dir: Utf8CStrRef);
1920
fn switch_root(path: Utf8CStrRef);
2021
fn is_device_mounted(dev: u64, target: Pin<&mut CxxString>) -> bool;
22+
fn collect_overlay_contexts(src: Utf8CStrRef) -> bool;
23+
fn reset_overlay_contexts() -> bool;
2124
}
2225

2326
unsafe extern "C++" {

native/src/init/rootdir.cpp

+1-50
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
#include <sys/mount.h>
22
#include <libgen.h>
33
#include <sys/sysmacros.h>
4-
#include <syscall.h>
5-
#include <sys/xattr.h>
64

75
#include <sepolicy.hpp>
86
#include <consts.hpp>
@@ -16,13 +14,6 @@ using namespace std;
1614
static vector<string> rc_list;
1715
static string magic_mount_list;
1816

19-
struct FileContext {
20-
std::string path;
21-
std::string con;
22-
};
23-
24-
static std::vector<FileContext> mount_contexts;
25-
2617
#define NEW_INITRC_DIR "/system/etc/init/hw"
2718
#define INIT_RC "init.rc"
2819

@@ -50,46 +41,6 @@ static void magic_mount(const string &sdir, const string &ddir = "") {
5041
}
5142
}
5243

53-
static int setfilecon(const char* path, const char* con) {
54-
int ret = syscall(__NR_setxattr, path, XATTR_NAME_SELINUX, con, strlen(con) + 1, 0);
55-
if (ret == -1) PLOGE("setfilecon %s %s", path, con);
56-
return ret;
57-
}
58-
59-
static std::string getfilecon(const char* path) {
60-
char buf[1024];
61-
ssize_t sz = syscall(__NR_getxattr, path, XATTR_NAME_SELINUX, buf, sizeof(buf));
62-
if (sz == -1) {
63-
PLOGE("getfilecon %s", path);
64-
return "";
65-
}
66-
return buf;
67-
}
68-
69-
static void collect_overlay_contexts(const string &sdir, const string &ddir = "") {
70-
auto dir = xopen_dir(sdir.data());
71-
if (!dir) return;
72-
for (dirent *entry; (entry = xreaddir(dir.get()));) {
73-
string src = sdir + "/" + entry->d_name;
74-
string dest = ddir + "/" + entry->d_name;
75-
if (access(dest.data(), F_OK) == 0) {
76-
if (entry->d_type == DT_DIR) {
77-
// Recursive
78-
collect_overlay_contexts(src, dest);
79-
} else {
80-
mount_contexts.emplace_back(dest, getfilecon(dest.data()));
81-
}
82-
}
83-
}
84-
}
85-
86-
void reset_overlay_contexts() {
87-
for (auto &attr: mount_contexts) {
88-
LOGD("set %s -> %s", attr.path.c_str(), attr.con.c_str());
89-
setfilecon(attr.path.c_str(), attr.con.c_str());
90-
}
91-
}
92-
9344
static void patch_rc_scripts(const char *src_path, const char *tmp_path, bool writable) {
9445
auto src_dir = xopen_dir(src_path);
9546
if (!src_dir) return;
@@ -380,7 +331,7 @@ void MagiskInit::patch_ro_root() {
380331
// Extract overlay archives
381332
extract_files(false);
382333

383-
collect_overlay_contexts(ROOTOVL);
334+
rust::collect_overlay_contexts(ROOTOVL);
384335

385336
// Oculus Go will use a special sepolicy if unlocked
386337
if (access("/sepolicy.unlocked", F_OK) == 0) {

native/src/init/rootdir.rs

+49-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,57 @@
1+
use base::{debug, libc, Directory, LibcReturn, ResultExt, Utf8CStr, Utf8CStrBuf, Utf8CStrBufArr, WalkResult};
12
use std::fs::File;
23
use std::io::Write;
34
use std::mem;
45
use std::os::fd::{FromRawFd, RawFd};
6+
use std::sync::OnceLock;
57

6-
use base::{debug, Utf8CStr};
8+
pub static OVERLAY_ATTRS: OnceLock<Vec<(String, String)>> = OnceLock::new();
9+
10+
const XATTR_NAME_SELINUX: &[u8] = b"security.selinux\0";
11+
12+
pub fn collect_overlay_contexts(src: &Utf8CStr) -> bool {
13+
OVERLAY_ATTRS.get_or_try_init(|| -> Result<_, std::io::Error> {
14+
let mut contexts = vec![];
15+
let mut con = Utf8CStrBufArr::default();
16+
let mut path = Utf8CStrBufArr::default();
17+
Directory::open(src)?.post_order_walk(|f| {
18+
f.path(&mut path)?;
19+
20+
unsafe {
21+
let sz = libc::lgetxattr(
22+
path.as_ptr(),
23+
XATTR_NAME_SELINUX.as_ptr().cast(),
24+
con.as_mut_ptr().cast(),
25+
con.capacity(),
26+
);
27+
con.set_len((sz - 1) as usize);
28+
}
29+
30+
debug!("collect context: {:?} -> {:?}", path, con);
31+
contexts.push((path.to_string(), con.to_string()));
32+
Ok(WalkResult::Continue)
33+
})?;
34+
Ok(contexts)
35+
}).is_ok()
36+
}
37+
38+
pub fn reset_overlay_contexts() -> bool {
39+
OVERLAY_ATTRS.get().map(|attrs| {
40+
for (dest, con) in attrs.iter() {
41+
debug!("set context: {} -> {}", dest, con);
42+
unsafe {
43+
libc::lsetxattr(
44+
dest.as_ptr().cast(),
45+
XATTR_NAME_SELINUX.as_ptr().cast(),
46+
con.as_ptr().cast(),
47+
con.len() + 1,
48+
0,
49+
).as_os_err().log().ok()?;
50+
}
51+
}
52+
Some(())
53+
}).is_some()
54+
}
755

856
pub fn inject_magisk_rc(fd: RawFd, tmp_dir: &Utf8CStr) {
957
debug!("Injecting magisk rc");

native/src/init/selinux.cpp

+1-2
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,7 @@ bool MagiskInit::hijack_sepolicy() {
132132
sepol->to_file(SELINUX_LOAD);
133133

134134
// restore mounted files' context after sepolicy loaded
135-
void reset_overlay_contexts();
136-
reset_overlay_contexts();
135+
rust::reset_overlay_contexts();
137136

138137
// Write to the enforce node ONLY after sepolicy is loaded. We need to make sure
139138
// the actual init process is blocked until sepolicy is loaded, or else

0 commit comments

Comments
 (0)