diff --git a/fs_mgr/libfstab/boot_config.cpp b/fs_mgr/libfstab/boot_config.cpp index 53c843e93..ae537b5d2 100644 --- a/fs_mgr/libfstab/boot_config.cpp +++ b/fs_mgr/libfstab/boot_config.cpp @@ -17,11 +17,9 @@ #include #include #include -#include #include #include -#include #include #include "fstab_priv.h" @@ -35,7 +33,7 @@ const std::string& GetAndroidDtDir() { static const std::string kAndroidDtDir = [] { std::string android_dt_dir; if ((GetBootconfig("androidboot.android_dt_dir", &android_dt_dir) || - fs_mgr_get_boot_config_from_kernel_cmdline("android_dt_dir", &android_dt_dir)) && + GetKernelCmdline("androidboot.android_dt_dir", &android_dt_dir)) && !android_dt_dir.empty()) { // Ensure the returned path ends with a / if (android_dt_dir.back() != '/') { @@ -110,13 +108,10 @@ bool GetBootconfig(const std::string& key, std::string* out) { return GetBootconfigFromString(bootconfig, key, out); } -} // namespace fs_mgr -} // namespace android - -std::vector> fs_mgr_parse_cmdline(const std::string& cmdline) { +void ImportKernelCmdlineFromString(const std::string& cmdline, + const std::function& fn) { static constexpr char quote = '"'; - std::vector> result; size_t base = 0; while (true) { // skip quoted spans @@ -135,48 +130,46 @@ std::vector> fs_mgr_parse_cmdline(const std: if (equal_sign == piece.npos) { if (!piece.empty()) { // no difference between and = - result.emplace_back(std::move(piece), ""); + fn(std::move(piece), ""); } } else { - result.emplace_back(piece.substr(0, equal_sign), piece.substr(equal_sign + 1)); + fn(piece.substr(0, equal_sign), piece.substr(equal_sign + 1)); } if (found == cmdline.npos) break; base = found + 1; } - - return result; } -bool fs_mgr_get_boot_config_from_kernel(const std::string& cmdline, const std::string& android_key, - std::string* out_val) { - FSTAB_CHECK(out_val != nullptr); - - const std::string cmdline_key("androidboot." + android_key); - for (const auto& [key, value] : fs_mgr_parse_cmdline(cmdline)) { - if (key == cmdline_key) { - *out_val = value; - return true; +bool GetKernelCmdlineFromString(const std::string& cmdline, const std::string& key, + std::string* out) { + bool found = false; + ImportKernelCmdlineFromString(cmdline, [&](std::string config_key, std::string value) { + if (!found && config_key == key) { + *out = std::move(value); + found = true; } - } - - *out_val = ""; - return false; + }); + return found; } -// Tries to get the given boot config value from kernel cmdline. -// Returns true if successfully found, false otherwise. -bool fs_mgr_get_boot_config_from_kernel_cmdline(const std::string& key, std::string* out_val) { +void ImportKernelCmdline(const std::function& fn) { std::string cmdline; - if (!android::base::ReadFileToString("/proc/cmdline", &cmdline)) return false; - if (!cmdline.empty() && cmdline.back() == '\n') { - cmdline.pop_back(); - } - return fs_mgr_get_boot_config_from_kernel(cmdline, key, out_val); + android::base::ReadFileToString("/proc/cmdline", &cmdline); + ImportKernelCmdlineFromString(android::base::Trim(cmdline), fn); } -// Tries to get the boot config value in device tree, properties and -// kernel cmdline (in that order). Returns 'true' if successfully -// found, 'false' otherwise. +bool GetKernelCmdline(const std::string& key, std::string* out) { + std::string cmdline; + android::base::ReadFileToString("/proc/cmdline", &cmdline); + return GetKernelCmdlineFromString(android::base::Trim(cmdline), key, out); +} + +} // namespace fs_mgr +} // namespace android + +// Tries to get the boot config value in device tree, properties, kernel bootconfig and kernel +// cmdline (in that order). +// Returns 'true' if successfully found, 'false' otherwise. bool fs_mgr_get_boot_config(const std::string& key, std::string* out_val) { FSTAB_CHECK(out_val != nullptr); @@ -204,7 +197,7 @@ bool fs_mgr_get_boot_config(const std::string& key, std::string* out_val) { } // finally, fallback to kernel cmdline, properties may not be ready yet - if (fs_mgr_get_boot_config_from_kernel_cmdline(key, out_val)) { + if (android::fs_mgr::GetKernelCmdline(config_key, out_val)) { return true; } diff --git a/fs_mgr/libfstab/fstab.cpp b/fs_mgr/libfstab/fstab.cpp index 3cbd8c819..21b002434 100644 --- a/fs_mgr/libfstab/fstab.cpp +++ b/fs_mgr/libfstab/fstab.cpp @@ -863,11 +863,11 @@ const FstabEntry* GetEntryForMountPoint(const Fstab* fstab, const std::string& p } std::set GetBootDevices() { + std::set boot_devices; // First check bootconfig, then kernel commandline, then the device tree std::string value; if (GetBootconfig("androidboot.boot_devices", &value) || GetBootconfig("androidboot.boot_device", &value)) { - std::set boot_devices; // split by spaces and trim the trailing comma. for (std::string_view device : android::base::Split(value, " ")) { base::ConsumeSuffix(&device, ","); @@ -876,25 +876,19 @@ std::set GetBootDevices() { return boot_devices; } - std::string dt_file_name = GetAndroidDtDir() + "boot_devices"; - if (fs_mgr_get_boot_config_from_kernel_cmdline("boot_devices", &value) || - ReadDtFile(dt_file_name, &value)) { - auto boot_devices = Split(value, ","); - return std::set(boot_devices.begin(), boot_devices.end()); + const std::string dt_file_name = GetAndroidDtDir() + "boot_devices"; + if (GetKernelCmdline("androidboot.boot_devices", &value) || ReadDtFile(dt_file_name, &value)) { + auto boot_devices_list = Split(value, ","); + return {boot_devices_list.begin(), boot_devices_list.end()}; } - std::string cmdline; - if (android::base::ReadFileToString("/proc/cmdline", &cmdline)) { - std::set boot_devices; - const std::string cmdline_key = "androidboot.boot_device"; - for (const auto& [key, value] : fs_mgr_parse_cmdline(cmdline)) { - if (key == cmdline_key) { - boot_devices.emplace(value); - } - } - if (!boot_devices.empty()) { - return boot_devices; + ImportKernelCmdline([&](std::string key, std::string value) { + if (key == "androidboot.boot_device") { + boot_devices.emplace(std::move(value)); } + }); + if (!boot_devices.empty()) { + return boot_devices; } // Fallback to extract boot devices from fstab. diff --git a/fs_mgr/libfstab/fstab_priv.h b/fs_mgr/libfstab/fstab_priv.h index cc5682567..5105da001 100644 --- a/fs_mgr/libfstab/fstab_priv.h +++ b/fs_mgr/libfstab/fstab_priv.h @@ -18,17 +18,11 @@ #include #include -#include -#include #include // Do not include logging_macros.h here as this header is used by fs_mgr, too. -std::vector> fs_mgr_parse_cmdline(const std::string& cmdline); -bool fs_mgr_get_boot_config_from_kernel(const std::string& cmdline, const std::string& key, - std::string* out_val); -bool fs_mgr_get_boot_config_from_kernel_cmdline(const std::string& key, std::string* out_val); bool fs_mgr_get_boot_config(const std::string& key, std::string* out_val); bool fs_mgr_update_for_slotselect(android::fs_mgr::Fstab* fstab); @@ -48,5 +42,11 @@ void ImportBootconfigFromString(const std::string& bootconfig, bool GetBootconfigFromString(const std::string& bootconfig, const std::string& key, std::string* out); +void ImportKernelCmdlineFromString(const std::string& cmdline, + const std::function& fn); + +bool GetKernelCmdlineFromString(const std::string& cmdline, const std::string& key, + std::string* out); + } // namespace fs_mgr } // namespace android diff --git a/fs_mgr/libfstab/include/fstab/fstab.h b/fs_mgr/libfstab/include/fstab/fstab.h index 79a07eef2..150a47da3 100644 --- a/fs_mgr/libfstab/include/fstab/fstab.h +++ b/fs_mgr/libfstab/include/fstab/fstab.h @@ -137,5 +137,13 @@ void ImportBootconfig(const std::function& fn); // Otherwise returns false and |*out| is not modified. bool GetBootconfig(const std::string& key, std::string* out); +// Import the kernel cmdline by calling the callback |fn| with each key-value pair. +void ImportKernelCmdline(const std::function& fn); + +// Get the kernel cmdline value for |key|. +// Returns true if |key| is found in the kernel cmdline. +// Otherwise returns false and |*out| is not modified. +bool GetKernelCmdline(const std::string& key, std::string* out); + } // namespace fs_mgr } // namespace android diff --git a/fs_mgr/tests/fs_mgr_test.cpp b/fs_mgr/tests/fs_mgr_test.cpp index fbed37160..322bf1b08 100644 --- a/fs_mgr/tests/fs_mgr_test.cpp +++ b/fs_mgr/tests/fs_mgr_test.cpp @@ -224,23 +224,32 @@ bool CompareFlags(FstabEntry::FsMgrFlags& lhs, FstabEntry::FsMgrFlags& rhs) { } // namespace -TEST(fs_mgr, fs_mgr_parse_cmdline) { - EXPECT_EQ(result_space, fs_mgr_parse_cmdline(cmdline)); +TEST(fs_mgr, ImportKernelCmdline) { + std::vector> result; + ImportKernelCmdlineFromString( + cmdline, [&](std::string key, std::string value) { result.emplace_back(key, value); }); + EXPECT_THAT(result, ContainerEq(result_space)); } -TEST(fs_mgr, fs_mgr_get_boot_config_from_kernel_cmdline) { +TEST(fs_mgr, GetKernelCmdline) { std::string content; - for (const auto& entry : result_space) { - static constexpr char androidboot[] = "androidboot."; - if (!android::base::StartsWith(entry.first, androidboot)) continue; - auto key = entry.first.substr(strlen(androidboot)); - EXPECT_TRUE(fs_mgr_get_boot_config_from_kernel(cmdline, key, &content)) << " for " << key; - EXPECT_EQ(entry.second, content); + for (const auto& [key, value] : result_space) { + EXPECT_TRUE(GetKernelCmdlineFromString(cmdline, key, &content)) << " for " << key; + EXPECT_EQ(content, value); } - EXPECT_FALSE(fs_mgr_get_boot_config_from_kernel(cmdline, "vbmeta.avb_versio", &content)); - EXPECT_TRUE(content.empty()) << content; - EXPECT_FALSE(fs_mgr_get_boot_config_from_kernel(cmdline, "nospace", &content)); - EXPECT_TRUE(content.empty()) << content; + + const std::string kUnmodifiedToken = ""; + content = kUnmodifiedToken; + EXPECT_FALSE(GetKernelCmdlineFromString(cmdline, "", &content)); + EXPECT_EQ(content, kUnmodifiedToken) << "output parameter shouldn't be overridden"; + + content = kUnmodifiedToken; + EXPECT_FALSE(GetKernelCmdlineFromString(cmdline, "androidboot.vbmeta.avb_versio", &content)); + EXPECT_EQ(content, kUnmodifiedToken) << "output parameter shouldn't be overridden"; + + content = kUnmodifiedToken; + EXPECT_FALSE(GetKernelCmdlineFromString(bootconfig, "androidboot.nospace", &content)); + EXPECT_EQ(content, kUnmodifiedToken) << "output parameter shouldn't be overridden"; } TEST(fs_mgr, ImportBootconfig) { @@ -260,17 +269,15 @@ TEST(fs_mgr, GetBootconfig) { const std::string kUnmodifiedToken = ""; content = kUnmodifiedToken; - EXPECT_FALSE(android::fs_mgr::GetBootconfigFromString(bootconfig, "", &content)); + EXPECT_FALSE(GetBootconfigFromString(bootconfig, "", &content)); EXPECT_EQ(content, kUnmodifiedToken) << "output parameter shouldn't be overridden"; content = kUnmodifiedToken; - EXPECT_FALSE(android::fs_mgr::GetBootconfigFromString( - bootconfig, "androidboot.vbmeta.avb_versio", &content)); + EXPECT_FALSE(GetBootconfigFromString(bootconfig, "androidboot.vbmeta.avb_versio", &content)); EXPECT_EQ(content, kUnmodifiedToken) << "output parameter shouldn't be overridden"; content = kUnmodifiedToken; - EXPECT_FALSE( - android::fs_mgr::GetBootconfigFromString(bootconfig, "androidboot.nospace", &content)); + EXPECT_FALSE(GetBootconfigFromString(bootconfig, "androidboot.nospace", &content)); EXPECT_EQ(content, kUnmodifiedToken) << "output parameter shouldn't be overridden"; } diff --git a/init/devices.cpp b/init/devices.cpp index 6b8474eaa..e76786a6d 100644 --- a/init/devices.cpp +++ b/init/devices.cpp @@ -204,7 +204,7 @@ std::string DeviceHandler::GetPartitionNameForDevice(const std::string& query_de partition_map.emplace_back(map_pieces[0], map_pieces[1]); } }; - ImportKernelCmdline(parser); + android::fs_mgr::ImportKernelCmdline(parser); android::fs_mgr::ImportBootconfig(parser); return partition_map; }(); diff --git a/init/property_service.cpp b/init/property_service.cpp index 35577874f..f5de17d82 100644 --- a/init/property_service.cpp +++ b/init/property_service.cpp @@ -1342,7 +1342,7 @@ static void ProcessKernelDt() { constexpr auto ANDROIDBOOT_PREFIX = "androidboot."sv; static void ProcessKernelCmdline() { - ImportKernelCmdline([&](const std::string& key, const std::string& value) { + android::fs_mgr::ImportKernelCmdline([&](const std::string& key, const std::string& value) { if (StartsWith(key, ANDROIDBOOT_PREFIX)) { InitPropertySet("ro.boot." + key.substr(ANDROIDBOOT_PREFIX.size()), value); } diff --git a/init/selinux.cpp b/init/selinux.cpp index 6fb028b16..f34474f85 100644 --- a/init/selinux.cpp +++ b/init/selinux.cpp @@ -101,23 +101,14 @@ namespace { enum EnforcingStatus { SELINUX_PERMISSIVE, SELINUX_ENFORCING }; EnforcingStatus StatusFromProperty() { - EnforcingStatus status = SELINUX_ENFORCING; - - ImportKernelCmdline([&](const std::string& key, const std::string& value) { - if (key == "androidboot.selinux" && value == "permissive") { - status = SELINUX_PERMISSIVE; - } - }); - - if (status == SELINUX_ENFORCING) { - std::string value; - if (android::fs_mgr::GetBootconfig("androidboot.selinux", &value) && - value == "permissive") { - status = SELINUX_PERMISSIVE; - } + std::string value; + if (android::fs_mgr::GetKernelCmdline("androidboot.selinux", &value) && value == "permissive") { + return SELINUX_PERMISSIVE; } - - return status; + if (android::fs_mgr::GetBootconfig("androidboot.selinux", &value) && value == "permissive") { + return SELINUX_PERMISSIVE; + } + return SELINUX_ENFORCING; } bool IsEnforcing() { diff --git a/init/util.cpp b/init/util.cpp index b34d45d70..e760a5969 100644 --- a/init/util.cpp +++ b/init/util.cpp @@ -242,18 +242,6 @@ int wait_for_file(const char* filename, std::chrono::nanoseconds timeout) { return -1; } -void ImportKernelCmdline(const std::function& fn) { - std::string cmdline; - android::base::ReadFileToString("/proc/cmdline", &cmdline); - - for (const auto& entry : android::base::Split(android::base::Trim(cmdline), " ")) { - std::vector pieces = android::base::Split(entry, "="); - if (pieces.size() == 2) { - fn(pieces[0], pieces[1]); - } - } -} - bool make_dir(const std::string& path, mode_t mode) { std::string secontext; if (SelabelLookupFileContext(path, mode, &secontext) && !secontext.empty()) { diff --git a/init/util.h b/init/util.h index 0b0ef632b..2d0218271 100644 --- a/init/util.h +++ b/init/util.h @@ -53,8 +53,7 @@ Result WriteFile(const std::string& path, const std::string& content); Result DecodeUid(const std::string& name); bool mkdir_recursive(const std::string& pathname, mode_t mode); -int wait_for_file(const char *filename, std::chrono::nanoseconds timeout); -void ImportKernelCmdline(const std::function&); +int wait_for_file(const char* filename, std::chrono::nanoseconds timeout); bool make_dir(const std::string& path, mode_t mode); bool is_dir(const char* pathname); Result ExpandProps(const std::string& src);