summaryrefslogtreecommitdiff
path: root/init/property_service.cpp
diff options
context:
space:
mode:
authorTom Cherry <tomcherry@google.com>2019-08-19 15:21:25 -0700
committerTom Cherry <tomcherry@google.com>2019-12-04 15:43:21 -0800
commitc88d8f93cfaa8cbf368a0fa94e8bc84bc55c3ece (patch)
tree3caaa75251230d98f2b21dadd9b8892c2442c976 /init/property_service.cpp
parentf7a6c4587f06bc7e79748acd97dc4dd5b741f328 (diff)
init: Replace property_set() with android::base::SetProperty()
Init is no longer a special case and talks to property service just like every other client, therefore move it away from property_set() and to android::base::SetProperty(). In doing so, this change moves the initial property set up from the kernel command line and property files directly into PropertyInit(). This makes the responsibilities between init and property services more clear. Test: boot, unit test cases Change-Id: I36b8c83e845d887f1b203355c2391ec123c3d05f
Diffstat (limited to 'init/property_service.cpp')
-rw-r--r--init/property_service.cpp149
1 files changed, 108 insertions, 41 deletions
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 7d707cc43..adf892905 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -97,8 +97,6 @@ static bool accept_messages = false;
static PropertyInfoAreaFile property_info_area;
-void CreateSerializedPropertyInfo();
-
struct PropertyAuditData {
const ucred* cr;
const char* name;
@@ -117,21 +115,6 @@ static int PropertyAuditCallback(void* data, security_class_t /*cls*/, char* buf
return 0;
}
-void property_init() {
- selinux_callback cb;
- cb.func_audit = PropertyAuditCallback;
- selinux_set_callback(SELINUX_CB_AUDIT, cb);
-
- mkdir("/dev/__properties__", S_IRWXU | S_IXGRP | S_IXOTH);
- CreateSerializedPropertyInfo();
- if (__system_property_area_init()) {
- LOG(FATAL) << "Failed to initialize property area";
- }
- if (!property_info_area.LoadDefaultPath()) {
- LOG(FATAL) << "Failed to load serialized property info file";
- }
-}
-
bool CanReadProperty(const std::string& source_context, const std::string& name) {
const char* target_context = nullptr;
property_info_area->GetPropertyInfo(name.c_str(), &target_context, nullptr);
@@ -527,20 +510,6 @@ uint32_t HandlePropertySet(const std::string& name, const std::string& value,
return PropertySet(name, value, error);
}
-uint32_t InitPropertySet(const std::string& name, const std::string& value) {
- uint32_t result = 0;
- ucred cr = {.pid = 1, .uid = 0, .gid = 0};
- std::string error;
- result = HandlePropertySet(name, value, kInitContext, cr, nullptr, &error);
- if (result != PROP_SUCCESS) {
- LOG(ERROR) << "Init cannot set '" << name << "' to '" << value << "': " << error;
- }
-
- return result;
-}
-
-uint32_t (*property_set)(const std::string& name, const std::string& value) = InitPropertySet;
-
static void handle_property_set_fd() {
static constexpr uint32_t kDefaultSocketTimeout = 2000; /* ms */
@@ -634,6 +603,18 @@ static void handle_property_set_fd() {
}
}
+uint32_t InitPropertySet(const std::string& name, const std::string& value) {
+ uint32_t result = 0;
+ ucred cr = {.pid = 1, .uid = 0, .gid = 0};
+ std::string error;
+ result = HandlePropertySet(name, value, kInitContext, cr, nullptr, &error);
+ if (result != PROP_SUCCESS) {
+ LOG(ERROR) << "Init cannot set '" << name << "' to '" << value << "': " << error;
+ }
+
+ return result;
+}
+
static bool load_properties_from_file(const char*, const char*,
std::map<std::string, std::string>*);
@@ -765,11 +746,11 @@ static void update_sys_usb_config() {
bool is_debuggable = android::base::GetBoolProperty("ro.debuggable", false);
std::string config = android::base::GetProperty("persist.sys.usb.config", "");
if (config.empty()) {
- property_set("persist.sys.usb.config", is_debuggable ? "adb" : "none");
+ InitPropertySet("persist.sys.usb.config", is_debuggable ? "adb" : "none");
} else if (is_debuggable && config.find("adb") == std::string::npos &&
config.length() + 4 < PROP_VALUE_MAX) {
config.append(",adb");
- property_set("persist.sys.usb.config", config);
+ InitPropertySet("persist.sys.usb.config", config);
}
}
@@ -890,7 +871,7 @@ static void property_derive_build_fingerprint() {
}
}
-void property_load_boot_defaults(bool load_debug_prop) {
+void PropertyLoadBootDefaults() {
// TODO(b/117892318): merge prop.default and build.prop files into one
// We read the properties and their values into a map, in order to always allow properties
// loaded in the later property files to override the properties in loaded in the earlier
@@ -916,7 +897,7 @@ void property_load_boot_defaults(bool load_debug_prop) {
load_properties_from_file("/product/build.prop", nullptr, &properties);
load_properties_from_file("/factory/factory.prop", "ro.*", &properties);
- if (load_debug_prop) {
+ if (access(kDebugRamdiskProp, R_OK) == 0) {
LOG(INFO) << "Loading " << kDebugRamdiskProp;
load_properties_from_file(kDebugRamdiskProp, nullptr, &properties);
}
@@ -1009,6 +990,97 @@ void CreateSerializedPropertyInfo() {
selinux_android_restorecon(kPropertyInfosPath, 0);
}
+static void ExportKernelBootProps() {
+ constexpr const char* UNSET = "";
+ struct {
+ const char* src_prop;
+ const char* dst_prop;
+ const char* default_value;
+ } prop_map[] = {
+ // clang-format off
+ { "ro.boot.serialno", "ro.serialno", UNSET, },
+ { "ro.boot.mode", "ro.bootmode", "unknown", },
+ { "ro.boot.baseband", "ro.baseband", "unknown", },
+ { "ro.boot.bootloader", "ro.bootloader", "unknown", },
+ { "ro.boot.hardware", "ro.hardware", "unknown", },
+ { "ro.boot.revision", "ro.revision", "0", },
+ // clang-format on
+ };
+ for (const auto& prop : prop_map) {
+ std::string value = GetProperty(prop.src_prop, prop.default_value);
+ if (value != UNSET) InitPropertySet(prop.dst_prop, value);
+ }
+}
+
+static void ProcessKernelDt() {
+ if (!is_android_dt_value_expected("compatible", "android,firmware")) {
+ return;
+ }
+
+ std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir(get_android_dt_dir().c_str()), closedir);
+ if (!dir) return;
+
+ std::string dt_file;
+ struct dirent* dp;
+ while ((dp = readdir(dir.get())) != NULL) {
+ if (dp->d_type != DT_REG || !strcmp(dp->d_name, "compatible") ||
+ !strcmp(dp->d_name, "name")) {
+ continue;
+ }
+
+ std::string file_name = get_android_dt_dir() + dp->d_name;
+
+ android::base::ReadFileToString(file_name, &dt_file);
+ std::replace(dt_file.begin(), dt_file.end(), ',', '.');
+
+ InitPropertySet("ro.boot."s + dp->d_name, dt_file);
+ }
+}
+
+static void ProcessKernelCmdline() {
+ bool for_emulator = false;
+ ImportKernelCmdline([&](const std::string& key, const std::string& value) {
+ if (key == "qemu") {
+ for_emulator = true;
+ } else if (StartsWith(key, "androidboot.")) {
+ InitPropertySet("ro.boot." + key.substr(12), value);
+ }
+ });
+
+ if (for_emulator) {
+ ImportKernelCmdline([&](const std::string& key, const std::string& value) {
+ // In the emulator, export any kernel option with the "ro.kernel." prefix.
+ InitPropertySet("ro.kernel." + key, value);
+ });
+ }
+}
+
+void PropertyInit() {
+ selinux_callback cb;
+ cb.func_audit = PropertyAuditCallback;
+ selinux_set_callback(SELINUX_CB_AUDIT, cb);
+
+ mkdir("/dev/__properties__", S_IRWXU | S_IXGRP | S_IXOTH);
+ CreateSerializedPropertyInfo();
+ if (__system_property_area_init()) {
+ LOG(FATAL) << "Failed to initialize property area";
+ }
+ if (!property_info_area.LoadDefaultPath()) {
+ LOG(FATAL) << "Failed to load serialized property info file";
+ }
+
+ // If arguments are passed both on the command line and in DT,
+ // properties set in DT always have priority over the command-line ones.
+ ProcessKernelDt();
+ ProcessKernelCmdline();
+
+ // Propagate the kernel variables to internal variables
+ // used by init as well as the current required properties.
+ ExportKernelBootProps();
+
+ PropertyLoadBootDefaults();
+}
+
static void HandleInitSocket() {
auto message = ReadMessage(init_socket);
if (!message) {
@@ -1075,7 +1147,7 @@ static void PropertyServiceThread() {
}
void StartPropertyService(int* epoll_socket) {
- property_set("ro.property_service.version", "2");
+ InitPropertySet("ro.property_service.version", "2");
int sockets[2];
if (socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0, sockets) != 0) {
@@ -1095,11 +1167,6 @@ void StartPropertyService(int* epoll_socket) {
listen(property_set_fd, 8);
std::thread{PropertyServiceThread}.detach();
-
- property_set = [](const std::string& key, const std::string& value) -> uint32_t {
- android::base::SetProperty(key, value);
- return 0;
- };
}
} // namespace init