Skip to content

Commit

Permalink
tmp
Browse files Browse the repository at this point in the history
  • Loading branch information
ThePedroo committed Dec 29, 2024
1 parent c030760 commit d4a6f2b
Show file tree
Hide file tree
Showing 10 changed files with 62 additions and 173 deletions.
7 changes: 4 additions & 3 deletions loader/src/common/daemon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -261,16 +261,17 @@ namespace zygiskd {
} else info->running = false;
}

std::string GetCleanNamespace() {
std::string UpdateMountNamespace(bool clean) {
int fd = Connect(1);
if (fd == -1) {
PLOGE("GetCleanNamespace");
PLOGE("UpdateMountNamespace");

return "";
}

socket_utils::write_u8(fd, (uint8_t) SocketAction::GetCleanNamespace);
socket_utils::write_u8(fd, (uint8_t) SocketAction::UpdateMountNamespace);
socket_utils::write_u32(fd, getpid());
socket_utils::write_u8(fd, clean);

uint32_t target_pid = socket_utils::read_u32(fd);
int target_fd = 0;
Expand Down
4 changes: 2 additions & 2 deletions loader/src/include/daemon.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ namespace zygiskd {
GetModuleDir,
ZygoteRestart,
SystemServerStarted,
GetCleanNamespace
UpdateMountNamespace
};

void Init(const char *path);
Expand All @@ -105,5 +105,5 @@ namespace zygiskd {

void GetInfo(struct zygote_info *info);

std::string GetCleanNamespace();
std::string UpdateMountNamespace(bool clean);
}
61 changes: 26 additions & 35 deletions loader/src/injector/hook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,36 +138,29 @@ DCL_HOOK_FUNC(int, fork) {
return (g_ctx && g_ctx->pid >= 0) ? g_ctx->pid : old_fork();
}

void clean_mnt_ns() {
std::string path = zygiskd::GetCleanNamespace();
LOGI("Switching to clean namespace: %s", path.data());
bool update_mnt_ns(bool clean, bool dry_run) {
std::string ns_path = zygiskd::UpdateMountNamespace(clean);
if (ns_path.empty()) {
PLOGE("Failed to update mount namespace");

if (path.empty()) {
LOGE("Failed to get clean namespace path");

return;
}

int nsfd = open(path.data(), O_RDONLY | O_CLOEXEC);
if (nsfd == -1) {
LOGE("Failed to open clean namespace: %s", strerror(errno));

return;
return false;
}

if (setns(nsfd, CLONE_NEWNS) == -1) {
LOGE("Failed to setns clean namespace: %s", strerror(errno));
if (dry_run) return true;

close(nsfd);
int updated_ns = open(ns_path.data(), O_RDONLY);
if (updated_ns == -1) {
PLOGE("Failed to open mount namespace [%s]", ns_path.data());

return;
return false;
}

close(nsfd);
LOGD("set mount namespace to [%s] fd=[%d]\n", ns_path.data(), updated_ns);
setns(updated_ns, CLONE_NEWNS);

LOGD("Switched to clean namespace");
close(updated_ns);

return;
return true;
}

// Unmount stuffs in the process's private mount namespace
Expand All @@ -177,17 +170,17 @@ DCL_HOOK_FUNC(int, unshare, int flags) {
// For some unknown reason, unmounting app_process in SysUI can break.
// This is reproducible on the official AVD running API 26 and 27.
// Simply avoid doing any unmounts for SysUI to avoid potential issues.
(g_ctx->info_flags & PROCESS_IS_FIRST_STARTED) == 0) {
if (g_ctx->flags[DO_REVERT_UNMOUNT]) clean_mnt_ns();
else if (!(g_ctx->info_flags & (PROCESS_IS_MANAGER | PROCESS_GRANTED_ROOT)))
do_umount(cached_mountinfo);

!g_ctx->flags[SERVER_FORK_AND_SPECIALIZE] && !(g_ctx->info_flags & PROCESS_IS_FIRST_STARTED)) {
if (!g_ctx->flags[DO_REVERT_UNMOUNT]) {
update_mnt_ns(false, false);
}
/* Zygisksu changed: No umount app_process */
old_unshare(CLONE_NEWNS);

// Restore errno back to 0
errno = 0;
}

return res;
}

Expand Down Expand Up @@ -632,14 +625,8 @@ void ZygiskContext::app_specialize_pre() {
flags[APP_SPECIALIZE] = true;

info_flags = zygiskd::GetProcessFlags(getpid());
if (info_flags & PROCESS_ON_DENYLIST) {
if (info_flags & PROCESS_ROOT_IS_KSU) {
cached_mountinfo = fill_ksu_umount_paths();
} else if (info_flags & PROCESS_ROOT_IS_APATCH){
cached_mountinfo = fill_apatch_umount_paths();
} else if (info_flags & PROCESS_ROOT_IS_MAGISK) {
cached_mountinfo = fill_magisk_umount_paths();
}
if (info_flags & PROCESS_IS_FIRST_STARTED) {
update_mnt_ns(true, true);
}

if ((info_flags & PROCESS_ON_DENYLIST) == PROCESS_ON_DENYLIST) {
Expand Down Expand Up @@ -715,8 +702,10 @@ void ZygiskContext::nativeForkSystemServer_post() {
void ZygiskContext::nativeForkAndSpecialize_pre() {
process = env->GetStringUTFChars(args.app->nice_name, nullptr);
LOGV("pre forkAndSpecialize [%s]", process);

flags[APP_FORK_AND_SPECIALIZE] = true;

update_mnt_ns(true, false);

/* Zygisksu changed: No args.app->fds_to_ignore check since we are Android 10+ */
if (logging::getfd() != -1) {
exempted_fds.push_back(logging::getfd());
Expand Down Expand Up @@ -853,6 +842,8 @@ void hook_functions() {
std::remove_if(plt_hook_list->begin(), plt_hook_list->end(),
[](auto &t) { return *std::get<3>(t) == nullptr;}),
plt_hook_list->end());

cached_mountinfo = fill_umount_paths();
}

static void hook_unloader() {
Expand Down
100 changes: 3 additions & 97 deletions loader/src/injector/unmount.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,6 @@
using namespace std::string_view_literals;

namespace {
constexpr auto MODULE_DIR = "/data/adb/modules";
constexpr auto KSU_OVERLAY_SOURCE = "KSU";
constexpr auto AP_OVERLAY_SOURCE = "APatch";
const std::vector<std::string> DEVICE_PARTITIONS{"/system", "/vendor", "/product", "/system_ext", "/odm", "/oem"};

void lazy_unmount(const char* mountpoint) {
if (umount2(mountpoint, MNT_DETACH) != -1) {
LOGD("Unmounted (%s)", mountpoint);
Expand All @@ -32,88 +27,14 @@ void do_umount(std::vector<std::string> targets) {
}
}

std::vector<std::string> fill_ksu_umount_paths() {
std::string ksu_loop;
std::vector<std::string> targets;

// Unmount ksu module dir last
targets.emplace_back(MODULE_DIR);

std::vector<mount_info> mounts = parse_mount_info("self");
for (auto &info : mounts) {
if (info.target == MODULE_DIR) {
ksu_loop = info.source;
continue;
}

// Unmount everything mounted to /data/adb
if (info.target.starts_with("/data/adb")) {
targets.emplace_back(info.target);
}

// Unmount everything mounted to /data/adb
if (info.root.starts_with("/adb/modules")) {
targets.emplace_back(info.target);
}

// Unmount ksu overlays
if (info.type == "overlay"
&& info.source == KSU_OVERLAY_SOURCE
&& std::find(DEVICE_PARTITIONS.begin(), DEVICE_PARTITIONS.end(), info.target) != DEVICE_PARTITIONS.end()) {
targets.emplace_back(info.target);
}

// Unmount temp dir
if (info.type == "tmpfs" && info.source == KSU_OVERLAY_SOURCE) {
targets.emplace_back(info.target);
}
}

for (auto &info : mounts) {
// Unmount everything from ksu loop except ksu module dir
if (info.source == ksu_loop && info.target != MODULE_DIR) {
targets.emplace_back(info.target);
}
}

return targets;
}

std::vector<std::string> fill_magisk_umount_paths() {
std::vector<std::string> fill_umount_paths() {
std::vector<std::string> targets;

// Unmount dummy skeletons and MAGISKTMP
// since mirror nodes are always mounted under skeleton, we don't have to specifically unmount
for (auto &info : parse_mount_info("self")) {
if (info.source == "magisk" || info.source == "worker" || // magisktmp tmpfs
info.root.starts_with("/adb/modules")) { // bind mount from data partition
targets.push_back(info.target);
}
// Unmount everything mounted to /data/adb
if (info.target.starts_with("/data/adb")) {
targets.emplace_back(info.target);
}
}

return targets;
}

std::vector<std::string> fill_apatch_umount_paths() {
std::string ap_loop;
std::vector<std::string> targets;

// Unmount ksu module dir last
targets.emplace_back(MODULE_DIR);

std::vector<mount_info> mounts = parse_mount_info("self");
for (auto &info : mounts) {
if (info.target == MODULE_DIR) {
ap_loop = info.source;
continue;
}

// Unmount everything mounted to /data/adb
if (info.target.starts_with("/data/adb")) {
if (info.target.starts_with("/data/adb") || info.target.starts_with("/debug_ramdisk")) {
targets.emplace_back(info.target);
}

Expand All @@ -122,22 +43,7 @@ std::vector<std::string> fill_apatch_umount_paths() {
targets.emplace_back(info.target);
}

// Unmount ksu overlays
if (info.type == "overlay"
&& info.source == AP_OVERLAY_SOURCE
&& std::find(DEVICE_PARTITIONS.begin(), DEVICE_PARTITIONS.end(), info.target) != DEVICE_PARTITIONS.end()) {
targets.emplace_back(info.target);
}

// Unmount temp dir
if (info.type == "tmpfs" && info.source == AP_OVERLAY_SOURCE) {
targets.emplace_back(info.target);
}
}

for (auto &info : mounts) {
// Unmount everything from ksu loop except ksu module dir
if (info.source == ap_loop && info.target != MODULE_DIR) {
if (info.source == "magisk" && info.target.starts_with("/system/bin")) {
targets.emplace_back(info.target);
}
}
Expand Down
6 changes: 1 addition & 5 deletions loader/src/injector/zygisk.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,4 @@ void clean_trace(const char* path, size_t load = 1, size_t unload = 0, bool spoo

void do_umount(std::vector<std::string> targets);

std::vector<std::string> fill_ksu_umount_paths();

std::vector<std::string> fill_magisk_umount_paths();

std::vector<std::string> fill_apatch_umount_paths();
std::vector<std::string> fill_umount_paths();
14 changes: 0 additions & 14 deletions zygiskd/src/root_impl/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,17 +127,3 @@ bool uid_is_manager(uid_t uid) {
}
}
}

bool uid_is_systemui(uid_t uid) {
struct stat s;
if (stat("/data/user_de/0/com.android.systemui", &s) == -1) {
if (errno != ENOENT) {
LOGE("Failed to stat SystemUI data directory: %s\n", strerror(errno));
}
errno = 0;

return false;
}

return s.st_uid == uid;
}
2 changes: 0 additions & 2 deletions zygiskd/src/root_impl/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,4 @@ bool uid_should_umount(uid_t uid);

bool uid_is_manager(uid_t uid);

bool uid_is_systemui(uid_t uid);

#endif /* COMMON_H */
27 changes: 19 additions & 8 deletions zygiskd/src/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "root_impl/common.h"

int clean_namespace_fd = 0;
int rooted_namespace_fd = 0;

bool switch_mount_namespace(pid_t pid) {
char path[PATH_MAX];
Expand Down Expand Up @@ -702,8 +703,9 @@ void unmount_root(struct root_impl impl) {
return;
}

int get_clean_mns_fd(int pid, struct root_impl impl) {
if (clean_namespace_fd != 0) return clean_namespace_fd;
int save_mns_fd(int pid, bool clean, struct root_impl impl) {
if (clean && clean_namespace_fd != 0) return clean_namespace_fd;
if (!clean && rooted_namespace_fd != 0) return rooted_namespace_fd;

int sockets[2];
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) == -1) {
Expand All @@ -718,11 +720,19 @@ int get_clean_mns_fd(int pid, struct root_impl impl) {
pid_t fork_pid = fork();
if (fork_pid == 0) {
switch_mount_namespace(pid);
unmount_root(impl);

write_uint32_t(writer, 0);
uint32_t _ = 0;
read_uint32_t(reader, &_);
if (clean) {
unshare(CLONE_NEWNS);
unmount_root(impl);

uint32_t mypid = 0;
while (mypid != (uint32_t)getpid()) {
write_uint32_t(writer, 0);
usleep(50);
read_uint32_t(reader, &mypid);

}
}

_exit(0);
} else if (fork_pid > 0) {
Expand All @@ -739,7 +749,7 @@ int get_clean_mns_fd(int pid, struct root_impl impl) {
return -1;
}

write_uint32_t(writer, 0);
write_uint32_t(writer, (uint32_t)fork_pid);

if (close(reader) == -1) {
LOGE("Failed to close reader: %s\n", strerror(errno));
Expand All @@ -759,7 +769,8 @@ int get_clean_mns_fd(int pid, struct root_impl impl) {
return -1;
}

return (clean_namespace_fd = ns_fd);
if (clean) return (rooted_namespace_fd = ns_fd);
else return (clean_namespace_fd = ns_fd);
} else {
LOGE("fork: %s\n", strerror(errno));

Expand Down
2 changes: 1 addition & 1 deletion zygiskd/src/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,6 @@ int non_blocking_execv(const char *restrict file, char *const argv[]);

void stringify_root_impl_name(struct root_impl impl, char *restrict output);

int get_clean_mns_fd(int pid, struct root_impl impl);
int save_mns_fd(int pid, bool clean, struct root_impl impl);

#endif /* UTILS_H */
Loading

0 comments on commit d4a6f2b

Please sign in to comment.