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

Commit a95f900d authored by Tom Cherry's avatar Tom Cherry Committed by Automerger Merge Worker
Browse files

Merge "ueventd: add no_fnm_pathname option" am: 6cf36955

Original change: https://android-review.googlesource.com/c/platform/system/core/+/1518705

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: I8bf82b3439e15e282bef89a9ecc40663796006f6
parents 877e2374 6cf36955
Loading
Loading
Loading
Loading
+11 −3
Original line number Diff line number Diff line
@@ -42,7 +42,7 @@ for the node path:
The permissions can be modified using a ueventd.rc script and a line that beings with `/dev`. These
lines take the format of

    devname mode uid gid
    devname mode uid gid [options]
For example

    /dev/null 0666 root root
@@ -80,7 +80,7 @@ Ueventd by default takes no action for `/sys`, however it can be instructed to s
certain files in `/sys` when matching uevents are generated. This is done using a ueventd.rc script
and a line that begins with `/sys`. These lines take the format of

    nodename attr mode uid gid
    nodename attr mode uid gid [options]
For example

    /sys/devices/system/cpu/cpu* cpufreq/scaling_max_freq 0664 system system
@@ -88,7 +88,15 @@ When a uevent that matches the pattern `/sys/devices/system/cpu/cpu*` is sent, t
attribute, `cpufreq/scaling_max_freq`, will have its mode set to `0664`, its user to to `system` and
its group set to `system`.

Note that `*` matches as a wildcard and can be used anywhere in a path.
## Path matching
----------------
The path for a `/dev` or `/sys` entry can contain a `*` anywhere in the path.
1. If the only `*` appears at the end of the string or if the _options_ parameter is set to
`no_fnm_pathname`, ueventd matches the entry by `fnmatch(entry_path, incoming_path, 0)`
2. Otherwise, ueventd matches the entry by `fnmatch(entry_path, incoming_path, FNM_PATHNAME)`

See the [man page for fnmatch](https://www.man7.org/linux/man-pages/man3/fnmatch.3.html) for more
details.

## Firmware loading
----------------
+11 −4
Original line number Diff line number Diff line
@@ -124,8 +124,15 @@ static bool FindDmDevice(const std::string& path, std::string* name, std::string
    return true;
}

Permissions::Permissions(const std::string& name, mode_t perm, uid_t uid, gid_t gid)
    : name_(name), perm_(perm), uid_(uid), gid_(gid), prefix_(false), wildcard_(false) {
Permissions::Permissions(const std::string& name, mode_t perm, uid_t uid, gid_t gid,
                         bool no_fnm_pathname)
    : name_(name),
      perm_(perm),
      uid_(uid),
      gid_(gid),
      prefix_(false),
      wildcard_(false),
      no_fnm_pathname_(no_fnm_pathname) {
    // Set 'prefix_' or 'wildcard_' based on the below cases:
    //
    // 1) No '*' in 'name' -> Neither are set and Match() checks a given path for strict
@@ -136,7 +143,6 @@ Permissions::Permissions(const std::string& name, mode_t perm, uid_t uid, gid_t
    //
    // 3) '*' appears elsewhere -> 'wildcard_' is set to true and Match() uses fnmatch()
    //    with FNM_PATHNAME to compare 'name' to a given path.

    auto wildcard_position = name_.find('*');
    if (wildcard_position != std::string::npos) {
        if (wildcard_position == name_.length() - 1) {
@@ -150,7 +156,8 @@ Permissions::Permissions(const std::string& name, mode_t perm, uid_t uid, gid_t

bool Permissions::Match(const std::string& path) const {
    if (prefix_) return StartsWith(path, name_);
    if (wildcard_) return fnmatch(name_.c_str(), path.c_str(), FNM_PATHNAME) == 0;
    if (wildcard_)
        return fnmatch(name_.c_str(), path.c_str(), no_fnm_pathname_ ? 0 : FNM_PATHNAME) == 0;
    return path == name_;
}

+4 −3
Original line number Diff line number Diff line
@@ -38,7 +38,7 @@ class Permissions {
  public:
    friend void TestPermissions(const Permissions& expected, const Permissions& test);

    Permissions(const std::string& name, mode_t perm, uid_t uid, gid_t gid);
    Permissions(const std::string& name, mode_t perm, uid_t uid, gid_t gid, bool no_fnm_pathname);

    bool Match(const std::string& path) const;

@@ -56,6 +56,7 @@ class Permissions {
    gid_t gid_;
    bool prefix_;
    bool wildcard_;
    bool no_fnm_pathname_;
};

class SysfsPermissions : public Permissions {
@@ -63,8 +64,8 @@ class SysfsPermissions : public Permissions {
    friend void TestSysfsPermissions(const SysfsPermissions& expected, const SysfsPermissions& test);

    SysfsPermissions(const std::string& name, const std::string& attribute, mode_t perm, uid_t uid,
                     gid_t gid)
        : Permissions(name, perm, uid, gid), attribute_(attribute) {}
                     gid_t gid, bool no_fnm_pathname)
        : Permissions(name, perm, uid, gid, no_fnm_pathname), attribute_(attribute) {}

    bool MatchWithSubsystem(const std::string& path, const std::string& subsystem) const;
    void SetPermissions(const std::string& path) const;
+26 −7
Original line number Diff line number Diff line
@@ -221,7 +221,7 @@ TEST(device_handler, sanitize_onebad) {
TEST(device_handler, DevPermissionsMatchNormal) {
    // Basic from ueventd.rc
    // /dev/null                 0666   root       root
    Permissions permissions("/dev/null", 0666, 0, 0);
    Permissions permissions("/dev/null", 0666, 0, 0, false);
    EXPECT_TRUE(permissions.Match("/dev/null"));
    EXPECT_FALSE(permissions.Match("/dev/nullsuffix"));
    EXPECT_FALSE(permissions.Match("/dev/nul"));
@@ -233,7 +233,7 @@ TEST(device_handler, DevPermissionsMatchNormal) {
TEST(device_handler, DevPermissionsMatchPrefix) {
    // Prefix from ueventd.rc
    // /dev/dri/*                0666   root       graphics
    Permissions permissions("/dev/dri/*", 0666, 0, 1000);
    Permissions permissions("/dev/dri/*", 0666, 0, 1000, false);
    EXPECT_TRUE(permissions.Match("/dev/dri/some_dri_device"));
    EXPECT_TRUE(permissions.Match("/dev/dri/some_other_dri_device"));
    EXPECT_TRUE(permissions.Match("/dev/dri/"));
@@ -246,7 +246,7 @@ TEST(device_handler, DevPermissionsMatchPrefix) {
TEST(device_handler, DevPermissionsMatchWildcard) {
    // Wildcard example
    // /dev/device*name                0666   root       graphics
    Permissions permissions("/dev/device*name", 0666, 0, 1000);
    Permissions permissions("/dev/device*name", 0666, 0, 1000, false);
    EXPECT_TRUE(permissions.Match("/dev/devicename"));
    EXPECT_TRUE(permissions.Match("/dev/device123name"));
    EXPECT_TRUE(permissions.Match("/dev/deviceabcname"));
@@ -260,13 +260,31 @@ TEST(device_handler, DevPermissionsMatchWildcard) {
TEST(device_handler, DevPermissionsMatchWildcardPrefix) {
    // Wildcard+Prefix example
    // /dev/device*name*                0666   root       graphics
    Permissions permissions("/dev/device*name*", 0666, 0, 1000);
    Permissions permissions("/dev/device*name*", 0666, 0, 1000, false);
    EXPECT_TRUE(permissions.Match("/dev/devicename"));
    EXPECT_TRUE(permissions.Match("/dev/device123name"));
    EXPECT_TRUE(permissions.Match("/dev/deviceabcname"));
    EXPECT_TRUE(permissions.Match("/dev/device123namesomething"));
    // FNM_PATHNAME doesn't match '/' with *
    EXPECT_FALSE(permissions.Match("/dev/device123name/something"));
    EXPECT_FALSE(permissions.Match("/dev/device/1/2/3name/something"));
    EXPECT_FALSE(permissions.Match("/dev/deviceame"));
    EXPECT_EQ(0666U, permissions.perm());
    EXPECT_EQ(0U, permissions.uid());
    EXPECT_EQ(1000U, permissions.gid());
}

TEST(device_handler, DevPermissionsMatchWildcardPrefix_NoFnmPathName) {
    // Wildcard+Prefix example with no_fnm_pathname
    // /dev/device*name*                0666   root       graphics
    Permissions permissions("/dev/device*name*", 0666, 0, 1000, true);
    EXPECT_TRUE(permissions.Match("/dev/devicename"));
    EXPECT_TRUE(permissions.Match("/dev/device123name"));
    EXPECT_TRUE(permissions.Match("/dev/deviceabcname"));
    EXPECT_TRUE(permissions.Match("/dev/device123namesomething"));
    // With NoFnmPathName, the below matches, unlike DevPermissionsMatchWildcardPrefix.
    EXPECT_TRUE(permissions.Match("/dev/device123name/something"));
    EXPECT_TRUE(permissions.Match("/dev/device/1/2/3name/something"));
    EXPECT_FALSE(permissions.Match("/dev/deviceame"));
    EXPECT_EQ(0666U, permissions.perm());
    EXPECT_EQ(0U, permissions.uid());
@@ -275,7 +293,8 @@ TEST(device_handler, DevPermissionsMatchWildcardPrefix) {

TEST(device_handler, SysfsPermissionsMatchWithSubsystemNormal) {
    // /sys/devices/virtual/input/input*   enable      0660  root   input
    SysfsPermissions permissions("/sys/devices/virtual/input/input*", "enable", 0660, 0, 1001);
    SysfsPermissions permissions("/sys/devices/virtual/input/input*", "enable", 0660, 0, 1001,
                                 false);
    EXPECT_TRUE(permissions.MatchWithSubsystem("/sys/devices/virtual/input/input0", "input"));
    EXPECT_FALSE(permissions.MatchWithSubsystem("/sys/devices/virtual/input/not_input0", "input"));
    EXPECT_EQ(0660U, permissions.perm());
@@ -285,7 +304,7 @@ TEST(device_handler, SysfsPermissionsMatchWithSubsystemNormal) {

TEST(device_handler, SysfsPermissionsMatchWithSubsystemClass) {
    // /sys/class/input/event*   enable      0660  root   input
    SysfsPermissions permissions("/sys/class/input/event*", "enable", 0660, 0, 1001);
    SysfsPermissions permissions("/sys/class/input/event*", "enable", 0660, 0, 1001, false);
    EXPECT_TRUE(permissions.MatchWithSubsystem(
        "/sys/devices/soc.0/f9924000.i2c/i2c-2/2-0020/input/input0/event0", "input"));
    EXPECT_FALSE(permissions.MatchWithSubsystem(
@@ -299,7 +318,7 @@ TEST(device_handler, SysfsPermissionsMatchWithSubsystemClass) {

TEST(device_handler, SysfsPermissionsMatchWithSubsystemBus) {
    // /sys/bus/i2c/devices/i2c-*   enable      0660  root   input
    SysfsPermissions permissions("/sys/bus/i2c/devices/i2c-*", "enable", 0660, 0, 1001);
    SysfsPermissions permissions("/sys/bus/i2c/devices/i2c-*", "enable", 0660, 0, 1001, false);
    EXPECT_TRUE(permissions.MatchWithSubsystem("/sys/devices/soc.0/f9967000.i2c/i2c-5", "i2c"));
    EXPECT_FALSE(permissions.MatchWithSubsystem("/sys/devices/soc.0/f9967000.i2c/not-i2c", "i2c"));
    EXPECT_FALSE(
+15 −6
Original line number Diff line number Diff line
@@ -34,12 +34,12 @@ Result<void> ParsePermissionsLine(std::vector<std::string>&& args,
                                  std::vector<SysfsPermissions>* out_sysfs_permissions,
                                  std::vector<Permissions>* out_dev_permissions) {
    bool is_sysfs = out_sysfs_permissions != nullptr;
    if (is_sysfs && args.size() != 5) {
        return Error() << "/sys/ lines must have 5 entries";
    if (is_sysfs && !(args.size() == 5 || args.size() == 6)) {
        return Error() << "/sys/ lines must have 5 or 6 entries";
    }

    if (!is_sysfs && args.size() != 4) {
        return Error() << "/dev/ lines must have 4 entries";
    if (!is_sysfs && !(args.size() == 4 || args.size() == 5)) {
        return Error() << "/dev/ lines must have 4 or 5 entries";
    }

    auto it = args.begin();
@@ -70,10 +70,19 @@ Result<void> ParsePermissionsLine(std::vector<std::string>&& args,
    }
    gid_t gid = grp->gr_gid;

    bool no_fnm_pathname = false;
    if (it != args.end()) {
        std::string& flags = *it++;
        if (flags != "no_fnm_pathname") {
            return Error() << "invalid option '" << flags << "', only no_fnm_pathname is supported";
        }
        no_fnm_pathname = true;
    }

    if (is_sysfs) {
        out_sysfs_permissions->emplace_back(name, sysfs_attribute, perm, uid, gid);
        out_sysfs_permissions->emplace_back(name, sysfs_attribute, perm, uid, gid, no_fnm_pathname);
    } else {
        out_dev_permissions->emplace_back(name, perm, uid, gid);
        out_dev_permissions->emplace_back(name, perm, uid, gid, no_fnm_pathname);
    }
    return {};
}
Loading