diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp index 84981bfae..5e0bfe48b 100644 --- a/fs_mgr/fs_mgr.cpp +++ b/fs_mgr/fs_mgr.cpp @@ -847,7 +847,9 @@ int fs_mgr_mount_all(struct fstab *fstab, int mount_mode) } } else if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) && is_device_secure()) { int rc = fs_mgr_setup_verity(&fstab->recs[i], true); - if (__android_log_is_debuggable() && rc == FS_MGR_SETUP_VERITY_DISABLED) { + if (__android_log_is_debuggable() && + (rc == FS_MGR_SETUP_VERITY_DISABLED || + rc == FS_MGR_SETUP_VERITY_SKIPPED)) { LINFO << "Verity disabled"; } else if (rc != FS_MGR_SETUP_VERITY_SUCCESS) { LERROR << "Could not set up verified partition, skipping!"; @@ -1061,7 +1063,9 @@ int fs_mgr_do_mount(struct fstab *fstab, const char *n_name, char *n_blk_device, } } else if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) && is_device_secure()) { int rc = fs_mgr_setup_verity(&fstab->recs[i], true); - if (__android_log_is_debuggable() && rc == FS_MGR_SETUP_VERITY_DISABLED) { + if (__android_log_is_debuggable() && + (rc == FS_MGR_SETUP_VERITY_DISABLED || + rc == FS_MGR_SETUP_VERITY_SKIPPED)) { LINFO << "Verity disabled"; } else if (rc != FS_MGR_SETUP_VERITY_SUCCESS) { LERROR << "Could not set up verified partition, skipping!"; diff --git a/fs_mgr/fs_mgr_verity.cpp b/fs_mgr/fs_mgr_verity.cpp index 0177fdf08..1d832b392 100644 --- a/fs_mgr/fs_mgr_verity.cpp +++ b/fs_mgr/fs_mgr_verity.cpp @@ -766,7 +766,7 @@ int fs_mgr_setup_verity(struct fstab_rec *fstab, bool wait_for_verity_dev) // setup is needed at all. if (!is_device_secure()) { LINFO << "Verity setup skipped for " << mount_point; - return FS_MGR_SETUP_VERITY_SUCCESS; + return FS_MGR_SETUP_VERITY_SKIPPED; } if (fec_open(&f, fstab->blk_device, O_RDONLY, FEC_VERITY_DISABLE, diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h index ae8018a0b..904adb0f9 100644 --- a/fs_mgr/include/fs_mgr.h +++ b/fs_mgr/include/fs_mgr.h @@ -143,6 +143,7 @@ int fs_mgr_swapon_all(struct fstab *fstab); int fs_mgr_do_format(struct fstab_rec *fstab, bool reserve_footer); +#define FS_MGR_SETUP_VERITY_SKIPPED (-3) #define FS_MGR_SETUP_VERITY_DISABLED (-2) #define FS_MGR_SETUP_VERITY_FAIL (-1) #define FS_MGR_SETUP_VERITY_SUCCESS 0 diff --git a/init/devices.cpp b/init/devices.cpp index c52d8f860..2943fb732 100644 --- a/init/devices.cpp +++ b/init/devices.cpp @@ -147,21 +147,34 @@ void SysfsPermissions::SetPermissions(const std::string& path) const { } } -// Given a path that may start with a platform device, find the length of the -// platform device prefix. If it doesn't start with a platform device, return false -bool PlatformDeviceList::Find(const std::string& path, std::string* out_path) const { - out_path->clear(); - // platform_devices is searched backwards, since parents are added before their children, - // and we want to match as deep of a child as we can. - for (auto it = platform_devices_.crbegin(); it != platform_devices_.crend(); ++it) { - auto platform_device_path_length = it->length(); - if (platform_device_path_length < path.length() && - path[platform_device_path_length] == '/' && - android::base::StartsWith(path, it->c_str())) { - *out_path = *it; +// Given a path that may start with a platform device, find the parent platform device by finding a +// parent directory with a 'subsystem' symlink that points to the platform bus. +// If it doesn't start with a platform device, return false +bool DeviceHandler::FindPlatformDevice(std::string path, std::string* platform_device_path) const { + platform_device_path->clear(); + + // Uevents don't contain the mount point, so we need to add it here. + path.insert(0, sysfs_mount_point_); + + std::string directory = android::base::Dirname(path); + + while (directory != "/" && directory != ".") { + std::string subsystem_link_path; + if (android::base::Realpath(directory + "/subsystem", &subsystem_link_path) && + subsystem_link_path == sysfs_mount_point_ + "/bus/platform") { + // We need to remove the mount point that we added above before returning. + directory.erase(0, sysfs_mount_point_.size()); + *platform_device_path = directory; return true; } + + auto last_slash = path.rfind('/'); + if (last_slash == std::string::npos) return false; + + path.erase(last_slash); + directory = android::base::Dirname(path); } + return false; } @@ -258,7 +271,7 @@ out: std::vector DeviceHandler::GetCharacterDeviceSymlinks(const Uevent& uevent) const { std::string parent_device; - if (!platform_devices_.Find(uevent.path, &parent_device)) return {}; + if (!FindPlatformDevice(uevent.path, &parent_device)) return {}; // skip path to the parent driver std::string path = uevent.path.substr(parent_device.length()); @@ -316,7 +329,7 @@ std::vector DeviceHandler::GetBlockDeviceSymlinks(const Uevent& uev std::string device; std::string type; - if (platform_devices_.Find(uevent.path, &device)) { + if (FindPlatformDevice(uevent.path, &device)) { // Skip /devices/platform or /devices/ if present static const std::string devices_platform_prefix = "/devices/platform/"; static const std::string devices_prefix = "/devices/"; @@ -388,14 +401,6 @@ void DeviceHandler::HandleDevice(const std::string& action, const std::string& d } } -void DeviceHandler::HandlePlatformDeviceEvent(const Uevent& uevent) { - if (uevent.action == "add") { - platform_devices_.Add(uevent.path); - } else if (uevent.action == "remove") { - platform_devices_.Remove(uevent.path); - } -} - void DeviceHandler::HandleBlockDeviceEvent(const Uevent& uevent) const { // if it's not a /dev device, nothing to do if (uevent.major < 0 || uevent.minor < 0) return; @@ -458,8 +463,6 @@ void DeviceHandler::HandleDeviceEvent(const Uevent& uevent) { if (uevent.subsystem == "block") { HandleBlockDeviceEvent(uevent); - } else if (uevent.subsystem == "platform") { - HandlePlatformDeviceEvent(uevent); } else { HandleGenericDeviceEvent(uevent); } @@ -472,7 +475,8 @@ DeviceHandler::DeviceHandler(std::vector dev_permissions, sysfs_permissions_(std::move(sysfs_permissions)), subsystems_(std::move(subsystems)), sehandle_(selinux_android_file_context_handle()), - skip_restorecon_(skip_restorecon) {} + skip_restorecon_(skip_restorecon), + sysfs_mount_point_("/sys") {} DeviceHandler::DeviceHandler() : DeviceHandler(std::vector{}, std::vector{}, diff --git a/init/devices.h b/init/devices.h index 09a0ce3ee..362c38cb8 100644 --- a/init/devices.h +++ b/init/devices.h @@ -93,20 +93,6 @@ class Subsystem { DevnameSource devname_source_; }; -class PlatformDeviceList { - public: - void Add(const std::string& path) { platform_devices_.emplace_back(path); } - void Remove(const std::string& path) { - auto it = std::find(platform_devices_.begin(), platform_devices_.end(), path); - if (it != platform_devices_.end()) platform_devices_.erase(it); - } - bool Find(const std::string& path, std::string* out_path) const; - auto size() const { return platform_devices_.size(); } - - private: - std::vector platform_devices_; -}; - class DeviceHandler { public: friend class DeviceHandlerTester; @@ -119,16 +105,11 @@ class DeviceHandler { void HandleDeviceEvent(const Uevent& uevent); - void FixupSysPermissions(const std::string& upath, const std::string& subsystem) const; - - void HandlePlatformDeviceEvent(const Uevent& uevent); - void HandleBlockDeviceEvent(const Uevent& uevent) const; - void HandleGenericDeviceEvent(const Uevent& uevent) const; - std::vector GetBlockDeviceSymlinks(const Uevent& uevent) const; void set_skip_restorecon(bool value) { skip_restorecon_ = value; } private: + bool FindPlatformDevice(std::string path, std::string* platform_device_path) const; std::tuple GetDevicePermissions( const std::string& path, const std::vector& links) const; void MakeDevice(const std::string& path, int block, int major, int minor, @@ -136,13 +117,17 @@ class DeviceHandler { std::vector GetCharacterDeviceSymlinks(const Uevent& uevent) const; void HandleDevice(const std::string& action, const std::string& devpath, int block, int major, int minor, const std::vector& links) const; + void FixupSysPermissions(const std::string& upath, const std::string& subsystem) const; + + void HandleBlockDeviceEvent(const Uevent& uevent) const; + void HandleGenericDeviceEvent(const Uevent& uevent) const; std::vector dev_permissions_; std::vector sysfs_permissions_; std::vector subsystems_; - PlatformDeviceList platform_devices_; selabel_handle* sehandle_; bool skip_restorecon_; + std::string sysfs_mount_point_; }; // Exposed for testing diff --git a/init/devices_test.cpp b/init/devices_test.cpp index 41b101b22..e1e4e49f6 100644 --- a/init/devices_test.cpp +++ b/init/devices_test.cpp @@ -16,33 +16,29 @@ #include "devices.h" -#include -#include - #include +#include #include +#include "util.h" + +using namespace std::string_literals; + class DeviceHandlerTester { public: - void AddPlatformDevice(const std::string& path) { - Uevent uevent = { - .action = "add", .subsystem = "platform", .path = path, - }; - device_handler_.HandlePlatformDeviceEvent(uevent); - } - - void RemovePlatformDevice(const std::string& path) { - Uevent uevent = { - .action = "remove", .subsystem = "platform", .path = path, - }; - device_handler_.HandlePlatformDeviceEvent(uevent); - } - - void TestGetSymlinks(const std::string& platform_device_name, const Uevent& uevent, + void TestGetSymlinks(const std::string& platform_device, const Uevent& uevent, const std::vector expected_links, bool block) { - AddPlatformDevice(platform_device_name); - auto platform_device_remover = android::base::make_scope_guard( - [this, &platform_device_name]() { RemovePlatformDevice(platform_device_name); }); + TemporaryDir fake_sys_root; + device_handler_.sysfs_mount_point_ = fake_sys_root.path; + + std::string platform_device_dir = fake_sys_root.path + platform_device; + mkdir_recursive(platform_device_dir, 0777, nullptr); + + std::string platform_bus = fake_sys_root.path + "/bus/platform"s; + mkdir_recursive(platform_bus, 0777, nullptr); + symlink(platform_bus.c_str(), (platform_device_dir + "/subsystem").c_str()); + + mkdir_recursive(android::base::Dirname(fake_sys_root.path + uevent.path), 0777, nullptr); std::vector result; if (block) { @@ -65,30 +61,6 @@ class DeviceHandlerTester { DeviceHandler device_handler_; }; -TEST(device_handler, PlatformDeviceList) { - PlatformDeviceList platform_device_list; - - platform_device_list.Add("/devices/platform/some_device_name"); - platform_device_list.Add("/devices/platform/some_device_name/longer"); - platform_device_list.Add("/devices/platform/other_device_name"); - EXPECT_EQ(3U, platform_device_list.size()); - - std::string out_path; - EXPECT_FALSE(platform_device_list.Find("/devices/platform/not_found", &out_path)); - EXPECT_EQ("", out_path); - - EXPECT_FALSE(platform_device_list.Find("/devices/platform/some_device_name_with_same_prefix", - &out_path)); - - EXPECT_TRUE(platform_device_list.Find("/devices/platform/some_device_name/longer/longer_child", - &out_path)); - EXPECT_EQ("/devices/platform/some_device_name/longer", out_path); - - EXPECT_TRUE( - platform_device_list.Find("/devices/platform/some_device_name/other_child", &out_path)); - EXPECT_EQ("/devices/platform/some_device_name", out_path); -} - TEST(device_handler, get_character_device_symlinks_success) { const char* platform_device = "/devices/platform/some_device_name"; Uevent uevent = { diff --git a/init/init_first_stage.cpp b/init/init_first_stage.cpp index 0f2b1f3d4..4faca8965 100644 --- a/init/init_first_stage.cpp +++ b/init/init_first_stage.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -35,6 +36,8 @@ #include "uevent_listener.h" #include "util.h" +using namespace std::chrono_literals; + // Class Declarations // ------------------ class FirstStageMount { @@ -49,11 +52,11 @@ class FirstStageMount { bool InitDevices(); protected: - void InitRequiredDevices(); - void InitVerityDevice(const std::string& verity_device); + bool InitRequiredDevices(); + bool InitVerityDevice(const std::string& verity_device); bool MountPartitions(); - virtual RegenerationAction UeventCallback(const Uevent& uevent); + virtual ListenerAction UeventCallback(const Uevent& uevent); // Pure virtual functions. virtual bool GetRequiredDevices() = 0; @@ -86,7 +89,7 @@ class FirstStageMountVBootV2 : public FirstStageMount { ~FirstStageMountVBootV2() override = default; protected: - RegenerationAction UeventCallback(const Uevent& uevent) override; + ListenerAction UeventCallback(const Uevent& uevent) override; bool GetRequiredDevices() override; bool SetUpDmVerity(fstab_rec* fstab_rec) override; bool InitAvbHandle(); @@ -141,55 +144,60 @@ bool FirstStageMount::DoFirstStageMount() { } bool FirstStageMount::InitDevices() { - if (!GetRequiredDevices()) return false; - - InitRequiredDevices(); - - // InitRequiredDevices() will remove found partitions from required_devices_partition_names_. - // So if it isn't empty here, it means some partitions are not found. - if (!required_devices_partition_names_.empty()) { - LOG(ERROR) << __FUNCTION__ << "(): partition(s) not found: " - << android::base::Join(required_devices_partition_names_, ", "); - return false; - } else { - return true; - } + return GetRequiredDevices() && InitRequiredDevices(); } // Creates devices with uevent->partition_name matching one in the member variable // required_devices_partition_names_. Found partitions will then be removed from it // for the subsequent member function to check which devices are NOT created. -void FirstStageMount::InitRequiredDevices() { +bool FirstStageMount::InitRequiredDevices() { if (required_devices_partition_names_.empty()) { - return; + return true; } if (need_dm_verity_) { const std::string dm_path = "/devices/virtual/misc/device-mapper"; - uevent_listener_.RegenerateUeventsForPath("/sys" + dm_path, - [this, &dm_path](const Uevent& uevent) { - if (uevent.path == dm_path) { - device_handler_.HandleDeviceEvent(uevent); - return RegenerationAction::kStop; - } - return RegenerationAction::kContinue; - }); + bool found = false; + auto dm_callback = [this, &dm_path, &found](const Uevent& uevent) { + if (uevent.path == dm_path) { + device_handler_.HandleDeviceEvent(uevent); + found = true; + return ListenerAction::kStop; + } + return ListenerAction::kContinue; + }; + uevent_listener_.RegenerateUeventsForPath("/sys" + dm_path, dm_callback); + if (!found) { + uevent_listener_.Poll(dm_callback, 10s); + } + if (!found) { + LOG(ERROR) << "device-mapper device not found"; + return false; + } } - uevent_listener_.RegenerateUevents( - [this](const Uevent& uevent) { return UeventCallback(uevent); }); + auto uevent_callback = [this](const Uevent& uevent) { return UeventCallback(uevent); }; + uevent_listener_.RegenerateUevents(uevent_callback); + + // UeventCallback() will remove found partitions from required_devices_partition_names_. + // So if it isn't empty here, it means some partitions are not found. + if (!required_devices_partition_names_.empty()) { + uevent_listener_.Poll(uevent_callback, 10s); + } + + if (!required_devices_partition_names_.empty()) { + LOG(ERROR) << __PRETTY_FUNCTION__ << ": partition(s) not found: " + << android::base::Join(required_devices_partition_names_, ", "); + return false; + } + + return true; } -RegenerationAction FirstStageMount::UeventCallback(const Uevent& uevent) { - // We need platform devices to create symlinks. - if (uevent.subsystem == "platform") { - device_handler_.HandleDeviceEvent(uevent); - return RegenerationAction::kContinue; - } - +ListenerAction FirstStageMount::UeventCallback(const Uevent& uevent) { // Ignores everything that is not a block device. if (uevent.subsystem != "block") { - return RegenerationAction::kContinue; + return ListenerAction::kContinue; } if (!uevent.partition_name.empty()) { @@ -198,34 +206,46 @@ RegenerationAction FirstStageMount::UeventCallback(const Uevent& uevent) { // suffix when A/B is used. auto iter = required_devices_partition_names_.find(uevent.partition_name); if (iter != required_devices_partition_names_.end()) { - LOG(VERBOSE) << __FUNCTION__ << "(): found partition: " << *iter; + LOG(VERBOSE) << __PRETTY_FUNCTION__ << ": found partition: " << *iter; required_devices_partition_names_.erase(iter); device_handler_.HandleDeviceEvent(uevent); if (required_devices_partition_names_.empty()) { - return RegenerationAction::kStop; + return ListenerAction::kStop; } else { - return RegenerationAction::kContinue; + return ListenerAction::kContinue; } } } // Not found a partition or find an unneeded partition, continue to find others. - return RegenerationAction::kContinue; + return ListenerAction::kContinue; } // Creates "/dev/block/dm-XX" for dm-verity by running coldboot on /sys/block/dm-XX. -void FirstStageMount::InitVerityDevice(const std::string& verity_device) { +bool FirstStageMount::InitVerityDevice(const std::string& verity_device) { const std::string device_name(basename(verity_device.c_str())); const std::string syspath = "/sys/block/" + device_name; + bool found = false; - uevent_listener_.RegenerateUeventsForPath( - syspath, [&device_name, &verity_device, this](const Uevent& uevent) { - if (uevent.device_name == device_name) { - LOG(VERBOSE) << "Creating dm-verity device : " << verity_device; - device_handler_.HandleDeviceEvent(uevent); - return RegenerationAction::kStop; - } - return RegenerationAction::kContinue; - }); + auto verity_callback = [&device_name, &verity_device, this, &found](const Uevent& uevent) { + if (uevent.device_name == device_name) { + LOG(VERBOSE) << "Creating dm-verity device : " << verity_device; + device_handler_.HandleDeviceEvent(uevent); + found = true; + return ListenerAction::kStop; + } + return ListenerAction::kContinue; + }; + + uevent_listener_.RegenerateUeventsForPath(syspath, verity_callback); + if (!found) { + uevent_listener_.Poll(verity_callback, 10s); + } + if (!found) { + LOG(ERROR) << "dm-verity device not found"; + return false; + } + + return true; } bool FirstStageMount::MountPartitions() { @@ -286,13 +306,17 @@ bool FirstStageMountVBootV1::GetRequiredDevices() { bool FirstStageMountVBootV1::SetUpDmVerity(fstab_rec* fstab_rec) { if (fs_mgr_is_verified(fstab_rec)) { int ret = fs_mgr_setup_verity(fstab_rec, false /* wait_for_verity_dev */); - if (ret == FS_MGR_SETUP_VERITY_DISABLED) { - LOG(INFO) << "Verity disabled for '" << fstab_rec->mount_point << "'"; - } else if (ret == FS_MGR_SETUP_VERITY_SUCCESS) { + switch (ret) { + case FS_MGR_SETUP_VERITY_SKIPPED: + case FS_MGR_SETUP_VERITY_DISABLED: + LOG(INFO) << "Verity disabled/skipped for '" << fstab_rec->mount_point << "'"; + break; + case FS_MGR_SETUP_VERITY_SUCCESS: // The exact block device name (fstab_rec->blk_device) is changed to "/dev/block/dm-XX". // Needs to create it because ueventd isn't started in init first stage. - InitVerityDevice(fstab_rec->blk_device); - } else { + return InitVerityDevice(fstab_rec->blk_device); + break; + default: return false; } } @@ -351,7 +375,7 @@ bool FirstStageMountVBootV2::GetRequiredDevices() { return true; } -RegenerationAction FirstStageMountVBootV2::UeventCallback(const Uevent& uevent) { +ListenerAction FirstStageMountVBootV2::UeventCallback(const Uevent& uevent) { // Check if this uevent corresponds to one of the required partitions and store its symlinks if // so, in order to create FsManagerAvbHandle later. // Note that the parent callback removes partitions from the list of required partitions diff --git a/init/uevent_listener.cpp b/init/uevent_listener.cpp index 27c5d2374..c7489843e 100644 --- a/init/uevent_listener.cpp +++ b/init/uevent_listener.cpp @@ -121,8 +121,8 @@ bool UeventListener::ReadUevent(Uevent* uevent) const { // make sure we don't overrun the socket's buffer. // -RegenerationAction UeventListener::RegenerateUeventsForDir(DIR* d, - RegenerateCallback callback) const { +ListenerAction UeventListener::RegenerateUeventsForDir(DIR* d, + const ListenerCallback& callback) const { int dfd = dirfd(d); int fd = openat(dfd, "uevent", O_WRONLY); @@ -132,7 +132,7 @@ RegenerationAction UeventListener::RegenerateUeventsForDir(DIR* d, Uevent uevent; while (ReadUevent(&uevent)) { - if (callback(uevent) == RegenerationAction::kStop) return RegenerationAction::kStop; + if (callback(uevent) == ListenerAction::kStop) return ListenerAction::kStop; } } @@ -147,49 +147,67 @@ RegenerationAction UeventListener::RegenerateUeventsForDir(DIR* d, if (d2 == 0) { close(fd); } else { - if (RegenerateUeventsForDir(d2.get(), callback) == RegenerationAction::kStop) { - return RegenerationAction::kStop; + if (RegenerateUeventsForDir(d2.get(), callback) == ListenerAction::kStop) { + return ListenerAction::kStop; } } } // default is always to continue looking for uevents - return RegenerationAction::kContinue; + return ListenerAction::kContinue; } -RegenerationAction UeventListener::RegenerateUeventsForPath(const std::string& path, - RegenerateCallback callback) const { +ListenerAction UeventListener::RegenerateUeventsForPath(const std::string& path, + const ListenerCallback& callback) const { std::unique_ptr d(opendir(path.c_str()), closedir); - if (!d) return RegenerationAction::kContinue; + if (!d) return ListenerAction::kContinue; return RegenerateUeventsForDir(d.get(), callback); } static const char* kRegenerationPaths[] = {"/sys/class", "/sys/block", "/sys/devices"}; -void UeventListener::RegenerateUevents(RegenerateCallback callback) const { +void UeventListener::RegenerateUevents(const ListenerCallback& callback) const { for (const auto path : kRegenerationPaths) { - if (RegenerateUeventsForPath(path, callback) == RegenerationAction::kStop) return; + if (RegenerateUeventsForPath(path, callback) == ListenerAction::kStop) return; } } -void UeventListener::DoPolling(PollCallback callback) const { +void UeventListener::Poll(const ListenerCallback& callback, + const std::optional relative_timeout) const { + using namespace std::chrono; + pollfd ufd; ufd.events = POLLIN; ufd.fd = device_fd_; + auto start_time = steady_clock::now(); + while (true) { ufd.revents = 0; - int nr = poll(&ufd, 1, -1); - if (nr <= 0) { + + int timeout_ms = -1; + if (relative_timeout) { + auto now = steady_clock::now(); + auto time_elapsed = duration_cast(now - start_time); + if (time_elapsed > *relative_timeout) return; + + auto remaining_timeout = *relative_timeout - time_elapsed; + timeout_ms = remaining_timeout.count(); + } + + int nr = poll(&ufd, 1, timeout_ms); + if (nr == 0) return; + if (nr < 0) { + PLOG(ERROR) << "poll() of uevent socket failed, continuing"; continue; } if (ufd.revents & POLLIN) { - // We're non-blocking, so if we receive a poll event keep processing until there + // We're non-blocking, so if we receive a poll event keep processing until // we have exhausted all uevent messages. Uevent uevent; while (ReadUevent(&uevent)) { - callback(uevent); + if (callback(uevent) == ListenerAction::kStop) return; } } } diff --git a/init/uevent_listener.h b/init/uevent_listener.h index ba31aaa71..0dae102ed 100644 --- a/init/uevent_listener.h +++ b/init/uevent_listener.h @@ -19,7 +19,9 @@ #include +#include #include +#include #include @@ -27,26 +29,26 @@ #define UEVENT_MSG_LEN 2048 -enum class RegenerationAction { +enum class ListenerAction { kStop = 0, // Stop regenerating uevents as we've handled the one(s) we're interested in. kContinue, // Continue regenerating uevents as we haven't seen the one(s) we're interested in. }; -using RegenerateCallback = std::function; -using PollCallback = std::function; +using ListenerCallback = std::function; class UeventListener { public: UeventListener(); - void RegenerateUevents(RegenerateCallback callback) const; - RegenerationAction RegenerateUeventsForPath(const std::string& path, - RegenerateCallback callback) const; - void DoPolling(PollCallback callback) const; + void RegenerateUevents(const ListenerCallback& callback) const; + ListenerAction RegenerateUeventsForPath(const std::string& path, + const ListenerCallback& callback) const; + void Poll(const ListenerCallback& callback, + const std::optional relative_timeout = {}) const; private: bool ReadUevent(Uevent* uevent) const; - RegenerationAction RegenerateUeventsForDir(DIR* d, RegenerateCallback callback) const; + ListenerAction RegenerateUeventsForDir(DIR* d, const ListenerCallback& callback) const; android::base::unique_fd device_fd_; }; diff --git a/init/ueventd.cpp b/init/ueventd.cpp index d12164719..4982b7774 100644 --- a/init/ueventd.cpp +++ b/init/ueventd.cpp @@ -128,15 +128,7 @@ class ColdBoot { void ColdBoot::UeventHandlerMain(unsigned int process_num, unsigned int total_processes) { for (unsigned int i = process_num; i < uevent_queue_.size(); i += total_processes) { auto& uevent = uevent_queue_[i]; - if (uevent.action == "add" || uevent.action == "change" || uevent.action == "online") { - device_handler_.FixupSysPermissions(uevent.path, uevent.subsystem); - } - - if (uevent.subsystem == "block") { - device_handler_.HandleBlockDeviceEvent(uevent); - } else { - device_handler_.HandleGenericDeviceEvent(uevent); - } + device_handler_.HandleDeviceEvent(uevent); } _exit(EXIT_SUCCESS); } @@ -145,16 +137,8 @@ void ColdBoot::RegenerateUevents() { uevent_listener_.RegenerateUevents([this](const Uevent& uevent) { HandleFirmwareEvent(uevent); - // This is the one mutable part of DeviceHandler, in which platform devices are - // added to a vector for later reference. Since there is no communication after - // fork()'ing subprocess handlers, all platform devices must be in the vector before - // we fork, and therefore they must be handled in this loop. - if (uevent.subsystem == "platform") { - device_handler_.HandlePlatformDeviceEvent(uevent); - } - uevent_queue_.emplace_back(std::move(uevent)); - return RegenerationAction::kContinue; + return ListenerAction::kContinue; }); } @@ -282,9 +266,10 @@ int ueventd_main(int argc, char** argv) { cold_boot.Run(); } - uevent_listener.DoPolling([&device_handler](const Uevent& uevent) { + uevent_listener.Poll([&device_handler](const Uevent& uevent) { HandleFirmwareEvent(uevent); device_handler.HandleDeviceEvent(uevent); + return ListenerAction::kContinue; }); return 0;