diff options
Diffstat (limited to 'init/property_service.cpp')
-rw-r--r-- | init/property_service.cpp | 149 |
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 |