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

Commit 8b7d0aa8 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "ueventd: add support for driver section in ueventd.rc" into main

parents 932497ea d17d5c58
Loading
Loading
Loading
Loading
+10 −6
Original line number Diff line number Diff line
@@ -76,17 +76,17 @@ For example
When `/dev/null` is created, its mode will be set to `0666`, its user to `root` and its group to
`root`.

The path can be modified using a ueventd.rc script and a `subsystem` section. There are three to set
for a subsystem: the subsystem name, which device name to use, and which directory to place the
device in. The section takes the below format of
The path can be modified using a ueventd.rc script and a `subsystem` and/or `driver` section.
There are three options to set for a subsystem or driver: the name, which device name to use,
and which directory to place the device in. The section takes the below format of

    subsystem <subsystem_name>
      devname uevent_devname|uevent_devpath
      [dirname <directory>]

`subsystem_name` is used to match uevent `SUBSYSTEM` value
`subsystem_name` is used to match the uevent `SUBSYSTEM` value.

`devname` takes one of three options
`devname` takes one of three options:
  1. `uevent_devname` specifies that the name of the node will be the uevent `DEVNAME`
  2. `uevent_devpath` specifies that the name of the node will be basename uevent `DEVPATH`
  3. `sys_name` specifies that the name of the node will be the contents of `/sys/DEVPATH/name`
@@ -99,9 +99,13 @@ For example
    subsystem sound
      devname uevent_devpath
      dirname /dev/snd
Indicates that all uevents with `SUBSYSTEM=sound` will create nodes as `/dev/snd/<basename uevent
indicates that all uevents with `SUBSYSTEM=sound` will create nodes as `/dev/snd/<basename uevent
DEVPATH>`.

The `driver` section has the exact same structure as a `subsystem` section, but
will instead match the `DRIVER` value in a `bind`/`unbind` uevent. However, the
`driver` section will be ignored for block devices.

## /sys
----
Ueventd by default takes no action for `/sys`, however it can be instructed to set permissions for
+2 −1
Original line number Diff line number Diff line
@@ -33,7 +33,8 @@ BlockDevInitializer::BlockDevInitializer() : uevent_listener_(16 * 1024 * 1024)
    auto boot_devices = android::fs_mgr::GetBootDevices();
    device_handler_ = std::make_unique<DeviceHandler>(
            std::vector<Permissions>{}, std::vector<SysfsPermissions>{}, std::vector<Subsystem>{},
            std::move(boot_devices), android::fs_mgr::GetBootPartUuid(), false);
            std::vector<Subsystem>{}, std::move(boot_devices), android::fs_mgr::GetBootPartUuid(),
            false);
}

// If boot_part_uuid is specified, use it to set boot_devices
+69 −3
Original line number Diff line number Diff line
@@ -345,6 +345,26 @@ bool DeviceHandler::FindScsiDevice(const std::string& path, std::string* scsi_de
    return FindSubsystemDevice(path, scsi_device_path, subsystem_paths);
}

void DeviceHandler::TrackDeviceUevent(const Uevent& uevent) {
    // No need to track any events if we won't bother handling any bind events
    // later.
    if (drivers_.size() == 0) return;

    // Only track add, and not for block devices. We don't track remove because
    // unbind events may arrive after remove events, so unbind will be the
    // trigger to untrack those events.
    if ((uevent.action != "add") || uevent.subsystem == "block" ||
        (uevent.major < 0 || uevent.minor < 0)) {
        return;
    }

    std::string path = sysfs_mount_point_ + uevent.path + "/device";
    std::string device;
    if (!Realpath(path, &device)) return;

    tracked_uevents_.emplace_back(uevent, device);
}

void DeviceHandler::FixupSysPermissions(const std::string& upath,
                                        const std::string& subsystem) const {
    // upaths omit the "/sys" that paths in this list
@@ -664,12 +684,53 @@ bool DeviceHandler::CheckUeventForBootPartUuid(const Uevent& uevent) {
    return true;
}

void DeviceHandler::HandleBindInternal(std::string driver_name, std::string action,
                                       const Uevent& uevent) {
    if (uevent.subsystem == "block") {
        LOG(FATAL) << "Tried to handle bind event for block device";
    }

    // Get tracked uevents for all devices that have this uevent's path as
    // their canonical device path. Then handle those again if their driver
    // is one of the ones we're interested in.
    const auto driver = std::find(drivers_.cbegin(), drivers_.cend(), driver_name);
    if (driver == drivers_.cend()) return;

    std::string bind_path = sysfs_mount_point_ + uevent.path;
    for (const TrackedUevent& tracked : tracked_uevents_) {
        if (tracked.canonical_device_path != bind_path) continue;

        LOG(VERBOSE) << "Propagating " << uevent.action << " as " << action << " for "
                     << uevent.path;

        std::string devpath = driver->ParseDevPath(tracked.uevent);
        mkdir_recursive(Dirname(devpath), 0755);
        HandleDevice(action, devpath, false, tracked.uevent.major, tracked.uevent.minor,
                     std::vector<std::string>{});
    }
}

void DeviceHandler::HandleUevent(const Uevent& uevent) {
    if (uevent.action == "add" || uevent.action == "change" || uevent.action == "bind" ||
        uevent.action == "online") {
        FixupSysPermissions(uevent.path, uevent.subsystem);
    }

    if (uevent.action == "bind") {
        bound_drivers_[uevent.path] = uevent.driver;
        HandleBindInternal(uevent.driver, "add", uevent);
        return;
    } else if (uevent.action == "unbind") {
        if (bound_drivers_.count(uevent.path) == 0) return;
        HandleBindInternal(bound_drivers_[uevent.path], "remove", uevent);

        std::string sys_path = sysfs_mount_point_ + uevent.path;
        std::erase_if(tracked_uevents_, [&sys_path](const TrackedUevent& tracked) {
            return sys_path == tracked.canonical_device_path;
        });
        return;
    }

    // if it's not a /dev device, nothing to do
    if (uevent.major < 0 || uevent.minor < 0) return;

@@ -677,6 +738,8 @@ void DeviceHandler::HandleUevent(const Uevent& uevent) {
    std::vector<std::string> links;
    bool block = false;

    TrackDeviceUevent(uevent);

    if (uevent.subsystem == "block") {
        block = true;
        devpath = "/dev/block/" + Basename(uevent.path);
@@ -725,10 +788,12 @@ void DeviceHandler::ColdbootDone() {

DeviceHandler::DeviceHandler(std::vector<Permissions> dev_permissions,
                             std::vector<SysfsPermissions> sysfs_permissions,
                             std::vector<Subsystem> subsystems, std::set<std::string> boot_devices,
                             std::string boot_part_uuid, bool skip_restorecon)
                             std::vector<Subsystem> drivers, std::vector<Subsystem> subsystems,
                             std::set<std::string> boot_devices, std::string boot_part_uuid,
                             bool skip_restorecon)
    : dev_permissions_(std::move(dev_permissions)),
      sysfs_permissions_(std::move(sysfs_permissions)),
      drivers_(std::move(drivers)),
      subsystems_(std::move(subsystems)),
      boot_devices_(std::move(boot_devices)),
      boot_part_uuid_(boot_part_uuid),
@@ -744,7 +809,8 @@ DeviceHandler::DeviceHandler(std::vector<Permissions> dev_permissions,

DeviceHandler::DeviceHandler()
    : DeviceHandler(std::vector<Permissions>{}, std::vector<SysfsPermissions>{},
                    std::vector<Subsystem>{}, std::set<std::string>{}, "", false) {}
                    std::vector<Subsystem>{}, std::vector<Subsystem>{}, std::set<std::string>{}, "",
                    false) {}

}  // namespace init
}  // namespace android
+14 −1
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#include <sys/types.h>

#include <algorithm>
#include <map>
#include <set>
#include <string>
#include <vector>
@@ -128,7 +129,7 @@ class DeviceHandler : public UeventHandler {

    DeviceHandler();
    DeviceHandler(std::vector<Permissions> dev_permissions,
                  std::vector<SysfsPermissions> sysfs_permissions,
                  std::vector<SysfsPermissions> sysfs_permissions, std::vector<Subsystem> drivers,
                  std::vector<Subsystem> subsystems, std::set<std::string> boot_devices,
                  std::string boot_part_uuid, bool skip_restorecon);
    virtual ~DeviceHandler() = default;
@@ -145,6 +146,11 @@ class DeviceHandler : public UeventHandler {
    bool IsBootDevice(const Uevent& uevent) const;

  private:
    struct TrackedUevent {
        Uevent uevent;
        std::string canonical_device_path;
    };

    void ColdbootDone() override;
    BlockDeviceInfo GetBlockDeviceInfo(const std::string& uevent_path) const;
    bool FindSubsystemDevice(std::string path, std::string* device_path,
@@ -163,14 +169,21 @@ class DeviceHandler : public UeventHandler {
    void FixupSysPermissions(const std::string& upath, const std::string& subsystem) const;
    void HandleAshmemUevent(const Uevent& uevent);

    void TrackDeviceUevent(const Uevent& uevent);
    void HandleBindInternal(std::string driver_name, std::string action, const Uevent& uevent);

    std::vector<Permissions> dev_permissions_;
    std::vector<SysfsPermissions> sysfs_permissions_;
    std::vector<Subsystem> drivers_;
    std::vector<Subsystem> subsystems_;
    std::set<std::string> boot_devices_;
    std::string boot_part_uuid_;
    bool found_boot_part_uuid_;
    bool skip_restorecon_;
    std::string sysfs_mount_point_;

    std::vector<TrackedUevent> tracked_uevents_;
    std::map<std::string, std::string> bound_drivers_;
};

// Exposed for testing
+1 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ struct Uevent {
    std::string action;
    std::string path;
    std::string subsystem;
    std::string driver;
    std::string firmware;
    std::string partition_name;
    std::string partition_uuid;
Loading