mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-04-01 06:02:15 +00:00
Create mapping from watch descriptor to UID
This commit is contained in:
parent
b51feffe80
commit
7203e7df5c
@ -33,7 +33,7 @@ using namespace std;
|
|||||||
extern char *system_block, *vendor_block, *data_block;
|
extern char *system_block, *vendor_block, *data_block;
|
||||||
|
|
||||||
static int inotify_fd = -1;
|
static int inotify_fd = -1;
|
||||||
static void term_thread(int);
|
static void term_thread(int sig = TERM_THREAD);
|
||||||
|
|
||||||
static inline int read_ns(const int pid, struct stat *st) {
|
static inline int read_ns(const int pid, struct stat *st) {
|
||||||
char path[32];
|
char path[32];
|
||||||
@ -116,58 +116,61 @@ static void hide_daemon(int pid) {
|
|||||||
********************/
|
********************/
|
||||||
|
|
||||||
map<string, string> hide_map; /* process -> package_name */
|
map<string, string> hide_map; /* process -> package_name */
|
||||||
|
static map<int, int> wd_uid_map; /* inotify wd -> uid */
|
||||||
static map<int, uint64_t> pid_ns_map; /* pid -> last ns inode */
|
static map<int, uint64_t> pid_ns_map; /* pid -> last ns inode */
|
||||||
static map<int, vector<string_view>> uid_proc_map; /* uid -> list of process */
|
static map<int, vector<string_view>> uid_proc_map; /* uid -> list of process */
|
||||||
|
|
||||||
// All maps are protected by this lock
|
// All maps are protected by this lock
|
||||||
pthread_mutex_t map_lock;
|
pthread_mutex_t map_lock;
|
||||||
|
|
||||||
static bool check_pid(int pid) {
|
static bool check_pid(int pid, int uid) {
|
||||||
// We're only interested in PIDs > 1000
|
// We're only interested in PIDs > 1000
|
||||||
if (pid <= 1000)
|
if (pid <= 1000)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
// Not our target UID
|
||||||
|
if (uid != get_uid(pid))
|
||||||
|
return true;
|
||||||
|
|
||||||
struct stat ns, pns;
|
struct stat ns, pns;
|
||||||
int ppid;
|
int ppid;
|
||||||
int uid = get_uid(pid);
|
|
||||||
auto it = uid_proc_map.find(uid);
|
|
||||||
if (it != uid_proc_map.end()) {
|
|
||||||
// Make sure we can read mount namespace
|
|
||||||
if ((ppid = parse_ppid(pid)) < 0 || read_ns(pid, &ns) || read_ns(ppid, &pns))
|
|
||||||
return true;
|
|
||||||
// mount namespace is not separated, we only unmount once
|
|
||||||
if (ns.st_dev == pns.st_dev && ns.st_ino == pns.st_ino)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// Check if it's a process we haven't already hijacked
|
// Make sure we can read mount namespace
|
||||||
auto pos = pid_ns_map.find(pid);
|
if ((ppid = parse_ppid(pid)) < 0 || read_ns(pid, &ns) || read_ns(ppid, &pns))
|
||||||
if (pos != pid_ns_map.end() && pos->second == ns.st_ino)
|
return true;
|
||||||
return true;
|
// mount namespace is not separated, we only unmount once
|
||||||
|
if (ns.st_dev == pns.st_dev && ns.st_ino == pns.st_ino)
|
||||||
|
return true;
|
||||||
|
|
||||||
// Check whether process name match hide list
|
// Check if it's a process we haven't already hijacked
|
||||||
const char *process = nullptr;
|
auto pos = pid_ns_map.find(pid);
|
||||||
for (auto &proc : it->second)
|
if (pos != pid_ns_map.end() && pos->second == ns.st_ino)
|
||||||
if (proc_name_match(pid, proc.data()))
|
return true;
|
||||||
process = proc.data();
|
|
||||||
|
|
||||||
if (!process)
|
// Check whether process name match hide list
|
||||||
return true;
|
const char *process = nullptr;
|
||||||
|
for (auto &proc : uid_proc_map[uid])
|
||||||
|
if (proc_name_match(pid, proc.data()))
|
||||||
|
process = proc.data();
|
||||||
|
|
||||||
// Send pause signal ASAP
|
if (!process)
|
||||||
if (kill(pid, SIGSTOP) == -1)
|
return true;
|
||||||
return true;
|
|
||||||
|
|
||||||
pid_ns_map[pid] = ns.st_ino;
|
// Send pause signal ASAP
|
||||||
LOGI("proc_monitor: [%s] UID=[%d] PID=[%d] ns=[%llu]\n", process, uid, pid, ns.st_ino);
|
if (kill(pid, SIGSTOP) == -1)
|
||||||
|
return true;
|
||||||
|
|
||||||
/*
|
pid_ns_map[pid] = ns.st_ino;
|
||||||
* The setns system call do not support multithread processes
|
LOGI("proc_monitor: [%s] UID=[%d] PID=[%d] ns=[%llu]\n", process, uid, pid, ns.st_ino);
|
||||||
* We have to fork a new process, setns, then do the unmounts
|
|
||||||
*/
|
/*
|
||||||
if (fork_dont_care() == 0)
|
* The setns system call do not support multithread processes
|
||||||
hide_daemon(pid);
|
* We have to fork a new process, setns, then do the unmounts
|
||||||
}
|
*/
|
||||||
return true;
|
if (fork_dont_care() == 0)
|
||||||
|
hide_daemon(pid);
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int xinotify_add_watch(int fd, const char* path, uint32_t mask) {
|
static int xinotify_add_watch(int fd, const char* path, uint32_t mask) {
|
||||||
@ -187,10 +190,13 @@ static bool parse_packages_xml(string_view &s) {
|
|||||||
/* <package key1="value1" key2="value2"....> */
|
/* <package key1="value1" key2="value2"....> */
|
||||||
char *start = (char *) s.data();
|
char *start = (char *) s.data();
|
||||||
start[s.length() - 2] = '\0'; /* Remove trailing '>' */
|
start[s.length() - 2] = '\0'; /* Remove trailing '>' */
|
||||||
|
start += 9; /* Skip '<package ' */
|
||||||
|
|
||||||
char key[32], value[1024];
|
char key[32], value[1024];
|
||||||
char *pkg = nullptr;
|
char *pkg = nullptr;
|
||||||
|
int wd = -1;
|
||||||
|
|
||||||
char *tok;
|
char *tok;
|
||||||
start += 9; /* Skip '<package ' */
|
|
||||||
while ((tok = strtok_r(nullptr, " ", &start))) {
|
while ((tok = strtok_r(nullptr, " ", &start))) {
|
||||||
sscanf(tok, "%[^=]=\"%[^\"]", key, value);
|
sscanf(tok, "%[^=]=\"%[^\"]", key, value);
|
||||||
string_view key_view(key);
|
string_view key_view(key);
|
||||||
@ -207,7 +213,7 @@ static bool parse_packages_xml(string_view &s) {
|
|||||||
} else if (key_view == "codePath") {
|
} else if (key_view == "codePath") {
|
||||||
if (ends_with(value_view, APK_EXT)) {
|
if (ends_with(value_view, APK_EXT)) {
|
||||||
// Directly add to inotify list
|
// Directly add to inotify list
|
||||||
xinotify_add_watch(inotify_fd, value, IN_OPEN);
|
wd = xinotify_add_watch(inotify_fd, value, IN_OPEN);
|
||||||
} else {
|
} else {
|
||||||
DIR *dir = opendir(value);
|
DIR *dir = opendir(value);
|
||||||
if (dir == nullptr)
|
if (dir == nullptr)
|
||||||
@ -217,7 +223,7 @@ static bool parse_packages_xml(string_view &s) {
|
|||||||
if (ends_with(entry->d_name, APK_EXT)) {
|
if (ends_with(entry->d_name, APK_EXT)) {
|
||||||
value[value_view.length()] = '/';
|
value[value_view.length()] = '/';
|
||||||
strcpy(value + value_view.length() + 1, entry->d_name);
|
strcpy(value + value_view.length() + 1, entry->d_name);
|
||||||
xinotify_add_watch(inotify_fd, value, IN_OPEN);
|
wd = xinotify_add_watch(inotify_fd, value, IN_OPEN);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -225,6 +231,7 @@ static bool parse_packages_xml(string_view &s) {
|
|||||||
}
|
}
|
||||||
} else if (key_view == "userId" || key_view == "sharedUserId") {
|
} else if (key_view == "userId" || key_view == "sharedUserId") {
|
||||||
int uid = parse_int(value);
|
int uid = parse_int(value);
|
||||||
|
wd_uid_map[wd] = uid;
|
||||||
for (auto &hide : hide_map) {
|
for (auto &hide : hide_map) {
|
||||||
if (hide.second == pkg)
|
if (hide.second == pkg)
|
||||||
uid_proc_map[uid].emplace_back(hide.first);
|
uid_proc_map[uid].emplace_back(hide.first);
|
||||||
@ -237,7 +244,7 @@ static bool parse_packages_xml(string_view &s) {
|
|||||||
void update_inotify_mask() {
|
void update_inotify_mask() {
|
||||||
int new_inotify = xinotify_init1(IN_CLOEXEC);
|
int new_inotify = xinotify_init1(IN_CLOEXEC);
|
||||||
if (new_inotify < 0)
|
if (new_inotify < 0)
|
||||||
term_thread(TERM_THREAD);
|
term_thread();
|
||||||
|
|
||||||
// Swap out and close old inotify_fd
|
// Swap out and close old inotify_fd
|
||||||
int tmp = inotify_fd;
|
int tmp = inotify_fd;
|
||||||
@ -249,6 +256,7 @@ void update_inotify_mask() {
|
|||||||
{
|
{
|
||||||
MutexGuard lock(map_lock);
|
MutexGuard lock(map_lock);
|
||||||
uid_proc_map.clear();
|
uid_proc_map.clear();
|
||||||
|
wd_uid_map.clear();
|
||||||
file_readline("/data/system/packages.xml", parse_packages_xml, true);
|
file_readline("/data/system/packages.xml", parse_packages_xml, true);
|
||||||
}
|
}
|
||||||
xinotify_add_watch(inotify_fd, "/data/system", IN_CLOSE_WRITE);
|
xinotify_add_watch(inotify_fd, "/data/system", IN_CLOSE_WRITE);
|
||||||
@ -260,6 +268,7 @@ static void term_thread(int) {
|
|||||||
hide_map.clear();
|
hide_map.clear();
|
||||||
uid_proc_map.clear();
|
uid_proc_map.clear();
|
||||||
pid_ns_map.clear();
|
pid_ns_map.clear();
|
||||||
|
wd_uid_map.clear();
|
||||||
hide_enabled = false;
|
hide_enabled = false;
|
||||||
pthread_mutex_destroy(&map_lock);
|
pthread_mutex_destroy(&map_lock);
|
||||||
close(inotify_fd);
|
close(inotify_fd);
|
||||||
@ -282,20 +291,21 @@ void proc_monitor() {
|
|||||||
|
|
||||||
// Read inotify events
|
// Read inotify events
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
|
int uid;
|
||||||
char buf[512];
|
char buf[512];
|
||||||
auto event = reinterpret_cast<inotify_event *>(buf);
|
auto event = reinterpret_cast<inotify_event *>(buf);
|
||||||
while ((len = read(inotify_fd, buf, sizeof(buf))) >= 0) {
|
while ((len = read(inotify_fd, buf, sizeof(buf))) >= 0) {
|
||||||
if (len < sizeof(*event))
|
if (len < sizeof(*event))
|
||||||
continue;
|
continue;
|
||||||
if (event->mask & IN_OPEN) {
|
if (event->mask & IN_OPEN) {
|
||||||
// Since we're just watching files,
|
|
||||||
// extracting file name is not possible from querying event
|
|
||||||
MutexGuard lock(map_lock);
|
MutexGuard lock(map_lock);
|
||||||
crawl_procfs(check_pid);
|
uid = wd_uid_map[event->wd];
|
||||||
|
crawl_procfs([=](int pid) -> bool { return check_pid(pid, uid); });
|
||||||
} else if ((event->mask & IN_CLOSE_WRITE) && strcmp(event->name, "packages.xml") == 0) {
|
} else if ((event->mask & IN_CLOSE_WRITE) && strcmp(event->name, "packages.xml") == 0) {
|
||||||
LOGD("proc_monitor: /data/system/packages.xml updated\n");
|
LOGD("proc_monitor: /data/system/packages.xml updated\n");
|
||||||
update_inotify_mask();
|
update_inotify_mask();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PLOGE("proc_monitor: read inotify");
|
PLOGE("proc_monitor: read inotify");
|
||||||
|
term_thread();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user