summaryrefslogtreecommitdiff
path: root/init/switch_root.cpp
diff options
context:
space:
mode:
authorTom Cherry <tomcherry@google.com>2018-11-06 10:32:53 -0800
committerTom Cherry <tomcherry@google.com>2018-11-09 14:58:46 -0800
commit866c08c0acea7ceba50086a02d36b27e815aa6d0 (patch)
tree9320322eb3bba9e68552256ee82b2a110834d473 /init/switch_root.cpp
parent223114008c47721512d877eefe5d7a903a7081ea (diff)
Reland: "init: chroot from recovery to /first_stage_ramdisk"
When using the recovery image as a trampoline to boot the system, first chroot from the recovery image to /first_stage_ramdisk, to minimize differences between these two boot paths. Primary motivation is due to the fact that the basename of each mount point is used by device-manager to name its nodes, and the previous code that created used /system_recovery_mount as the mount point for system.img broke AVB. Instead of hacking around that issue, this change unified mounting for the recovery trampoline and true first stage ramdisk paths. Change when relanding: the original change skipped the move mount from /first_stage_ramdisk to / and only did a chroot instead. This was a mistake that resulted in the subsequent move mount of /system to / to mount over the '/' directory instead of moving that mount. This change uses a bind mount of /first_stage_ramdisk to itself instead of skipping the first move mount. Bug: 114062208 Test: AVB works with blueline_mainline Change-Id: I65207edfe98531892da2eafcbff19b438c9c64fe
Diffstat (limited to 'init/switch_root.cpp')
-rw-r--r--init/switch_root.cpp58
1 files changed, 3 insertions, 55 deletions
diff --git a/init/switch_root.cpp b/init/switch_root.cpp
index 0e59b576b..575b67f38 100644
--- a/init/switch_root.cpp
+++ b/init/switch_root.cpp
@@ -16,7 +16,6 @@
#include "switch_root.h"
-#include <dirent.h>
#include <fcntl.h>
#include <mntent.h>
#include <sys/mount.h>
@@ -35,45 +34,6 @@ namespace init {
namespace {
-void FreeRamdisk(DIR* dir, dev_t dev) {
- int dfd = dirfd(dir);
-
- dirent* de;
- while ((de = readdir(dir)) != nullptr) {
- if (de->d_name == "."s || de->d_name == ".."s) {
- continue;
- }
-
- bool is_dir = false;
-
- if (de->d_type == DT_DIR || de->d_type == DT_UNKNOWN) {
- struct stat info;
- if (fstatat(dfd, de->d_name, &info, AT_SYMLINK_NOFOLLOW) != 0) {
- continue;
- }
-
- if (info.st_dev != dev) {
- continue;
- }
-
- if (S_ISDIR(info.st_mode)) {
- is_dir = true;
- auto fd = openat(dfd, de->d_name, O_RDONLY | O_DIRECTORY);
- if (fd >= 0) {
- auto subdir =
- std::unique_ptr<DIR, decltype(&closedir)>{fdopendir(fd), closedir};
- if (subdir) {
- FreeRamdisk(subdir.get(), dev);
- } else {
- close(fd);
- }
- }
- }
- }
- unlinkat(dfd, de->d_name, is_dir ? AT_REMOVEDIR : 0);
- }
-}
-
std::vector<std::string> GetMounts(const std::string& new_root) {
auto fp = std::unique_ptr<std::FILE, decltype(&endmntent)>{setmntent("/proc/mounts", "re"),
endmntent};
@@ -112,24 +72,16 @@ std::vector<std::string> GetMounts(const std::string& new_root) {
void SwitchRoot(const std::string& new_root) {
auto mounts = GetMounts(new_root);
+ LOG(INFO) << "Switching root to '" << new_root << "'";
+
for (const auto& mount_path : mounts) {
auto new_mount_path = new_root + mount_path;
+ mkdir(new_mount_path.c_str(), 0755);
if (mount(mount_path.c_str(), new_mount_path.c_str(), nullptr, MS_MOVE, nullptr) != 0) {
PLOG(FATAL) << "Unable to move mount at '" << mount_path << "'";
}
}
- auto old_root_dir = std::unique_ptr<DIR, decltype(&closedir)>{opendir("/"), closedir};
- if (!old_root_dir) {
- PLOG(ERROR) << "Could not opendir(\"/\"), not freeing ramdisk";
- }
-
- struct stat old_root_info;
- if (stat("/", &old_root_info) != 0) {
- PLOG(ERROR) << "Could not stat(\"/\"), not freeing ramdisk";
- old_root_dir.reset();
- }
-
if (chdir(new_root.c_str()) != 0) {
PLOG(FATAL) << "Could not chdir to new_root, '" << new_root << "'";
}
@@ -141,10 +93,6 @@ void SwitchRoot(const std::string& new_root) {
if (chroot(".") != 0) {
PLOG(FATAL) << "Unable to chroot to new root";
}
-
- if (old_root_dir) {
- FreeRamdisk(old_root_dir.get(), old_root_info.st_dev);
- }
}
} // namespace init