fix: root related mounts leak in APatch in isolated services

This commit fixes the issue where mounts related to APatch and ReZygisk would be leaked in isolated services for APatch environments as the UID between the main process and isolated service is different, resulting it to not be found in "package_config" and default to not switch to clean mount namespace.
This commit is contained in:
ThePedroo
2025-06-20 16:42:36 -03:00
parent f432550f07
commit b7fe7b3dbe
4 changed files with 27 additions and 5 deletions

View File

@@ -62,6 +62,7 @@ void apatch_get_existence(struct root_impl_state *state) {
}
struct package_config {
char *process;
uid_t uid;
bool root_granted;
bool umount_needed;
@@ -104,7 +105,7 @@ bool _apatch_get_package_config(struct packages_config *restrict config) {
return false;
}
strtok(line, ",");
config->configs[config->size].process = strdup(strtok(line, ","));
char *exclude_str = strtok(NULL, ",");
if (exclude_str == NULL) continue;
@@ -128,6 +129,10 @@ bool _apatch_get_package_config(struct packages_config *restrict config) {
}
void _apatch_free_package_config(struct packages_config *restrict config) {
for (size_t i = 0; i < config->size; i++) {
free(config->configs[i].process);
}
free(config->configs);
}
@@ -155,7 +160,7 @@ bool apatch_uid_granted_root(uid_t uid) {
return false;
}
bool apatch_uid_should_umount(uid_t uid) {
bool apatch_uid_should_umount(uid_t uid, const char *const process) {
struct packages_config config;
if (!_apatch_get_package_config(&config)) {
_apatch_free_package_config(&config);
@@ -163,8 +168,22 @@ bool apatch_uid_should_umount(uid_t uid) {
return false;
}
/* INFO: Some can take advantage of the UID being different in an app's
isolated service, bypassing this check, so we must check against
process name in case it is an isolated service. This can happen in
all root implementations. */
size_t targeted_process_length = 0;
if (IS_ISOLATED_SERVICE(uid)) targeted_process_length = strlen(process);
for (size_t i = 0; i < config.size; i++) {
if (config.configs[i].uid != uid) continue;
if (IS_ISOLATED_SERVICE(uid)) {
size_t config_process_length = strlen(config.configs[i].process);
size_t smallest_process_length = targeted_process_length < config_process_length ? targeted_process_length : config_process_length;
if (strncmp(config.configs[i].process, process, smallest_process_length) != 0) continue;
} else {
if (config.configs[i].uid != uid) continue;
}
/* INFO: This allow us to copy the information to avoid use-after-free */
bool umount_needed = config.configs[i].umount_needed;

View File

@@ -7,7 +7,7 @@ void apatch_get_existence(struct root_impl_state *state);
bool apatch_uid_granted_root(uid_t uid);
bool apatch_uid_should_umount(uid_t uid);
bool apatch_uid_should_umount(uid_t uid, const char *const process);
bool apatch_uid_is_manager(uid_t uid);

View File

@@ -100,7 +100,7 @@ bool uid_should_umount(uid_t uid, const char *const process) {
return ksu_uid_should_umount(uid);
}
case APatch: {
return apatch_uid_should_umount(uid);
return apatch_uid_should_umount(uid, process);
}
case Magisk: {
return magisk_uid_should_umount(process);

View File

@@ -65,6 +65,9 @@
return -1; \
}
#define IS_ISOLATED_SERVICE(uid) \
((uid) >= 90000 && (uid) < 1000000)
#define write_func_def(type) \
ssize_t write_## type(int fd, type val)