From a68ee762f7083a7ba320bf716e4d96ebad0beeaa Mon Sep 17 00:00:00 2001 From: Yifan Hong Date: Tue, 6 Oct 2020 16:58:19 -0700 Subject: [PATCH] Load boot image props. This change does the following: - Create /second_stage_resources empty dir at root. - At runtime: - At first stage init: - mount tmpfs to /second_stage_resources. - Copy /system/etc/ramdisk/build.prop to /second_stage_resources/system/etc/ramdisk/build.prop - At second stage init: - Load prop from the above path - umount /second_stage_resources Test: getprop -Z Test: getprop Bug: 169169031 Change-Id: I18b16aa5fd42fa44686c858982a17791b2d43489 --- init/Android.mk | 1 + init/first_stage_init.cpp | 20 ++++++++++++++++++++ init/init.cpp | 10 ++++++++++ init/property_service.cpp | 11 +++++++++++ init/second_stage_resources.h | 32 ++++++++++++++++++++++++++++++++ rootdir/Android.mk | 2 +- 6 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 init/second_stage_resources.h diff --git a/init/Android.mk b/init/Android.mk index da94daf44..7d7c827c6 100644 --- a/init/Android.mk +++ b/init/Android.mk @@ -80,6 +80,7 @@ LOCAL_POST_INSTALL_CMD := mkdir -p \ $(TARGET_RAMDISK_OUT)/dev \ $(TARGET_RAMDISK_OUT)/mnt \ $(TARGET_RAMDISK_OUT)/proc \ + $(TARGET_RAMDISK_OUT)/second_stage_resources \ $(TARGET_RAMDISK_OUT)/sys \ LOCAL_STATIC_LIBRARIES := \ diff --git a/init/first_stage_init.cpp b/init/first_stage_init.cpp index 021557697..554f301cc 100644 --- a/init/first_stage_init.cpp +++ b/init/first_stage_init.cpp @@ -41,6 +41,7 @@ #include "first_stage_console.h" #include "first_stage_mount.h" #include "reboot_utils.h" +#include "second_stage_resources.h" #include "switch_root.h" #include "util.h" @@ -235,6 +236,11 @@ int FirstStageMain(int argc, char** argv) { // /debug_ramdisk is used to preserve additional files from the debug ramdisk CHECKCALL(mount("tmpfs", "/debug_ramdisk", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV, "mode=0755,uid=0,gid=0")); + + // /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, + "mode=0755,uid=0,gid=0")) #undef CHECKCALL SetStdioToDevNull(argv); @@ -276,6 +282,20 @@ int FirstStageMain(int argc, char** argv) { StartConsole(); } + if (access(kBootImageRamdiskProp, F_OK) == 0) { + std::string dest = GetRamdiskPropForSecondStage(); + std::string dir = android::base::Dirname(dest); + std::error_code ec; + if (!fs::create_directories(dir, ec)) { + LOG(FATAL) << "Can't mkdir " << dir << ": " << ec.message(); + } + if (!fs::copy_file(kBootImageRamdiskProp, dest, ec)) { + LOG(FATAL) << "Can't copy " << kBootImageRamdiskProp << " to " << dest << ": " + << ec.message(); + } + LOG(INFO) << "Copied ramdisk prop to " << dest; + } + if (ForceNormalBoot(cmdline)) { mkdir("/first_stage_ramdisk", 0755); // SwitchRoot() must be called with a mount point as the target, so we bind mount the diff --git a/init/init.cpp b/init/init.cpp index 7d00538bb..ea0449446 100644 --- a/init/init.cpp +++ b/init/init.cpp @@ -71,6 +71,7 @@ #include "proto_utils.h" #include "reboot.h" #include "reboot_utils.h" +#include "second_stage_resources.h" #include "security.h" #include "selabel.h" #include "selinux.h" @@ -668,6 +669,12 @@ static void UmountDebugRamdisk() { } } +static void UmountSecondStageRes() { + if (umount(kSecondStageRes) != 0) { + PLOG(ERROR) << "Failed to umount " << kSecondStageRes; + } +} + static void MountExtraFilesystems() { #define CHECKCALL(x) \ if ((x) != 0) PLOG(FATAL) << #x " failed."; @@ -776,6 +783,9 @@ int SecondStageMain(int argc, char** argv) { PropertyInit(); + // Umount second stage resources after property service has read the .prop files. + UmountSecondStageRes(); + // Umount the debug ramdisk after property service has read the .prop files when it means to. if (load_debug_prop) { UmountDebugRamdisk(); diff --git a/init/property_service.cpp b/init/property_service.cpp index a1e0969ed..e4c98026a 100644 --- a/init/property_service.cpp +++ b/init/property_service.cpp @@ -67,6 +67,7 @@ #include "persistent_properties.h" #include "property_type.h" #include "proto_utils.h" +#include "second_stage_resources.h" #include "selinux.h" #include "subcontext.h" #include "system/core/init/property_service.pb.h" @@ -745,6 +746,15 @@ static bool load_properties_from_file(const char* filename, const char* filter, return true; } +static void LoadPropertiesFromSecondStageRes(std::map* properties) { + std::string prop = GetRamdiskPropForSecondStage(); + if (access(prop.c_str(), R_OK) != 0) { + CHECK(errno == ENOENT) << "Cannot access " << prop << ": " << strerror(errno); + return; + } + load_properties_from_file(prop.c_str(), nullptr, properties); +} + // persist.sys.usb.config values can't be combined on build-time when property // files are split into each partition. // So we need to apply the same rule of build/make/tools/post_process_props.py @@ -933,6 +943,7 @@ void PropertyLoadBootDefaults() { // Order matters here. The more the partition is specific to a product, the higher its // precedence is. + LoadPropertiesFromSecondStageRes(&properties); load_properties_from_file("/system/build.prop", nullptr, &properties); load_properties_from_partition("system_ext", /* support_legacy_path_until */ 30); // TODO(b/117892318): uncomment the following condition when vendor.imgs for aosp_* targets are diff --git a/init/second_stage_resources.h b/init/second_stage_resources.h new file mode 100644 index 000000000..544d16f53 --- /dev/null +++ b/init/second_stage_resources.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +namespace android { +namespace init { + +constexpr const char kSecondStageRes[] = "/second_stage_resources"; +constexpr const char kBootImageRamdiskProp[] = "/system/etc/ramdisk/build.prop"; + +inline std::string GetRamdiskPropForSecondStage() { + return std::string(kSecondStageRes) + kBootImageRamdiskProp; +} + +} // namespace init +} // namespace android diff --git a/rootdir/Android.mk b/rootdir/Android.mk index 77fa94e73..2bceb751a 100644 --- a/rootdir/Android.mk +++ b/rootdir/Android.mk @@ -78,7 +78,7 @@ endif # create some directories (some are mount points) and symlinks LOCAL_POST_INSTALL_CMD := mkdir -p $(addprefix $(TARGET_ROOT_OUT)/, \ dev proc sys system data data_mirror odm oem acct config storage mnt apex debug_ramdisk \ - linkerconfig $(BOARD_ROOT_EXTRA_FOLDERS)); \ + linkerconfig second_stage_resources $(BOARD_ROOT_EXTRA_FOLDERS)); \ ln -sf /system/bin $(TARGET_ROOT_OUT)/bin; \ ln -sf /system/etc $(TARGET_ROOT_OUT)/etc; \ ln -sf /data/user_de/0/com.android.shell/files/bugreports $(TARGET_ROOT_OUT)/bugreports; \