Loading fs_mgr/fs_mgr.cpp +5 −0 Original line number Diff line number Diff line Loading @@ -2335,6 +2335,11 @@ OverlayfsCheckResult CheckOverlayfs() { if (!fs_mgr_filesystem_available("overlay")) { return {.supported = false}; } if (!use_override_creds) { return {.supported = true}; } struct utsname uts; if (uname(&uts) == -1) { return {.supported = false}; Loading fs_mgr/include/fs_mgr_overlayfs.h +6 −0 Original line number Diff line number Diff line Loading @@ -43,5 +43,11 @@ void MapScratchPartitionIfNeeded(Fstab* fstab, // overlays if any partition is flashed or updated. void TeardownAllOverlayForMountPoint(const std::string& mount_point = {}); // Are we using overlayfs's non-upstreamed override_creds feature? // b/388912628 removes the need for override_creds // Once this bug is fixed and has had enough soak time, remove this variable and hard code to false // where it used constexpr bool use_override_creds = true; } // namespace fs_mgr } // namespace android init/Android.bp +6 −1 Original line number Diff line number Diff line Loading @@ -136,6 +136,8 @@ libinit_cc_defaults { "-DWORLD_WRITABLE_KMSG=1", "-UDUMP_ON_UMOUNT_FAILURE", "-DDUMP_ON_UMOUNT_FAILURE=1", "-UALLOW_REMOUNT_OVERLAYS", "-DALLOW_REMOUNT_OVERLAYS=1", ], }, eng: { Loading Loading @@ -263,7 +265,10 @@ phony { name: "init", required: [ "init_second_stage", ], ] + select(product_variable("debuggable"), { true: ["overlay_remounter"], false: [], }), } cc_defaults { Loading init/first_stage_init.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -402,7 +402,7 @@ int FirstStageMain(int argc, char** argv) { // /second_stage_resources is used to preserve files from first to second // stage init CHECKCALL(mount("tmpfs", kSecondStageRes, "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV, CHECKCALL(mount("tmpfs", kSecondStageRes, "tmpfs", MS_NOSUID | MS_NODEV, "mode=0755,uid=0,gid=0")); if (IsMicrodroid() && android::virtualization::IsOpenDiceChangesFlagEnabled()) { Loading init/selinux.cpp +65 −0 Original line number Diff line number Diff line Loading @@ -69,6 +69,7 @@ #include <android/avf_cc_flags.h> #include <fs_avb/fs_avb.h> #include <fs_mgr.h> #include <fs_mgr_overlayfs.h> #include <genfslabelsversion.h> #include <libgsi/libgsi.h> #include <libsnapshot/snapshot.h> Loading @@ -77,6 +78,7 @@ #include "block_dev_initializer.h" #include "debug_ramdisk.h" #include "reboot_utils.h" #include "second_stage_resources.h" #include "snapuserd_transition.h" #include "util.h" Loading Loading @@ -698,6 +700,65 @@ void LoadSelinuxPolicyAndroid() { } } #ifdef ALLOW_REMOUNT_OVERLAYS void SetupOverlays() { if (android::fs_mgr::use_override_creds) return; bool has_overlays = false; std::string contents; auto result = android::base::ReadFileToString("/proc/mounts", &contents, true); auto lines = android::base::Split(contents, "\n"); for (auto const& line : lines) if (android::base::StartsWith(line, "overlay")) { has_overlays = true; break; } if (!has_overlays) return; // After adb remount, we mount all r/o volumes with overlayfs to allow writing. // However, since overlayfs performs its file operations in the context of the // mounting process, this will not work as is - init is in the kernel domain in // first stage, which has very limited permissions. // In order to fix this, we need to unmount remount all these volumes from a process // with sufficient privileges to be able to perform these operations. The // overlay_remounter domain has those privileges on debuggable devices. // We will call overlay_remounter which will do the unmounts/mounts. // But for that to work, the volumes must not be busy, so we need to copy // overlay_remounter from system to a ramdisk and run it from there. const char* kOverlayRemounter = "overlay_remounter"; auto or_src = std::filesystem::path("/system/xbin/") / kOverlayRemounter; auto or_dest = std::filesystem::path(kSecondStageRes) / kOverlayRemounter; std::error_code ec; std::filesystem::copy(or_src, or_dest, ec); if (ec) { LOG(FATAL) << "Failed to copy " << or_src << " to " << or_dest << " " << ec.message(); } if (selinux_android_restorecon(or_dest.c_str(), 0) == -1) { PLOG(FATAL) << "restorecon of " << or_dest << " failed"; } auto dest = unique_fd(open(or_dest.c_str(), O_RDONLY | O_CLOEXEC)); if (dest.get() == -1) { PLOG(FATAL) << "Failed to reopen " << or_dest; } if (unlink(or_dest.c_str()) == -1) { PLOG(FATAL) << "Failed to unlink " << or_dest; } const char* args[] = {or_dest.c_str(), nullptr}; fexecve(dest.get(), const_cast<char**>(args), nullptr); // execv() only returns if an error happened, in which case we // panic and never return from this function. PLOG(FATAL) << "execv(\"" << or_dest << "\") failed"; } #else void SetupOverlays() {} #endif int SetupSelinux(char** argv) { SetStdioToDevNull(argv); InitKernelLogging(argv); Loading Loading @@ -738,6 +799,10 @@ int SetupSelinux(char** argv) { setenv(kEnvSelinuxStartedAt, std::to_string(start_time.time_since_epoch().count()).c_str(), 1); // SetupOverlays does not return if overlays exist, instead it execs overlay_remounter // which then execs second stage init SetupOverlays(); const char* path = "/system/bin/init"; const char* args[] = {path, "second_stage", nullptr}; execv(path, const_cast<char**>(args)); Loading Loading
fs_mgr/fs_mgr.cpp +5 −0 Original line number Diff line number Diff line Loading @@ -2335,6 +2335,11 @@ OverlayfsCheckResult CheckOverlayfs() { if (!fs_mgr_filesystem_available("overlay")) { return {.supported = false}; } if (!use_override_creds) { return {.supported = true}; } struct utsname uts; if (uname(&uts) == -1) { return {.supported = false}; Loading
fs_mgr/include/fs_mgr_overlayfs.h +6 −0 Original line number Diff line number Diff line Loading @@ -43,5 +43,11 @@ void MapScratchPartitionIfNeeded(Fstab* fstab, // overlays if any partition is flashed or updated. void TeardownAllOverlayForMountPoint(const std::string& mount_point = {}); // Are we using overlayfs's non-upstreamed override_creds feature? // b/388912628 removes the need for override_creds // Once this bug is fixed and has had enough soak time, remove this variable and hard code to false // where it used constexpr bool use_override_creds = true; } // namespace fs_mgr } // namespace android
init/Android.bp +6 −1 Original line number Diff line number Diff line Loading @@ -136,6 +136,8 @@ libinit_cc_defaults { "-DWORLD_WRITABLE_KMSG=1", "-UDUMP_ON_UMOUNT_FAILURE", "-DDUMP_ON_UMOUNT_FAILURE=1", "-UALLOW_REMOUNT_OVERLAYS", "-DALLOW_REMOUNT_OVERLAYS=1", ], }, eng: { Loading Loading @@ -263,7 +265,10 @@ phony { name: "init", required: [ "init_second_stage", ], ] + select(product_variable("debuggable"), { true: ["overlay_remounter"], false: [], }), } cc_defaults { Loading
init/first_stage_init.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -402,7 +402,7 @@ int FirstStageMain(int argc, char** argv) { // /second_stage_resources is used to preserve files from first to second // stage init CHECKCALL(mount("tmpfs", kSecondStageRes, "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV, CHECKCALL(mount("tmpfs", kSecondStageRes, "tmpfs", MS_NOSUID | MS_NODEV, "mode=0755,uid=0,gid=0")); if (IsMicrodroid() && android::virtualization::IsOpenDiceChangesFlagEnabled()) { Loading
init/selinux.cpp +65 −0 Original line number Diff line number Diff line Loading @@ -69,6 +69,7 @@ #include <android/avf_cc_flags.h> #include <fs_avb/fs_avb.h> #include <fs_mgr.h> #include <fs_mgr_overlayfs.h> #include <genfslabelsversion.h> #include <libgsi/libgsi.h> #include <libsnapshot/snapshot.h> Loading @@ -77,6 +78,7 @@ #include "block_dev_initializer.h" #include "debug_ramdisk.h" #include "reboot_utils.h" #include "second_stage_resources.h" #include "snapuserd_transition.h" #include "util.h" Loading Loading @@ -698,6 +700,65 @@ void LoadSelinuxPolicyAndroid() { } } #ifdef ALLOW_REMOUNT_OVERLAYS void SetupOverlays() { if (android::fs_mgr::use_override_creds) return; bool has_overlays = false; std::string contents; auto result = android::base::ReadFileToString("/proc/mounts", &contents, true); auto lines = android::base::Split(contents, "\n"); for (auto const& line : lines) if (android::base::StartsWith(line, "overlay")) { has_overlays = true; break; } if (!has_overlays) return; // After adb remount, we mount all r/o volumes with overlayfs to allow writing. // However, since overlayfs performs its file operations in the context of the // mounting process, this will not work as is - init is in the kernel domain in // first stage, which has very limited permissions. // In order to fix this, we need to unmount remount all these volumes from a process // with sufficient privileges to be able to perform these operations. The // overlay_remounter domain has those privileges on debuggable devices. // We will call overlay_remounter which will do the unmounts/mounts. // But for that to work, the volumes must not be busy, so we need to copy // overlay_remounter from system to a ramdisk and run it from there. const char* kOverlayRemounter = "overlay_remounter"; auto or_src = std::filesystem::path("/system/xbin/") / kOverlayRemounter; auto or_dest = std::filesystem::path(kSecondStageRes) / kOverlayRemounter; std::error_code ec; std::filesystem::copy(or_src, or_dest, ec); if (ec) { LOG(FATAL) << "Failed to copy " << or_src << " to " << or_dest << " " << ec.message(); } if (selinux_android_restorecon(or_dest.c_str(), 0) == -1) { PLOG(FATAL) << "restorecon of " << or_dest << " failed"; } auto dest = unique_fd(open(or_dest.c_str(), O_RDONLY | O_CLOEXEC)); if (dest.get() == -1) { PLOG(FATAL) << "Failed to reopen " << or_dest; } if (unlink(or_dest.c_str()) == -1) { PLOG(FATAL) << "Failed to unlink " << or_dest; } const char* args[] = {or_dest.c_str(), nullptr}; fexecve(dest.get(), const_cast<char**>(args), nullptr); // execv() only returns if an error happened, in which case we // panic and never return from this function. PLOG(FATAL) << "execv(\"" << or_dest << "\") failed"; } #else void SetupOverlays() {} #endif int SetupSelinux(char** argv) { SetStdioToDevNull(argv); InitKernelLogging(argv); Loading Loading @@ -738,6 +799,10 @@ int SetupSelinux(char** argv) { setenv(kEnvSelinuxStartedAt, std::to_string(start_time.time_since_epoch().count()).c_str(), 1); // SetupOverlays does not return if overlays exist, instead it execs overlay_remounter // which then execs second stage init SetupOverlays(); const char* path = "/system/bin/init"; const char* args[] = {path, "second_stage", nullptr}; execv(path, const_cast<char**>(args)); Loading