Loading init/first_stage_mount.cpp +2 −16 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #include "first_stage_mount.h" #include <stdlib.h> #include <sys/mount.h> #include <unistd.h> #include <chrono> Loading Loading @@ -123,18 +124,8 @@ static inline bool IsDtVbmetaCompatible() { return is_android_dt_value_expected("vbmeta/compatible", "android,vbmeta"); } static bool ForceNormalBoot() { static bool force_normal_boot = []() { std::string cmdline; android::base::ReadFileToString("/proc/cmdline", &cmdline); return cmdline.find("androidboot.force_normal_boot=1") != std::string::npos; }(); return force_normal_boot; } static bool IsRecoveryMode() { return !ForceNormalBoot() && access("/system/bin/recovery", F_OK) == 0; return access("/system/bin/recovery", F_OK) == 0; } // Class Definitions Loading Loading @@ -403,11 +394,6 @@ bool FirstStageMount::MountPartitions() { [](const auto& rec) { return rec->mount_point == "/system"s; }); if (system_partition != mount_fstab_recs_.end()) { if (ForceNormalBoot()) { free((*system_partition)->mount_point); (*system_partition)->mount_point = strdup("/system_recovery_mount"); } if (!MountPartition(*system_partition)) { return false; } Loading init/init_first_stage.cpp +86 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,8 @@ * limitations under the License. */ #include <dirent.h> #include <fcntl.h> #include <paths.h> #include <stdlib.h> #include <sys/mount.h> Loading @@ -26,19 +28,72 @@ #include <vector> #include <android-base/chrono_utils.h> #include <android-base/file.h> #include <android-base/logging.h> #include <cutils/android_reboot.h> #include <private/android_filesystem_config.h> #include "first_stage_mount.h" #include "reboot_utils.h" #include "switch_root.h" #include "util.h" using android::base::boot_clock; using namespace std::literals; namespace android { 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); } } bool ForceNormalBoot() { std::string cmdline; android::base::ReadFileToString("/proc/cmdline", &cmdline); return cmdline.find("androidboot.force_normal_boot=1") != std::string::npos; } } // namespace int main(int argc, char** argv) { if (REBOOT_BOOTLOADER_ON_PANIC) { InstallRebootSignalHandlers(); Loading Loading @@ -117,10 +172,41 @@ int main(int argc, char** argv) { LOG(INFO) << "init first stage started!"; 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 (ForceNormalBoot()) { mkdir("/first_stage_ramdisk", 0755); // SwitchRoot() must be called with a mount point as the target, so we bind mount the // target directory to itself here. if (mount("/first_stage_ramdisk", "/first_stage_ramdisk", nullptr, MS_BIND, nullptr) != 0) { LOG(FATAL) << "Could not bind mount /first_stage_ramdisk to itself"; } SwitchRoot("/first_stage_ramdisk"); } if (!DoFirstStageMount()) { LOG(FATAL) << "Failed to mount required partitions early ..."; } struct stat new_root_info; if (stat("/", &new_root_info) != 0) { PLOG(ERROR) << "Could not stat(\"/\"), not freeing ramdisk"; old_root_dir.reset(); } if (old_root_dir && old_root_info.st_dev != new_root_info.st_dev) { FreeRamdisk(old_root_dir.get(), old_root_info.st_dev); } SetInitAvbVersionInRecovery(); static constexpr uint32_t kNanosecondsPerMillisecond = 1e6; Loading init/switch_root.cpp +3 −55 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ #include "switch_root.h" #include <dirent.h> #include <fcntl.h> #include <mntent.h> #include <sys/mount.h> Loading @@ -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}; Loading Loading @@ -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 << "'"; } Loading @@ -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 Loading Loading
init/first_stage_mount.cpp +2 −16 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #include "first_stage_mount.h" #include <stdlib.h> #include <sys/mount.h> #include <unistd.h> #include <chrono> Loading Loading @@ -123,18 +124,8 @@ static inline bool IsDtVbmetaCompatible() { return is_android_dt_value_expected("vbmeta/compatible", "android,vbmeta"); } static bool ForceNormalBoot() { static bool force_normal_boot = []() { std::string cmdline; android::base::ReadFileToString("/proc/cmdline", &cmdline); return cmdline.find("androidboot.force_normal_boot=1") != std::string::npos; }(); return force_normal_boot; } static bool IsRecoveryMode() { return !ForceNormalBoot() && access("/system/bin/recovery", F_OK) == 0; return access("/system/bin/recovery", F_OK) == 0; } // Class Definitions Loading Loading @@ -403,11 +394,6 @@ bool FirstStageMount::MountPartitions() { [](const auto& rec) { return rec->mount_point == "/system"s; }); if (system_partition != mount_fstab_recs_.end()) { if (ForceNormalBoot()) { free((*system_partition)->mount_point); (*system_partition)->mount_point = strdup("/system_recovery_mount"); } if (!MountPartition(*system_partition)) { return false; } Loading
init/init_first_stage.cpp +86 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,8 @@ * limitations under the License. */ #include <dirent.h> #include <fcntl.h> #include <paths.h> #include <stdlib.h> #include <sys/mount.h> Loading @@ -26,19 +28,72 @@ #include <vector> #include <android-base/chrono_utils.h> #include <android-base/file.h> #include <android-base/logging.h> #include <cutils/android_reboot.h> #include <private/android_filesystem_config.h> #include "first_stage_mount.h" #include "reboot_utils.h" #include "switch_root.h" #include "util.h" using android::base::boot_clock; using namespace std::literals; namespace android { 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); } } bool ForceNormalBoot() { std::string cmdline; android::base::ReadFileToString("/proc/cmdline", &cmdline); return cmdline.find("androidboot.force_normal_boot=1") != std::string::npos; } } // namespace int main(int argc, char** argv) { if (REBOOT_BOOTLOADER_ON_PANIC) { InstallRebootSignalHandlers(); Loading Loading @@ -117,10 +172,41 @@ int main(int argc, char** argv) { LOG(INFO) << "init first stage started!"; 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 (ForceNormalBoot()) { mkdir("/first_stage_ramdisk", 0755); // SwitchRoot() must be called with a mount point as the target, so we bind mount the // target directory to itself here. if (mount("/first_stage_ramdisk", "/first_stage_ramdisk", nullptr, MS_BIND, nullptr) != 0) { LOG(FATAL) << "Could not bind mount /first_stage_ramdisk to itself"; } SwitchRoot("/first_stage_ramdisk"); } if (!DoFirstStageMount()) { LOG(FATAL) << "Failed to mount required partitions early ..."; } struct stat new_root_info; if (stat("/", &new_root_info) != 0) { PLOG(ERROR) << "Could not stat(\"/\"), not freeing ramdisk"; old_root_dir.reset(); } if (old_root_dir && old_root_info.st_dev != new_root_info.st_dev) { FreeRamdisk(old_root_dir.get(), old_root_info.st_dev); } SetInitAvbVersionInRecovery(); static constexpr uint32_t kNanosecondsPerMillisecond = 1e6; Loading
init/switch_root.cpp +3 −55 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ #include "switch_root.h" #include <dirent.h> #include <fcntl.h> #include <mntent.h> #include <sys/mount.h> Loading @@ -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}; Loading Loading @@ -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 << "'"; } Loading @@ -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 Loading