SIGSTOP any possible process ASAP

Shut down any UID matching process and resume if it turns out not to
be our target. Since we will record every single process we have ever
paused, this means that the same process will not be paused erroneously
for another time.

This is an optimization to hijack the app as soon as possible.
This commit is contained in:
topjohnwu 2019-03-02 04:24:41 -05:00
parent 7203e7df5c
commit d8cd2031c7
2 changed files with 23 additions and 20 deletions

View File

@ -46,6 +46,7 @@ static inline void lazy_unmount(const char* mountpoint) {
LOGD("hide_daemon: Unmounted (%s)\n", mountpoint); LOGD("hide_daemon: Unmounted (%s)\n", mountpoint);
} }
#if 0
static inline int parse_ppid(const int pid) { static inline int parse_ppid(const int pid) {
char path[32]; char path[32];
int ppid; int ppid;
@ -61,6 +62,7 @@ static inline int parse_ppid(const int pid) {
return ppid; return ppid;
} }
#endif
static void hide_daemon(int pid) { static void hide_daemon(int pid) {
RunFinally fin([=]() -> void { RunFinally fin([=]() -> void {
@ -132,21 +134,26 @@ static bool check_pid(int pid, int uid) {
if (uid != get_uid(pid)) if (uid != get_uid(pid))
return true; return true;
struct stat ns, pns; struct stat ns;
int ppid; if (read_ns(pid, &ns))
// 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; return true;
// Check if it's a process we haven't already hijacked // Check if we have already seen it before
auto pos = pid_ns_map.find(pid); auto pos = pid_ns_map.find(pid);
if (pos != pid_ns_map.end() && pos->second == ns.st_ino) if (pos != pid_ns_map.end() && pos->second == ns.st_ino)
return true; return true;
// Will rather kill all just for one
if (kill(pid, SIGSTOP) == -1)
return true;
// Auto send resume signal if return
RunFinally resume([=]() -> void {
kill(pid, SIGCONT);
});
// Record this PID
pid_ns_map[pid] = ns.st_ino;
// Check whether process name match hide list // Check whether process name match hide list
const char *process = nullptr; const char *process = nullptr;
for (auto &proc : uid_proc_map[uid]) for (auto &proc : uid_proc_map[uid])
@ -156,20 +163,14 @@ static bool check_pid(int pid, int uid) {
if (!process) if (!process)
return true; return true;
// Send pause signal ASAP
if (kill(pid, SIGSTOP) == -1)
return true;
pid_ns_map[pid] = ns.st_ino;
LOGI("proc_monitor: [%s] UID=[%d] PID=[%d] ns=[%llu]\n", process, uid, pid, ns.st_ino); LOGI("proc_monitor: [%s] UID=[%d] PID=[%d] ns=[%llu]\n", process, uid, pid, ns.st_ino);
/* // Disable auto resume PID, and let the daemon do it
* The setns system call do not support multithread processes resume.disable();
* We have to fork a new process, setns, then do the unmounts
*/
if (fork_dont_care() == 0) if (fork_dont_care() == 0)
hide_daemon(pid); hide_daemon(pid);
// We found what we want, stop traversal
return false; return false;
} }

View File

@ -162,10 +162,12 @@ class RunFinally {
public: public:
explicit RunFinally(std::function<void()> &&fn): fn(std::move(fn)) {} explicit RunFinally(std::function<void()> &&fn): fn(std::move(fn)) {}
~RunFinally() { fn(); } void disable() { fn = nullptr; }
~RunFinally() { if (fn) fn(); }
private: private:
const std::function<void ()> fn; std::function<void ()> fn;
}; };
// file.cpp // file.cpp