Merge "init: Use libfs_mgr kernel cmdline parser" into main
This commit is contained in:
commit
63a3f34e4c
10 changed files with 90 additions and 110 deletions
|
@ -17,11 +17,9 @@
|
|||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <android-base/file.h>
|
||||
#include <android-base/properties.h>
|
||||
#include <android-base/stringprintf.h>
|
||||
#include <android-base/strings.h>
|
||||
|
||||
#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<std::pair<std::string, std::string>> fs_mgr_parse_cmdline(const std::string& cmdline) {
|
||||
void ImportKernelCmdlineFromString(const std::string& cmdline,
|
||||
const std::function<void(std::string, std::string)>& fn) {
|
||||
static constexpr char quote = '"';
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> result;
|
||||
size_t base = 0;
|
||||
while (true) {
|
||||
// skip quoted spans
|
||||
|
@ -135,48 +130,46 @@ std::vector<std::pair<std::string, std::string>> fs_mgr_parse_cmdline(const std:
|
|||
if (equal_sign == piece.npos) {
|
||||
if (!piece.empty()) {
|
||||
// no difference between <key> and <key>=
|
||||
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<void(std::string, std::string)>& 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -863,11 +863,11 @@ const FstabEntry* GetEntryForMountPoint(const Fstab* fstab, const std::string& p
|
|||
}
|
||||
|
||||
std::set<std::string> GetBootDevices() {
|
||||
std::set<std::string> 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<std::string> 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<std::string> 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<std::string>(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<std::string> 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.
|
||||
|
|
|
@ -18,17 +18,11 @@
|
|||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <fstab/fstab.h>
|
||||
|
||||
// Do not include logging_macros.h here as this header is used by fs_mgr, too.
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> 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<void(std::string, std::string)>& fn);
|
||||
|
||||
bool GetKernelCmdlineFromString(const std::string& cmdline, const std::string& key,
|
||||
std::string* out);
|
||||
|
||||
} // namespace fs_mgr
|
||||
} // namespace android
|
||||
|
|
|
@ -137,5 +137,13 @@ void ImportBootconfig(const std::function<void(std::string, std::string)>& 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<void(std::string, std::string)>& 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
|
||||
|
|
|
@ -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<std::pair<std::string, std::string>> 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 = "<UNMODIFIED>";
|
||||
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 = "<UNMODIFIED>";
|
||||
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";
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -242,18 +242,6 @@ int wait_for_file(const char* filename, std::chrono::nanoseconds timeout) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
void ImportKernelCmdline(const std::function<void(const std::string&, const std::string&)>& fn) {
|
||||
std::string cmdline;
|
||||
android::base::ReadFileToString("/proc/cmdline", &cmdline);
|
||||
|
||||
for (const auto& entry : android::base::Split(android::base::Trim(cmdline), " ")) {
|
||||
std::vector<std::string> 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()) {
|
||||
|
|
|
@ -53,8 +53,7 @@ Result<void> WriteFile(const std::string& path, const std::string& content);
|
|||
Result<uid_t> 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<void(const std::string&, const std::string&)>&);
|
||||
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<std::string> ExpandProps(const std::string& src);
|
||||
|
|
Loading…
Reference in a new issue