From eee7f097e335d110b60e8249fda1742f6dee053e Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Thu, 17 Dec 2020 16:54:53 -0800 Subject: [PATCH] Make post-fs-data scripts block at most 35 secs --- native/jni/core/scripting.cpp | 101 +++++++++++++++++++++++++++------- native/jni/include/magisk.hpp | 3 + native/jni/init/magiskrc.inc | 5 +- native/jni/utils/misc.cpp | 10 +--- native/jni/utils/misc.hpp | 2 +- 5 files changed, 92 insertions(+), 29 deletions(-) diff --git a/native/jni/core/scripting.cpp b/native/jni/core/scripting.cpp index dc7c618cc..ebf25fdf5 100644 --- a/native/jni/core/scripting.cpp +++ b/native/jni/core/scripting.cpp @@ -1,8 +1,6 @@ -#include -#include -#include #include #include +#include #include #include @@ -29,23 +27,66 @@ static void set_script_env() { void exec_script(const char *script) { exec_t exec { .pre_exec = set_script_env, - .fork = fork_no_zombie + .fork = fork_no_orphan }; exec_command_sync(exec, BBEXEC_CMD, script); } +static timespec pfs_timeout; + +#define PFS_SETUP() \ +if (pfs) { \ + if (int pid = xfork()) { \ + if (pid < 0) \ + return; \ + /* In parent process, simply wait for child to finish */ \ + waitpid(pid, nullptr, 0); \ + return; \ + } \ + timer_pid = xfork(); \ + if (timer_pid == 0) { \ + /* In timer process, count down */ \ + clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &pfs_timeout, nullptr); \ + exit(0); \ + } \ +} + +#define PFS_WAIT() \ +if (pfs) { \ + /* If we ran out of time, don't block */ \ + if (timer_pid < 0) \ + continue; \ + if (int pid = waitpid(-1, nullptr, 0); pid == timer_pid) { \ + LOGW("* post-fs-data scripts blocking phase timeout\n"); \ + timer_pid = -1; \ + } \ +} + +#define PFS_DONE() \ +if (pfs) { \ + if (timer_pid > 0) \ + kill(timer_pid, SIGKILL); \ + exit(0); \ +} + void exec_common_scripts(const char *stage) { LOGI("* Running %s.d scripts\n", stage); char path[4096]; char *name = path + sprintf(path, SECURE_DIR "/%s.d", stage); auto dir = xopen_dir(path); - if (!dir) - return; + if (!dir) return; - int dfd = dirfd(dir.get()); bool pfs = stage == "post-fs-data"sv; - *(name++) = '/'; + int timer_pid = -1; + if (pfs) { + // Setup timer + clock_gettime(CLOCK_MONOTONIC, &pfs_timeout); + pfs_timeout.tv_sec += POST_FS_DATA_SCRIPT_MAX_TIME; + } + PFS_SETUP() + *(name++) = '/'; + int dfd = dirfd(dir.get()); for (dirent *entry; (entry = xreaddir(dir.get()));) { if (entry->d_type == DT_REG) { if (faccessat(dfd, entry->d_name, X_OK, 0) != 0) @@ -54,20 +95,40 @@ void exec_common_scripts(const char *stage) { strcpy(name, entry->d_name); exec_t exec { .pre_exec = set_script_env, - .fork = pfs ? fork_no_zombie : fork_dont_care + .fork = pfs ? xfork : fork_dont_care }; - if (pfs) - exec_command_sync(exec, BBEXEC_CMD, path); - else - exec_command(exec, BBEXEC_CMD, path); + exec_command(exec, BBEXEC_CMD, path); + PFS_WAIT() } } + + PFS_DONE() +} + +// Return if a > b +static bool timespec_larger(timespec *a, timespec *b) { + if (a->tv_sec != b->tv_sec) + return a->tv_sec > b->tv_sec; + return a->tv_nsec > b->tv_nsec; } void exec_module_scripts(const char *stage, const vector &module_list) { LOGI("* Running module %s scripts\n", stage); - char path[4096]; + if (module_list.empty()) + return; + bool pfs = stage == "post-fs-data"sv; + if (pfs) { + timespec now{}; + clock_gettime(CLOCK_MONOTONIC, &now); + // If we had already timed out, treat it as service mode + if (timespec_larger(&now, &pfs_timeout)) + pfs = false; + } + int timer_pid = -1; + PFS_SETUP() + + char path[4096]; for (auto &m : module_list) { const char* module = m.data(); sprintf(path, MODULEROOT "/%s/%s.sh", module, stage); @@ -76,13 +137,13 @@ void exec_module_scripts(const char *stage, const vector &module_list) { LOGI("%s: exec [%s.sh]\n", module, stage); exec_t exec { .pre_exec = set_script_env, - .fork = pfs ? fork_no_zombie : fork_dont_care + .fork = pfs ? xfork : fork_dont_care }; - if (pfs) - exec_command_sync(exec, BBEXEC_CMD, path); - else - exec_command(exec, BBEXEC_CMD, path); + exec_command(exec, BBEXEC_CMD, path); + PFS_WAIT() } + + PFS_DONE() } constexpr char install_script[] = R"EOF( @@ -95,7 +156,7 @@ rm -f $APK void install_apk(const char *apk) { setfilecon(apk, "u:object_r:" SEPOL_FILE_TYPE ":s0"); exec_t exec { - .fork = fork_no_zombie + .fork = fork_no_orphan }; char cmds[sizeof(install_script) + 4096]; sprintf(cmds, install_script, apk); diff --git a/native/jni/include/magisk.hpp b/native/jni/include/magisk.hpp index a86688edb..f3f785338 100644 --- a/native/jni/include/magisk.hpp +++ b/native/jni/include/magisk.hpp @@ -27,6 +27,9 @@ extern std::string MAGISKTMP; constexpr const char *applet_names[] = { "su", "resetprop", "magiskhide", nullptr }; constexpr const char *init_applet[] = { "magiskpolicy", "supolicy", nullptr }; +#define POST_FS_DATA_WAIT_TIME 40 +#define POST_FS_DATA_SCRIPT_MAX_TIME 35 + // Multi-call entrypoints int magisk_main(int argc, char *argv[]); int magiskhide_main(int argc, char *argv[]); diff --git a/native/jni/init/magiskrc.inc b/native/jni/init/magiskrc.inc index 641de9a8f..8c9b780c6 100644 --- a/native/jni/init/magiskrc.inc +++ b/native/jni/init/magiskrc.inc @@ -1,6 +1,9 @@ #include #include +#define quote(s) #s +#define str(s) quote(s) + constexpr char MAGISK_RC[] = "\n" @@ -8,7 +11,7 @@ constexpr char MAGISK_RC[] = " start logd\n" " rm " UNBLOCKFILE "\n" " start %2$s\n" -" wait " UNBLOCKFILE " 40\n" +" wait " UNBLOCKFILE " " str(POST_FS_DATA_WAIT_TIME) "\n" " rm " UNBLOCKFILE "\n" "\n" diff --git a/native/jni/utils/misc.cpp b/native/jni/utils/misc.cpp index 1c1f220bb..8d3ad20bd 100644 --- a/native/jni/utils/misc.cpp +++ b/native/jni/utils/misc.cpp @@ -1,6 +1,3 @@ -/* misc.cpp - Store all functions that are unable to be catagorized clearly - */ - #include #include #include @@ -20,17 +17,16 @@ using namespace std; int fork_dont_care() { - int pid = xfork(); - if (pid) { + if (int pid = xfork()) { waitpid(pid, nullptr, 0); return pid; - } else if ((pid = xfork())) { + } else if (xfork()) { exit(0); } return 0; } -int fork_no_zombie() { +int fork_no_orphan() { int pid = xfork(); if (pid) return pid; diff --git a/native/jni/utils/misc.hpp b/native/jni/utils/misc.hpp index 69114311b..a9665fa8a 100644 --- a/native/jni/utils/misc.hpp +++ b/native/jni/utils/misc.hpp @@ -67,7 +67,7 @@ int new_daemon_thread(std::function &&entry); bool ends_with(const std::string_view &s1, const std::string_view &s2); int fork_dont_care(); -int fork_no_zombie(); +int fork_no_orphan(); int strend(const char *s1, const char *s2); void init_argv0(int argc, char **argv); void set_nice_name(const char *name);