From dbfde74c1e43fc488ed1433fce47c294e4296006 Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Wed, 1 Apr 2020 23:37:11 -0700 Subject: [PATCH] Clean rootfs in switch_root --- native/jni/core/bootstages.cpp | 2 +- native/jni/init/mount.cpp | 9 ++++---- native/jni/utils/file.cpp | 40 ++++++++++------------------------ native/jni/utils/files.hpp | 2 +- native/jni/utils/xwrap.cpp | 8 +++++++ native/jni/utils/xwrap.hpp | 1 + 6 files changed, 27 insertions(+), 35 deletions(-) diff --git a/native/jni/core/bootstages.cpp b/native/jni/core/bootstages.cpp index a44a840eb..a0c664978 100644 --- a/native/jni/core/bootstages.cpp +++ b/native/jni/core/bootstages.cpp @@ -478,7 +478,7 @@ static void collect_modules() { fd_pathat(modfd, "uninstall.sh", buf, sizeof(buf)); if (access(buf, F_OK) == 0) exec_script(buf); - frm_rf(modfd); + frm_rf(xdup(modfd)); unlinkat(dfd, entry->d_name, AT_REMOVEDIR); continue; } diff --git a/native/jni/init/mount.cpp b/native/jni/init/mount.cpp index a7dcaf337..cace570ce 100644 --- a/native/jni/init/mount.cpp +++ b/native/jni/init/mount.cpp @@ -121,6 +121,7 @@ if (!is_lnk("/" #name) && read_dt_fstab(cmd, #name)) { \ static void switch_root(const string &path) { LOGD("Switch root to %s\n", path.data()); + int root = xopen("/", O_RDONLY); vector mounts; parse_mnt("/proc/mounts", [&](mntent *me) { // Skip root and self @@ -142,6 +143,9 @@ static void switch_root(const string &path) { chdir(path.data()); xmount(path.data(), "/", nullptr, MS_MOVE, nullptr); chroot("."); + + LOGD("Cleaning rootfs\n"); + frm_rf(root); } static void mount_persist(const char *dev_base, const char *mnt_base) { @@ -219,11 +223,6 @@ void SARInit::early_mount() { backup_files(); - LOGD("Cleaning rootfs\n"); - int root = xopen("/", O_RDONLY | O_CLOEXEC); - frm_rf(root, { "proc", "sys", "dev" }); - close(root); - mount_system_root(); switch_root("/system_root"); diff --git a/native/jni/utils/file.cpp b/native/jni/utils/file.cpp index 118bc7a98..f36170351 100644 --- a/native/jni/utils/file.cpp +++ b/native/jni/utils/file.cpp @@ -47,27 +47,15 @@ int mkdirs(const char *pathname, mode_t mode) { return 0; } -static bool is_excl(initializer_list excl, const char *name) { - for (auto item : excl) - if (strcmp(item, name) == 0) - return true; - return false; -} - -static void post_order_walk(int dirfd, initializer_list excl, - function &&fn) { +static void post_order_walk(int dirfd, function &&fn) { auto dir = xopen_dir(dirfd); if (!dir) return; for (dirent *entry; (entry = xreaddir(dir.get()));) { - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + if (entry->d_name == "."sv || entry->d_name == ".."sv) continue; - if (is_excl(excl, entry->d_name)) - continue; - if (entry->d_type == DT_DIR) { - int newfd = xopenat(dirfd, entry->d_name, O_RDONLY | O_CLOEXEC); - post_order_walk(newfd, excl, std::move(fn)); - } + if (entry->d_type == DT_DIR) + post_order_walk(xopenat(dirfd, entry->d_name, O_RDONLY | O_CLOEXEC), std::move(fn)); fn(dirfd, entry); } } @@ -80,15 +68,13 @@ void rm_rf(const char *path) { struct stat st; if (lstat(path, &st) < 0) return; - if (S_ISDIR(st.st_mode)) { - int fd = xopen(path, O_RDONLY | O_CLOEXEC); - frm_rf(fd); - } + if (S_ISDIR(st.st_mode)) + frm_rf(xopen(path, O_RDONLY | O_CLOEXEC)); remove(path); } -void frm_rf(int dirfd, initializer_list excl) { - post_order_walk(dup(dirfd), excl, remove_at); +void frm_rf(int dirfd) { + post_order_walk(dirfd, remove_at); } /* This will only on the same file system */ @@ -389,7 +375,7 @@ void parse_prop_file(const char *file, const function &fn) { - unique_ptr fp(setmntent(file, "re"), &endmntent); + auto fp = sFILE(setmntent(file, "re"), endmntent); if (fp) { mntent mentry{}; char buf[4096]; @@ -404,11 +390,11 @@ void backup_folder(const char *dir, vector &files) { char path[4096]; realpath(dir, path); int len = strlen(path); - int dirfd = xopen(dir, O_RDONLY); - post_order_walk(dirfd, {}, [&](int dfd, dirent *entry) -> int { + post_order_walk(xopen(dir, O_RDONLY), [&](int dfd, dirent *entry) -> int { int fd = xopenat(dfd, entry->d_name, O_RDONLY); if (fd < 0) return -1; + run_finally f([&]{ close(fd); }); if (fd_path(fd, path, sizeof(path)) < 0) return -1; raw_file file; @@ -423,11 +409,9 @@ void backup_folder(const char *dir, vector &files) { file.buf = (uint8_t *) xmalloc(file.sz); memcpy(file.buf, path, file.sz); } - close(fd); files.emplace_back(std::move(file)); return 0; }); - close(dirfd); } void restore_folder(const char *dir, vector &files) { @@ -438,7 +422,7 @@ void restore_folder(const char *dir, vector &files) { if (S_ISDIR(file.attr.st.st_mode)) { mkdirs(path.data(), 0); } else if (S_ISREG(file.attr.st.st_mode)) { - auto fp = xopen_file(path.data(), "w"); + auto fp = xopen_file(path.data(), "we"); fwrite(file.buf, 1, file.sz, fp.get()); } else if (S_ISLNK(file.attr.st.st_mode)) { symlink((char *)file.buf, path.data()); diff --git a/native/jni/utils/files.hpp b/native/jni/utils/files.hpp index c955282b5..19f129f58 100644 --- a/native/jni/utils/files.hpp +++ b/native/jni/utils/files.hpp @@ -66,7 +66,7 @@ static inline void file_readline(const char *file, void parse_prop_file(const char *file, const std::function &fn); void *__mmap(const char *filename, size_t *size, bool rw); -void frm_rf(int dirfd, std::initializer_list excl = {}); +void frm_rf(int dirfd); void clone_dir(int src, int dest, bool overwrite = true); void parse_mnt(const char *file, const std::function &fn); void backup_folder(const char *dir, std::vector &files); diff --git a/native/jni/utils/xwrap.cpp b/native/jni/utils/xwrap.cpp index 120521cae..949b5da5f 100644 --- a/native/jni/utils/xwrap.cpp +++ b/native/jni/utils/xwrap.cpp @@ -258,6 +258,14 @@ int xfstat(int fd, struct stat *buf) { return ret; } +int xdup(int fd) { + int ret = dup(fd); + if (ret == -1) { + PLOGE("dup"); + } + return ret; +} + int xdup2(int oldfd, int newfd) { int ret = dup2(oldfd, newfd); if (ret == -1) { diff --git a/native/jni/utils/xwrap.hpp b/native/jni/utils/xwrap.hpp index ffa4f6536..bdd343132 100644 --- a/native/jni/utils/xwrap.hpp +++ b/native/jni/utils/xwrap.hpp @@ -35,6 +35,7 @@ int xpthread_create(pthread_t *thread, const pthread_attr_t *attr, int xstat(const char *pathname, struct stat *buf); int xlstat(const char *pathname, struct stat *buf); int xfstat(int fd, struct stat *buf); +int xdup(int fd); int xdup2(int oldfd, int newfd); int xdup3(int oldfd, int newfd, int flags); ssize_t xreadlink(const char *pathname, char *buf, size_t bufsiz);