Proper package state management

This commit is contained in:
topjohnwu 2022-05-29 23:31:57 -07:00
parent 4ea8bd0229
commit d0c4226997
7 changed files with 22 additions and 24 deletions

View File

@ -18,8 +18,7 @@ android {
ndkBuild {
// Pass arguments to ndk-build.
arguments(
"B_MAGISK=1", "B_INIT=1", "B_BOOT=1", "B_TEST=1", "B_POLICY=1", "B_PRELOAD=1",
"MAGISK_DEBUG=1", "MAGISK_VERSION=debug", "MAGISK_VER_CODE=INT_MAX"
"B_MAGISK=1", "B_INIT=1", "B_BOOT=1", "B_TEST=1", "B_POLICY=1", "B_PRELOAD=1"
)
}
}

View File

@ -366,7 +366,7 @@ void boot_complete(int client) {
xmkdir(SECURE_DIR, 0700);
// Ensure manager exists
need_pkg_refresh();
check_pkg_refresh();
get_manager(0, nullptr, true);
}

View File

@ -15,7 +15,7 @@ using namespace std;
// or simply skipped unless necessary.
atomic<ino_t> pkg_xml_ino = 0;
static atomic_flag skip_check;
static atomic_flag skip_mgr_check;
static pthread_mutex_t pkg_lock = PTHREAD_MUTEX_INITIALIZER;
// pkg_lock protects all following variables
@ -25,16 +25,12 @@ static string *mgr_cert;
static int stub_apk_fd = -1;
static const string *default_cert;
bool need_pkg_refresh() {
void check_pkg_refresh() {
struct stat st{};
stat("/data/system/packages.xml", &st);
ino_t ino = pkg_xml_ino.exchange(st.st_ino);
if (ino == st.st_ino) {
// Packages have not changed
return false;
} else {
skip_check.clear();
return true;
if (stat("/data/system/packages.xml", &st) == 0 &&
pkg_xml_ino.exchange(st.st_ino) != st.st_ino) {
skip_mgr_check.clear();
skip_pkg_rescan.clear();
}
}
@ -120,7 +116,7 @@ int get_manager(int user_id, string *pkg, bool install) {
return true;
};
if (skip_check.test_and_set()) {
if (skip_mgr_check.test_and_set()) {
if (mgr_app_id < 0) {
goto not_found;
}

View File

@ -89,11 +89,14 @@ void zygisk_handler(int client, const sock_cred *cred);
// Package
void preserve_stub_apk();
bool need_pkg_refresh();
void check_pkg_refresh();
std::vector<bool> get_app_no_list();
// Call check_pkg_refresh() before calling get_manager(...)
// to make sure the package state is invalidated!
int get_manager(int user_id = 0, std::string *pkg = nullptr, bool install = false);
void prune_su_access();
// Denylist
extern std::atomic_flag skip_pkg_rescan;
void initialize_denylist();
int denylist_cli(int argc, char **argv);

View File

@ -81,9 +81,11 @@ void su_info::check_db() {
}
// We need to check our manager
if (access.log || access.notify)
if (access.log || access.notify) {
check_pkg_refresh();
mgr_uid = get_manager(to_user_id(eval_uid), &mgr_pkg, true);
}
}
bool uid_granted_root(int uid) {
if (uid == UID_ROOT)
@ -138,6 +140,7 @@ bool uid_granted_root(int uid) {
}
void prune_su_access() {
cached.reset();
vector<bool> app_no_list = get_app_no_list();
vector<int> rm_uids;
char query[256], *err;
@ -170,10 +173,6 @@ static shared_ptr<su_info> get_su_info(unsigned uid) {
{
mutex_guard lock(cache_lock);
if (need_pkg_refresh()) {
cached.reset();
prune_su_access();
}
if (!cached || cached->uid != uid || !cached->is_fresh())
cached = make_shared<su_info>(uid);
cached->refresh();

View File

@ -14,6 +14,8 @@
using namespace std;
atomic_flag skip_pkg_rescan;
// For the following data structures:
// If package name == ISOLATED_MAGIC, or app ID == -1, it means isolated service
@ -33,9 +35,6 @@ atomic<bool> denylist_enforced = false;
#define do_kill (zygisk_enabled && denylist_enforced)
static void rescan_apps() {
if (!need_pkg_refresh())
return;
LOGD("denylist: rescanning apps\n");
app_id_to_pkgs.clear();
@ -386,6 +385,7 @@ bool is_deny_target(int uid, string_view process) {
if (!ensure_data())
return false;
if (!skip_pkg_rescan.test_and_set())
rescan_apps();
int app_id = to_app_id(uid);

View File

@ -319,6 +319,7 @@ static void get_process_info(int client, const sock_cred *cred) {
uint32_t flags = 0;
check_pkg_refresh();
if (is_deny_target(uid, process)) {
flags |= PROCESS_ON_DENYLIST;
}