Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 75924028 authored by Tom Cherry's avatar Tom Cherry Committed by Gerrit Code Review
Browse files

Merge "init: Replace property_set() with android::base::SetProperty()"

parents bb4754be c88d8f93
Loading
Loading
Loading
Loading
+16 −15
Original line number Diff line number Diff line
@@ -84,6 +84,7 @@
using namespace std::literals::string_literals;

using android::base::Basename;
using android::base::SetProperty;
using android::base::StartsWith;
using android::base::StringPrintf;
using android::base::unique_fd;
@@ -561,16 +562,16 @@ static Result<void> queue_fs_event(int code, bool userdata_remount) {
            LOG(ERROR) << "Userdata remount is not supported on FDE devices. How did you get here?";
            trigger_shutdown("reboot,requested-userdata-remount-on-fde-device");
        }
        property_set("ro.crypto.state", "encrypted");
        property_set("ro.crypto.type", "block");
        SetProperty("ro.crypto.state", "encrypted");
        SetProperty("ro.crypto.type", "block");
        ActionManager::GetInstance().QueueEventTrigger("defaultcrypto");
        return {};
    } else if (code == FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) {
        property_set("ro.crypto.state", "unencrypted");
        SetProperty("ro.crypto.state", "unencrypted");
        ActionManager::GetInstance().QueueEventTrigger("nonencrypted");
        return {};
    } else if (code == FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE) {
        property_set("ro.crypto.state", "unsupported");
        SetProperty("ro.crypto.state", "unsupported");
        ActionManager::GetInstance().QueueEventTrigger("nonencrypted");
        return {};
    } else if (code == FS_MGR_MNTALL_DEV_NEEDS_RECOVERY) {
@@ -586,8 +587,8 @@ static Result<void> queue_fs_event(int code, bool userdata_remount) {
        if (!FscryptInstallKeyring()) {
            return Error() << "FscryptInstallKeyring() failed";
        }
        property_set("ro.crypto.state", "encrypted");
        property_set("ro.crypto.type", "file");
        SetProperty("ro.crypto.state", "encrypted");
        SetProperty("ro.crypto.type", "file");

        // Although encrypted, we have device key, so we do not need to
        // do anything different from the nonencrypted case.
@@ -597,8 +598,8 @@ static Result<void> queue_fs_event(int code, bool userdata_remount) {
        if (!FscryptInstallKeyring()) {
            return Error() << "FscryptInstallKeyring() failed";
        }
        property_set("ro.crypto.state", "encrypted");
        property_set("ro.crypto.type", "file");
        SetProperty("ro.crypto.state", "encrypted");
        SetProperty("ro.crypto.type", "file");

        // Although encrypted, vold has already set the device up, so we do not need to
        // do anything different from the nonencrypted case.
@@ -608,8 +609,8 @@ static Result<void> queue_fs_event(int code, bool userdata_remount) {
        if (!FscryptInstallKeyring()) {
            return Error() << "FscryptInstallKeyring() failed";
        }
        property_set("ro.crypto.state", "encrypted");
        property_set("ro.crypto.type", "file");
        SetProperty("ro.crypto.state", "encrypted");
        SetProperty("ro.crypto.type", "file");

        // Although encrypted, vold has already set the device up, so we do not need to
        // do anything different from the nonencrypted case.
@@ -662,7 +663,7 @@ static Result<void> do_mount_all(const BuiltinArguments& args) {
    }

    auto mount_fstab_return_code = fs_mgr_mount_all(&fstab, mount_mode);
    property_set(prop_name, std::to_string(t.duration().count()));
    SetProperty(prop_name, std::to_string(t.duration().count()));

    if (import_rc && SelinuxGetVendorAndroidVersion() <= __ANDROID_API_Q__) {
        /* Paths of .rc files are specified at the 2nd argument and beyond */
@@ -718,7 +719,7 @@ static Result<void> do_setprop(const BuiltinArguments& args) {
                       << "' from init; use the restorecon builtin directly";
    }

    property_set(args[1], args[2]);
    SetProperty(args[1], args[2]);
    return {};
}

@@ -832,7 +833,7 @@ static Result<void> do_verity_update_state(const BuiltinArguments& args) {
        // To be consistent in vboot 1.0 and vboot 2.0 (AVB), use "system" for the partition even
        // for system as root, so it has property [partition.system.verified].
        std::string partition = entry.mount_point == "/" ? "system" : Basename(entry.mount_point);
        property_set("partition." + partition + ".verified", std::to_string(mode));
        SetProperty("partition." + partition + ".verified", std::to_string(mode));
    }

    return {};
@@ -1221,7 +1222,7 @@ static Result<void> do_enter_default_mount_ns(const BuiltinArguments& args) {
static Result<void> do_finish_userspace_reboot(const BuiltinArguments&) {
    LOG(INFO) << "Userspace reboot successfully finished";
    boot_clock::time_point now = boot_clock::now();
    property_set("sys.init.userspace_reboot.last_finished",
    SetProperty("sys.init.userspace_reboot.last_finished",
                std::to_string(now.time_since_epoch().count()));
    if (!android::sysprop::InitProperties::userspace_reboot_in_progress(false)) {
        return Error() << "Failed to set sys.init.userspace_reboot.in_progress property";
+0 −9
Original line number Diff line number Diff line
@@ -39,15 +39,6 @@ namespace init {
inline bool CanReadProperty(const std::string&, const std::string&) {
    return true;
}
inline uint32_t SetProperty(const std::string& key, const std::string& value) {
    android::base::SetProperty(key, value);
    return 0;
}
inline uint32_t (*property_set)(const std::string& name, const std::string& value) = SetProperty;
inline uint32_t HandlePropertySet(const std::string&, const std::string&, const std::string&,
                                  const ucred&, std::string*) {
    return 0;
}

// reboot_utils.h
inline void SetFatalRebootTarget() {}
+40 −113
Original line number Diff line number Diff line
@@ -81,6 +81,7 @@ using namespace std::string_literals;
using android::base::boot_clock;
using android::base::GetProperty;
using android::base::ReadFileToString;
using android::base::SetProperty;
using android::base::StringPrintf;
using android::base::Timer;
using android::base::Trim;
@@ -91,8 +92,6 @@ namespace init {

static int property_triggers_enabled = 0;

static char qemu[32];

static int signal_fd = -1;
static int property_fd = -1;

@@ -101,7 +100,6 @@ static std::string wait_prop_name;
static std::string wait_prop_value;
static std::string shutdown_command;
static bool do_shutdown = false;
static bool load_debug_prop = false;

static std::unique_ptr<Subcontext> subcontext;

@@ -208,7 +206,7 @@ void property_changed(const std::string& name, const std::string& value) {
    // to wait.
    if (name == kColdBootDoneProp) {
        auto time_waited = waiting_for_prop ? waiting_for_prop->duration().count() : 0;
        property_set("ro.boottime.init.cold_boot_wait", std::to_string(time_waited));
        SetProperty("ro.boottime.init.cold_boot_wait", std::to_string(time_waited));
    }

    if (waiting_for_prop) {
@@ -364,87 +362,17 @@ static Result<void> SetupCgroupsAction(const BuiltinArguments&) {
    return {};
}

static void import_kernel_nv(const std::string& key, const std::string& value, bool for_emulator) {
    if (key.empty()) return;

    if (for_emulator) {
        // In the emulator, export any kernel option with the "ro.kernel." prefix.
        property_set("ro.kernel." + key, value);
        return;
    }

    if (key == "qemu") {
        strlcpy(qemu, value.c_str(), sizeof(qemu));
    } else if (android::base::StartsWith(key, "androidboot.")) {
        property_set("ro.boot." + key.substr(12), value);
    }
}

static void export_oem_lock_status() {
    if (!android::base::GetBoolProperty("ro.oem_unlock_supported", false)) {
        return;
    }
    import_kernel_cmdline(
            false, [](const std::string& key, const std::string& value, bool in_qemu) {
    ImportKernelCmdline([](const std::string& key, const std::string& value) {
        if (key == "androidboot.verifiedbootstate") {
                    property_set("ro.boot.flash.locked", value == "orange" ? "0" : "1");
            SetProperty("ro.boot.flash.locked", value == "orange" ? "0" : "1");
        }
    });
}

static void export_kernel_boot_props() {
    constexpr const char* UNSET = "";
    struct {
        const char *src_prop;
        const char *dst_prop;
        const char *default_value;
    } prop_map[] = {
        { "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", },
    };
    for (const auto& prop : prop_map) {
        std::string value = GetProperty(prop.src_prop, prop.default_value);
        if (value != UNSET)
            property_set(prop.dst_prop, value);
    }
}

static void process_kernel_dt() {
    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(), ',', '.');

        property_set("ro.boot."s + dp->d_name, dt_file);
    }
}

static void process_kernel_cmdline() {
    // The first pass does the common stuff, and finds if we are in qemu.
    // The second pass is only necessary for qemu to export all kernel params
    // as properties.
    import_kernel_cmdline(false, import_kernel_nv);
    if (qemu[0]) import_kernel_cmdline(true, import_kernel_nv);
}

static Result<void> property_enable_triggers_action(const BuiltinArguments& args) {
    /* Enable property triggers. */
    property_triggers_enabled = 1;
@@ -468,7 +396,7 @@ static void set_usb_controller() {
    while ((dp = readdir(dir.get())) != nullptr) {
        if (dp->d_name[0] == '.') continue;

        property_set("sys.usb.controller", dp->d_name);
        SetProperty("sys.usb.controller", dp->d_name);
        break;
    }
}
@@ -591,7 +519,7 @@ static void RecordStageBoottimes(const boot_clock::time_point& second_stage_star
    int64_t first_stage_start_time_ns = -1;
    if (auto first_stage_start_time_str = getenv(kEnvFirstStageStartedAt);
        first_stage_start_time_str) {
        property_set("ro.boottime.init", first_stage_start_time_str);
        SetProperty("ro.boottime.init", first_stage_start_time_str);
        android::base::ParseInt(first_stage_start_time_str, &first_stage_start_time_ns);
    }
    unsetenv(kEnvFirstStageStartedAt);
@@ -605,9 +533,9 @@ static void RecordStageBoottimes(const boot_clock::time_point& second_stage_star
    if (selinux_start_time_ns == -1) return;
    if (first_stage_start_time_ns == -1) return;

    property_set("ro.boottime.init.first_stage",
    SetProperty("ro.boottime.init.first_stage",
                std::to_string(selinux_start_time_ns - first_stage_start_time_ns));
    property_set("ro.boottime.init.selinux",
    SetProperty("ro.boottime.init.selinux",
                std::to_string(second_stage_start_time.time_since_epoch().count() -
                               selinux_start_time_ns));
}
@@ -706,34 +634,27 @@ int SecondStageMain(int argc, char** argv) {
    // Indicate that booting is in progress to background fw loaders, etc.
    close(open("/dev/.booting", O_WRONLY | O_CREAT | O_CLOEXEC, 0000));

    property_init();

    // If arguments are passed both on the command line and in DT,
    // properties set in DT always have priority over the command-line ones.
    process_kernel_dt();
    process_kernel_cmdline();

    // Propagate the kernel variables to internal variables
    // used by init as well as the current required properties.
    export_kernel_boot_props();

    // Make the time that init stages started available for bootstat to log.
    RecordStageBoottimes(start_time);

    // Set libavb version for Framework-only OTA match in Treble build.
    const char* avb_version = getenv("INIT_AVB_VERSION");
    if (avb_version) property_set("ro.boot.avb_version", avb_version);

    // See if need to load debug props to allow adb root, when the device is unlocked.
    const char* force_debuggable_env = getenv("INIT_FORCE_DEBUGGABLE");
    bool load_debug_prop = false;
    if (force_debuggable_env && AvbHandle::IsDeviceUnlocked()) {
        load_debug_prop = "true"s == force_debuggable_env;
    }

    // Clean up our environment.
    unsetenv("INIT_AVB_VERSION");
    unsetenv("INIT_FORCE_DEBUGGABLE");

    // Umount the debug ramdisk so property service doesn't read .prop files from there, when it
    // is not meant to.
    if (!load_debug_prop) {
        UmountDebugRamdisk();
    }

    PropertyInit();

    // Umount the debug ramdisk after property service has read the .prop files when it means to.
    if (load_debug_prop) {
        UmountDebugRamdisk();
    }

    // Now set up SELinux for second stage.
    SelinuxSetupKernelLogging();
    SelabelInitialize();
@@ -746,16 +667,22 @@ int SecondStageMain(int argc, char** argv) {

    InstallSignalFdHandler(&epoll);

    property_load_boot_defaults(load_debug_prop);
    UmountDebugRamdisk();
    fs_mgr_vendor_overlay_mount_all();
    export_oem_lock_status();

    StartPropertyService(&property_fd);
    if (auto result = epoll.RegisterHandler(property_fd, HandlePropertyFd); !result) {
        LOG(FATAL) << "Could not register epoll handler for property fd: " << result.error();
    }

    // Make the time that init stages started available for bootstat to log.
    RecordStageBoottimes(start_time);

    // Set libavb version for Framework-only OTA match in Treble build.
    if (const char* avb_version = getenv("INIT_AVB_VERSION"); avb_version != nullptr) {
        SetProperty("ro.boot.avb_version", avb_version);
    }
    unsetenv("INIT_AVB_VERSION");

    fs_mgr_vendor_overlay_mount_all();
    export_oem_lock_status();
    MountHandler mount_handler(&epoll);
    set_usb_controller();

@@ -779,9 +706,9 @@ int SecondStageMain(int argc, char** argv) {

    // Make the GSI status available before scripts start running.
    if (android::gsi::IsGsiRunning()) {
        property_set("ro.gsid.image_running", "1");
        SetProperty("ro.gsid.image_running", "1");
    } else {
        property_set("ro.gsid.image_running", "0");
        SetProperty("ro.gsid.image_running", "0");
    }

    am.QueueBuiltinAction(SetupCgroupsAction, "SetupCgroups");
+1 −2
Original line number Diff line number Diff line
@@ -38,7 +38,6 @@
#include <libdm/dm.h>

#include "epoll.h"
#include "property_service.h"

namespace android {
namespace init {
@@ -96,7 +95,7 @@ void SetMountProperty(const MountHandlerEntry& entry, bool add) {
    // handling, except for clearing non-existent or already clear property.
    // Goal is reduction of empty properties and associated triggers.
    if (value.empty() && android::base::GetProperty(mount_prop, "").empty()) return;
    property_set(mount_prop, value);
    android::base::SetProperty(mount_prop, value);
}

}  // namespace
+108 −41
Original line number Diff line number Diff line
@@ -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
Loading