From 4d4195c02d7a85174f5c467f4a878dfdaddb8a13 Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Fri, 10 Jan 2025 09:04:56 +0800 Subject: [PATCH] Migrate prune_su_access to Rust --- native/src/Android.mk | 1 - native/src/Cargo.lock | 16 +++++++++++ native/src/Cargo.toml | 1 + native/src/core/Cargo.toml | 1 + native/src/core/daemon.cpp | 2 +- native/src/core/daemon.rs | 48 +++++++++++++++++++++++++++++--- native/src/core/db.rs | 6 +--- native/src/core/include/core.hpp | 6 ---- native/src/core/lib.rs | 4 +-- native/src/core/package.cpp | 39 -------------------------- native/src/core/su/mod.rs | 40 +++++++++++++++++++++++++- native/src/core/su/su_daemon.cpp | 28 ------------------- 12 files changed, 104 insertions(+), 88 deletions(-) delete mode 100644 native/src/core/package.cpp diff --git a/native/src/Android.mk b/native/src/Android.mk index 3ed0ca82d..2035c1a10 100644 --- a/native/src/Android.mk +++ b/native/src/Android.mk @@ -20,7 +20,6 @@ LOCAL_SRC_FILES := \ core/daemon.cpp \ core/bootstages.cpp \ core/socket.cpp \ - core/package.cpp \ core/scripting.cpp \ core/selinux.cpp \ core/sqlite.cpp \ diff --git a/native/src/Cargo.lock b/native/src/Cargo.lock index d08543eeb..e7625de60 100644 --- a/native/src/Cargo.lock +++ b/native/src/Cargo.lock @@ -70,6 +70,21 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[package]] +name = "bit-set" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + [[package]] name = "block-buffer" version = "0.11.0-rc.3" @@ -442,6 +457,7 @@ name = "magisk" version = "0.0.0" dependencies = [ "base", + "bit-set", "bytemuck", "cxx", "cxx-gen", diff --git a/native/src/Cargo.toml b/native/src/Cargo.toml index 799c54db8..85c4853fe 100644 --- a/native/src/Cargo.toml +++ b/native/src/Cargo.toml @@ -25,6 +25,7 @@ der = "0.8.0-rc.1" bytemuck = "1.16" fdt = "0.1" const_format = "0.2" +bit-set = "0.8" [workspace.dependencies.argh] git = "https://github.com/google/argh.git" diff --git a/native/src/core/Cargo.toml b/native/src/core/Cargo.toml index 8f5d97a32..25862b66b 100644 --- a/native/src/core/Cargo.toml +++ b/native/src/core/Cargo.toml @@ -23,3 +23,4 @@ num-derive = { workspace = true } quick-protobuf = { workspace = true } bytemuck = { workspace = true, features = ["derive"] } thiserror = { workspace = true } +bit-set = { workspace = true } diff --git a/native/src/core/daemon.cpp b/native/src/core/daemon.cpp index 5c98b5cd9..b2a6ad50d 100644 --- a/native/src/core/daemon.cpp +++ b/native/src/core/daemon.cpp @@ -144,7 +144,7 @@ static void handle_request_async(int client, int code, const sock_cred &cred) { break; case +RequestCode::ZYGOTE_RESTART: LOGI("** zygote restarted\n"); - prune_su_access(); + MagiskD().prune_su_access(); scan_deny_apps(); reset_zygisk(false); close(client); diff --git a/native/src/core/daemon.rs b/native/src/core/daemon.rs index abcf65b60..d0cae8a16 100644 --- a/native/src/core/daemon.rs +++ b/native/src/core/daemon.rs @@ -5,7 +5,11 @@ use crate::get_prop; use crate::logging::{magisk_logging, start_log_daemon}; use crate::package::ManagerInfo; use base::libc::{O_CLOEXEC, O_RDONLY}; -use base::{cstr, info, libc, open_fd, BufReadExt, FsPath, FsPathBuf, ReadExt, Utf8CStrBufArr}; +use base::{ + cstr, info, libc, open_fd, BufReadExt, DirEntry, Directory, FsPath, FsPathBuf, LoggedResult, + ReadExt, Utf8CStr, Utf8CStrBufArr, +}; +use bit_set::BitSet; use bytemuck::bytes_of; use std::fs::File; use std::io; @@ -37,6 +41,8 @@ impl BootStateFlags { } } +pub const AID_APP_START: i32 = 10000; +pub const AID_APP_END: i32 = 19999; pub const AID_USER_OFFSET: i32 = 100000; pub const fn to_app_id(uid: i32) -> i32 { @@ -62,14 +68,48 @@ impl MagiskD { self.sdk_int } - pub fn app_data_dir(&self) -> &'static str { + pub fn app_data_dir(&self) -> &'static Utf8CStr { if self.sdk_int >= 24 { - "/data/user_de" + cstr!("/data/user_de") } else { - "/data/user" + cstr!("/data/user") } } + // app_id = app_no + AID_APP_START + // app_no range: [0, 9999] + pub fn get_app_no_list(&self) -> BitSet { + let mut list = BitSet::new(); + let _: LoggedResult<()> = try { + let mut dir = Directory::open(self.app_data_dir())?; + // For each user + loop { + let entry: DirEntry; + match dir.read()? { + None => break, + Some(e) => entry = e, + } + if let Ok(mut dir) = entry.open_as_dir() { + // For each package + loop { + match dir.read()? { + None => break, + Some(e) => { + let attr = e.get_attr()?; + let app_id = to_app_id(attr.st.st_uid as i32); + if app_id >= AID_APP_START && app_id <= AID_APP_END { + let app_no = app_id - AID_APP_START; + list.insert(app_no as usize); + } + } + } + } + } + } + }; + list + } + pub fn boot_stage_handler(&self, client: i32, code: i32) { // Make sure boot stage execution is always serialized let mut state = self.boot_stage_lock.lock().unwrap(); diff --git a/native/src/core/db.rs b/native/src/core/db.rs index dc872c967..1f6ff64a5 100644 --- a/native/src/core/db.rs +++ b/native/src/core/db.rs @@ -213,7 +213,7 @@ impl MagiskD { ) } - fn db_exec(&self, sql: &str, args: &[DbArg]) -> i32 { + pub fn db_exec(&self, sql: &str, args: &[DbArg]) -> i32 { self.db_exec_impl(sql, args, None, ptr::null_mut()) } @@ -308,10 +308,6 @@ impl MagiskD { self.set_db_setting(key, value).log().is_ok() } - pub fn rm_db_string_for_cxx(&self, key: DbEntryKey) -> bool { - self.rm_db_string(key).log().is_ok() - } - pub fn db_exec_for_cxx(&self, client_fd: RawFd) { // Take ownership let fd = unsafe { OwnedFd::from_raw_fd(client_fd) }; diff --git a/native/src/core/include/core.hpp b/native/src/core/include/core.hpp index baeafe4b2..1282c0fb4 100644 --- a/native/src/core/include/core.hpp +++ b/native/src/core/include/core.hpp @@ -12,8 +12,6 @@ #define AID_ROOT 0 #define AID_SHELL 2000 -#define AID_APP_START 10000 -#define AID_APP_END 19999 #define AID_USER_OFFSET 100000 #define to_app_id(uid) (uid % AID_USER_OFFSET) @@ -60,10 +58,6 @@ void denylist_handler(int client, const sock_cred *cred); void su_daemon_handler(int client, const sock_cred *cred); void zygisk_handler(int client, const sock_cred *cred); -// Package -std::vector get_app_no_list(); -void prune_su_access(); - // Module stuffs void handle_modules(); void load_modules(); diff --git a/native/src/core/lib.rs b/native/src/core/lib.rs index def3578cc..42d100e0b 100644 --- a/native/src/core/lib.rs +++ b/native/src/core/lib.rs @@ -181,6 +181,7 @@ pub mod ffi { fn sdk_int(&self) -> i32; fn boot_stage_handler(&self, client: i32, code: i32); fn preserve_stub_apk(&self); + fn prune_su_access(&self); #[cxx_name = "get_manager"] unsafe fn get_manager_for_cxx(&self, user: i32, ptr: *mut CxxString, install: bool) -> i32; @@ -189,9 +190,6 @@ pub mod ffi { fn get_db_setting(&self, key: DbEntryKey) -> i32; #[cxx_name = "set_db_setting"] fn set_db_setting_for_cxx(&self, key: DbEntryKey, value: i32) -> bool; - fn get_db_string(&self, key: DbEntryKey) -> String; - #[cxx_name = "rm_db_string"] - fn rm_db_string_for_cxx(&self, key: DbEntryKey) -> bool; #[cxx_name = "db_exec"] fn db_exec_for_cxx(&self, client_fd: i32); #[cxx_name = "get_root_settings"] diff --git a/native/src/core/package.cpp b/native/src/core/package.cpp deleted file mode 100644 index 5abbbd05a..000000000 --- a/native/src/core/package.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include -#include -#include -#include -#include - -using namespace std; - -// app_id = app_no + AID_APP_START -// app_no range: [0, 9999] -vector get_app_no_list() { - vector list; - auto data_dir = xopen_dir(APP_DATA_DIR); - if (!data_dir) - return list; - dirent *entry; - while ((entry = xreaddir(data_dir.get()))) { - // For each user - int dfd = xopenat(dirfd(data_dir.get()), entry->d_name, O_RDONLY); - if (auto dir = xopen_dir(dfd)) { - while ((entry = xreaddir(dir.get()))) { - // For each package - struct stat st{}; - xfstatat(dfd, entry->d_name, &st, 0); - int app_id = to_app_id(st.st_uid); - if (app_id >= AID_APP_START && app_id <= AID_APP_END) { - int app_no = app_id - AID_APP_START; - if (list.size() <= app_no) { - list.resize(app_no + 1); - } - list[app_no] = true; - } - } - } else { - close(dfd); - } - } - return list; -} diff --git a/native/src/core/su/mod.rs b/native/src/core/su/mod.rs index e329f6094..40f9c4daf 100644 --- a/native/src/core/su/mod.rs +++ b/native/src/core/su/mod.rs @@ -1,4 +1,4 @@ -use crate::daemon::MagiskD; +use crate::daemon::{to_app_id, MagiskD, AID_APP_END, AID_APP_START}; use crate::db::DbArg::Integer; use crate::db::{SqlTable, SqliteResult, SqliteReturn}; use crate::ffi::{DbValues, RootSettings, SuPolicy}; @@ -35,6 +35,14 @@ impl SqlTable for RootSettings { } } +struct UidList(Vec); + +impl SqlTable for UidList { + fn on_row(&mut self, _: &[String], values: &DbValues) { + self.0.push(values.get_int(0)); + } +} + impl MagiskD { fn get_root_settings(&self, uid: i32, settings: &mut RootSettings) -> SqliteResult { self.db_exec_with_rows( @@ -49,6 +57,36 @@ impl MagiskD { pub fn get_root_settings_for_cxx(&self, uid: i32, settings: &mut RootSettings) -> bool { self.get_root_settings(uid, settings).log().is_ok() } + + pub fn prune_su_access(&self) { + let mut list = UidList(Vec::new()); + if self + .db_exec_with_rows("SELECT uid FROM policies", &[], &mut list) + .sql_result() + .log() + .is_err() + { + return; + } + + let app_list = self.get_app_no_list(); + let mut rm_uids = Vec::new(); + + for uid in list.0 { + let app_id = to_app_id(uid); + if app_id >= AID_APP_START && app_id <= AID_APP_END { + let app_no = app_id - AID_APP_START; + if !app_list.contains(app_no as usize) { + // The app_id is no longer installed + rm_uids.push(uid); + } + } + } + + for uid in rm_uids { + self.db_exec("DELETE FROM policies WHERE uid=?", &[Integer(uid as i64)]); + } + } } pub fn get_default_root_settings() -> RootSettings { diff --git a/native/src/core/su/su_daemon.cpp b/native/src/core/su/su_daemon.cpp index 6c1c57fe1..9ef7eea7c 100644 --- a/native/src/core/su/su_daemon.cpp +++ b/native/src/core/su/su_daemon.cpp @@ -116,34 +116,6 @@ bool uid_granted_root(int uid) { return granted; } -struct policy_uid_list : public vector { - void operator()(StringSlice, const DbValues &values) { - push_back(values.get_int(0)); - } -}; - -void prune_su_access() { - cached.reset(); - policy_uid_list uids; - if (!db_exec("SELECT uid FROM policies", {}, uids)) - return; - vector app_no_list = get_app_no_list(); - vector rm_uids; - for (int uid : uids) { - int app_id = to_app_id(uid); - if (app_id >= AID_APP_START && app_id <= AID_APP_END) { - int app_no = app_id - AID_APP_START; - if (app_no >= app_no_list.size() || !app_no_list[app_no]) { - // The app_id is no longer installed - rm_uids.push_back(uid); - } - } - } - for (int uid : rm_uids) { - db_exec("DELETE FROM policies WHERE uid=?", { uid }); - } -} - static shared_ptr get_su_info(unsigned uid) { if (uid == AID_ROOT) { auto info = make_shared(uid);