Snap for 12680993 from c27ea1cc352235ababa3523a12fa701dd2391607 to 25Q1-release

Change-Id: I0f58eeae28fc1bdd1bfd54ff35de9da9e25d9a8b
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index 13c8d70..5bdc946 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -3302,3 +3302,30 @@
   ASSERT_MATCH(result, ":\\s*This line has a newline.");
   ASSERT_MATCH(result, ":\\s*This is on the next line.");
 }
+
+TEST_F(CrasherTest, log_with_non_utf8) {
+  StartProcess([]() { LOG(FATAL) << "Invalid UTF-8: \xA0\xB0\xC0\xD0 and some other data."; });
+
+  unique_fd output_fd;
+  StartIntercept(&output_fd);
+  FinishCrasher();
+  AssertDeath(SIGABRT);
+  int intercept_result;
+  FinishIntercept(&intercept_result);
+  ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
+
+  std::string result;
+  ConsumeFd(std::move(output_fd), &result);
+  // Verify the abort message is sanitized properly.
+  size_t pos = result.find(
+      "Abort message: 'Invalid UTF-8: "
+      "\x5C\x32\x34\x30\x5C\x32\x36\x30\x5C\x33\x30\x30\x5C\x33\x32\x30 and some other data.'");
+  EXPECT_TRUE(pos != std::string::npos) << "Couldn't find sanitized abort message: " << result;
+
+  // Make sure that the log message is sanitized properly too.
+  EXPECT_TRUE(
+      result.find("Invalid UTF-8: \x5C\x32\x34\x30\x5C\x32\x36\x30\x5C\x33\x30\x30\x5C\x33\x32\x30 "
+                  "and some other data.",
+                  pos + 30) != std::string::npos)
+      << "Couldn't find sanitized log message: " << result;
+}
diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/utility_host.h b/debuggerd/libdebuggerd/include/libdebuggerd/utility_host.h
index 43fb8bd..df22e01 100644
--- a/debuggerd/libdebuggerd/include/libdebuggerd/utility_host.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/utility_host.h
@@ -29,3 +29,5 @@
 // Number of rows and columns to display in an MTE tag dump.
 constexpr size_t kNumTagColumns = 16;
 constexpr size_t kNumTagRows = 16;
+
+std::string oct_encode(const std::string& data);
diff --git a/debuggerd/libdebuggerd/tombstone_proto.cpp b/debuggerd/libdebuggerd/tombstone_proto.cpp
index d59358c..ef303f0 100644
--- a/debuggerd/libdebuggerd/tombstone_proto.cpp
+++ b/debuggerd/libdebuggerd/tombstone_proto.cpp
@@ -34,10 +34,13 @@
 #include <sys/sysinfo.h>
 #include <time.h>
 
+#include <map>
 #include <memory>
 #include <optional>
 #include <set>
 #include <string>
+#include <utility>
+#include <vector>
 
 #include <async_safe/log.h>
 
@@ -463,7 +466,8 @@
   }
   msg.resize(index);
 
-  tombstone->set_abort_message(msg);
+  // Make sure only UTF8 characters are present since abort_message is a string.
+  tombstone->set_abort_message(oct_encode(msg));
 }
 
 static void dump_open_fds(Tombstone* tombstone, const OpenFilesList* open_files) {
@@ -771,7 +775,8 @@
       log_msg->set_tid(log_entry.entry.tid);
       log_msg->set_priority(prio);
       log_msg->set_tag(tag);
-      log_msg->set_message(msg);
+      // Make sure only UTF8 characters are present since message is a string.
+      log_msg->set_message(oct_encode(msg));
     } while ((msg = nl));
   }
   android_logger_list_free(logger_list);
diff --git a/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp b/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
index fedafc0..e885c5a 100644
--- a/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
+++ b/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
@@ -19,9 +19,9 @@
 
 #include <inttypes.h>
 
-#include <charconv>
+#include <algorithm>
 #include <functional>
-#include <limits>
+#include <optional>
 #include <set>
 #include <string>
 #include <unordered_set>
@@ -32,6 +32,7 @@
 #include <android-base/strings.h>
 #include <android-base/unique_fd.h>
 
+#include "libdebuggerd/utility_host.h"
 #include "tombstone.pb.h"
 
 using android::base::StringAppendF;
@@ -418,27 +419,6 @@
   }
 }
 
-static std::string oct_encode(const std::string& data) {
-  std::string oct_encoded;
-  oct_encoded.reserve(data.size());
-
-  // N.B. the unsigned here is very important, otherwise e.g. \255 would render as
-  // \-123 (and overflow our buffer).
-  for (unsigned char c : data) {
-    if (isprint(c)) {
-      oct_encoded += c;
-    } else {
-      std::string oct_digits("\\\0\0\0", 4);
-      // char is encodable in 3 oct digits
-      static_assert(std::numeric_limits<unsigned char>::max() <= 8 * 8 * 8);
-      auto [ptr, ec] = std::to_chars(oct_digits.data() + 1, oct_digits.data() + 4, c, 8);
-      oct_digits.resize(ptr - oct_digits.data());
-      oct_encoded += oct_digits;
-    }
-  }
-  return oct_encoded;
-}
-
 static void print_main_thread(CallbackType callback, SymbolizeCallbackType symbolize,
                               const Tombstone& tombstone, const Thread& thread) {
   print_thread_header(callback, tombstone, thread, true);
diff --git a/debuggerd/libdebuggerd/utility_host.cpp b/debuggerd/libdebuggerd/utility_host.cpp
index 72a560c..4efa03c 100644
--- a/debuggerd/libdebuggerd/utility_host.cpp
+++ b/debuggerd/libdebuggerd/utility_host.cpp
@@ -18,6 +18,8 @@
 
 #include <sys/prctl.h>
 
+#include <charconv>
+#include <limits>
 #include <string>
 
 #include <android-base/stringprintf.h>
@@ -99,3 +101,24 @@
   DESCRIBE_FLAG(PR_PAC_APGAKEY);
   return describe_end(value, desc);
 }
+
+std::string oct_encode(const std::string& data) {
+  std::string oct_encoded;
+  oct_encoded.reserve(data.size());
+
+  // N.B. the unsigned here is very important, otherwise e.g. \255 would render as
+  // \-123 (and overflow our buffer).
+  for (unsigned char c : data) {
+    if (isprint(c)) {
+      oct_encoded += c;
+    } else {
+      std::string oct_digits("\\\0\0\0", 4);
+      // char is encodable in 3 oct digits
+      static_assert(std::numeric_limits<unsigned char>::max() <= 8 * 8 * 8);
+      auto [ptr, ec] = std::to_chars(oct_digits.data() + 1, oct_digits.data() + 4, c, 8);
+      oct_digits.resize(ptr - oct_digits.data());
+      oct_encoded += oct_digits;
+    }
+  }
+  return oct_encoded;
+}
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_test.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_test.cpp
index 4dfb9bf..469fd09 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_test.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_test.cpp
@@ -82,6 +82,8 @@
 
     unique_fd GetCowFd() { return unique_fd{dup(cow_system_->fd)}; }
 
+    bool ShouldSkipSetUp();
+
     std::unique_ptr<ITestHarness> harness_;
     size_t size_ = 10_MiB;
     int total_base_size_ = 0;
@@ -97,6 +99,10 @@
 };
 
 void SnapuserdTestBase::SetUp() {
+    if (ShouldSkipSetUp()) {
+        GTEST_SKIP() << "snapuserd not supported on this device";
+    }
+
 #if __ANDROID__
     harness_ = std::make_unique<DmUserTestHarness>();
 #else
@@ -104,6 +110,16 @@
 #endif
 }
 
+bool SnapuserdTestBase::ShouldSkipSetUp() {
+#ifdef __ANDROID__
+    if (!android::snapshot::CanUseUserspaceSnapshots() ||
+        android::snapshot::IsVendorFromAndroid12()) {
+        return true;
+    }
+#endif
+    return false;
+}
+
 void SnapuserdTestBase::TearDown() {
     cow_system_ = nullptr;
 }
@@ -302,6 +318,9 @@
 };
 
 void SnapuserdTest::SetUp() {
+    if (ShouldSkipSetUp()) {
+        GTEST_SKIP() << "snapuserd not supported on this device";
+    }
     ASSERT_NO_FATAL_FAILURE(SnapuserdTestBase::SetUp());
     handlers_ = std::make_unique<SnapshotHandlerManager>();
 }
@@ -312,6 +331,9 @@
 }
 
 void SnapuserdTest::Shutdown() {
+    if (!handlers_) {
+        return;
+    }
     if (dmuser_dev_) {
         ASSERT_TRUE(dmuser_dev_->Destroy());
     }
@@ -1181,6 +1203,9 @@
 }
 
 void SnapuserdVariableBlockSizeTest::SetUp() {
+    if (ShouldSkipSetUp()) {
+        GTEST_SKIP() << "snapuserd not supported on this device";
+    }
     ASSERT_NO_FATAL_FAILURE(SnapuserdTest::SetUp());
 }
 
@@ -1244,6 +1269,9 @@
 }
 
 void HandlerTest::SetUp() {
+    if (ShouldSkipSetUp()) {
+        GTEST_SKIP() << "snapuserd not supported on this device";
+    }
     ASSERT_NO_FATAL_FAILURE(SnapuserdTestBase::SetUp());
     ASSERT_NO_FATAL_FAILURE(CreateBaseDevice());
     ASSERT_NO_FATAL_FAILURE(SetUpV2Cow());
@@ -1251,6 +1279,9 @@
 }
 
 void HandlerTest::TearDown() {
+    if (ShouldSkipSetUp()) {
+        return;
+    }
     ASSERT_TRUE(factory_.DeleteQueue(system_device_ctrl_name_));
     ASSERT_TRUE(handler_thread_.get());
     SnapuserdTestBase::TearDown();
@@ -1326,6 +1357,9 @@
 };
 
 void HandlerTestV3::SetUp() {
+    if (ShouldSkipSetUp()) {
+        GTEST_SKIP() << "snapuserd not supported on this device";
+    }
     ASSERT_NO_FATAL_FAILURE(SnapuserdTestBase::SetUp());
     ASSERT_NO_FATAL_FAILURE(CreateBaseDevice());
     ASSERT_NO_FATAL_FAILURE(SetUpV3Cow());
@@ -1530,14 +1564,6 @@
 int main(int argc, char** argv) {
     ::testing::InitGoogleTest(&argc, argv);
 
-#ifdef __ANDROID__
-    if (!android::snapshot::CanUseUserspaceSnapshots() ||
-        android::snapshot::IsVendorFromAndroid12()) {
-        std::cerr << "snapuserd_test not supported on this device\n";
-        return 0;
-    }
-#endif
-
     gflags::ParseCommandLineFlags(&argc, &argv, false);
 
     return RUN_ALL_TESTS();
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_verify.h b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_verify.h
index 7c99085..b300a70 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_verify.h
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_verify.h
@@ -62,8 +62,8 @@
      * (/proc/pressure/{cpu,memory}; and monitoring the Inactive(file) and
      * Active(file) pages from /proc/meminfo.
      *
-     * Additionally, for low memory devices, it is advisible to use O_DIRECT
-     * fucntionality for source block device.
+     * Additionally, for low memory devices, it is advisable to use O_DIRECT
+     * functionality for source block device.
      */
     int kMinThreadsToVerify = 1;
     int kMaxThreadsToVerify = 3;
diff --git a/init/README.ueventd.md b/init/README.ueventd.md
index aac4acb..0e84c6f 100644
--- a/init/README.ueventd.md
+++ b/init/README.ueventd.md
@@ -76,17 +76,17 @@
 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 @@
     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
diff --git a/init/block_dev_initializer.cpp b/init/block_dev_initializer.cpp
index 7f83037..deb68e9 100644
--- a/init/block_dev_initializer.cpp
+++ b/init/block_dev_initializer.cpp
@@ -33,7 +33,8 @@
     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
diff --git a/init/devices.cpp b/init/devices.cpp
index fafa58f..aeaa431 100644
--- a/init/devices.cpp
+++ b/init/devices.cpp
@@ -345,6 +345,26 @@
     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 @@
     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 @@
     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 @@
 
 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()
     : 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
diff --git a/init/devices.h b/init/devices.h
index b8f8e54..69a2449 100644
--- a/init/devices.h
+++ b/init/devices.h
@@ -21,6 +21,7 @@
 #include <sys/types.h>
 
 #include <algorithm>
+#include <map>
 #include <set>
 #include <string>
 #include <vector>
@@ -128,7 +129,7 @@
 
     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 @@
     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 @@
     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
diff --git a/init/uevent.h b/init/uevent.h
index c8ca52a..e7ed226 100644
--- a/init/uevent.h
+++ b/init/uevent.h
@@ -26,6 +26,7 @@
     std::string action;
     std::string path;
     std::string subsystem;
+    std::string driver;
     std::string firmware;
     std::string partition_name;
     std::string partition_uuid;
diff --git a/init/uevent_listener.cpp b/init/uevent_listener.cpp
index 97f3de6..d329c17 100644
--- a/init/uevent_listener.cpp
+++ b/init/uevent_listener.cpp
@@ -36,6 +36,7 @@
     uevent->action.clear();
     uevent->path.clear();
     uevent->subsystem.clear();
+    uevent->driver.clear();
     uevent->firmware.clear();
     uevent->partition_name.clear();
     uevent->device_name.clear();
@@ -51,6 +52,9 @@
         } else if (!strncmp(msg, "SUBSYSTEM=", 10)) {
             msg += 10;
             uevent->subsystem = msg;
+        } else if (!strncmp(msg, "DRIVER=", 7)) {
+            msg += 7;
+            uevent->driver = msg;
         } else if (!strncmp(msg, "FIRMWARE=", 9)) {
             msg += 9;
             uevent->firmware = msg;
diff --git a/init/ueventd.cpp b/init/ueventd.cpp
index 286e472..cb6b851 100644
--- a/init/ueventd.cpp
+++ b/init/ueventd.cpp
@@ -364,8 +364,8 @@
     std::unique_ptr<DeviceHandler> device_handler = std::make_unique<DeviceHandler>(
             std::move(ueventd_configuration.dev_permissions),
             std::move(ueventd_configuration.sysfs_permissions),
-            std::move(ueventd_configuration.subsystems), android::fs_mgr::GetBootDevices(),
-            android::fs_mgr::GetBootPartUuid(), true);
+            std::move(ueventd_configuration.drivers), std::move(ueventd_configuration.subsystems),
+            android::fs_mgr::GetBootDevices(), android::fs_mgr::GetBootPartUuid(), true);
     uevent_listener.RegenerateUevents([&](const Uevent& uevent) -> ListenerAction {
         bool uuid_check_done = device_handler->CheckUeventForBootPartUuid(uevent);
         return uuid_check_done ? ListenerAction::kStop : ListenerAction::kContinue;
diff --git a/init/ueventd_parser.cpp b/init/ueventd_parser.cpp
index 4395d88..097ef09 100644
--- a/init/ueventd_parser.cpp
+++ b/init/ueventd_parser.cpp
@@ -264,6 +264,8 @@
     parser.AddSectionParser("import", std::make_unique<ImportParser>(&parser));
     parser.AddSectionParser("subsystem",
                             std::make_unique<SubsystemParser>(&ueventd_configuration.subsystems));
+    parser.AddSectionParser("driver",
+                            std::make_unique<SubsystemParser>(&ueventd_configuration.drivers));
 
     using namespace std::placeholders;
     parser.AddSingleLineParser(
diff --git a/init/ueventd_parser.h b/init/ueventd_parser.h
index 81f4e9d..ffe6072 100644
--- a/init/ueventd_parser.h
+++ b/init/ueventd_parser.h
@@ -27,6 +27,7 @@
 
 struct UeventdConfiguration {
     std::vector<Subsystem> subsystems;
+    std::vector<Subsystem> drivers;
     std::vector<SysfsPermissions> sysfs_permissions;
     std::vector<Permissions> dev_permissions;
     std::vector<std::string> firmware_directories;
diff --git a/init/ueventd_parser_test.cpp b/init/ueventd_parser_test.cpp
index 41924e2..6d91039 100644
--- a/init/ueventd_parser_test.cpp
+++ b/init/ueventd_parser_test.cpp
@@ -106,7 +106,32 @@
             {"test_devname2", Subsystem::DEVNAME_UEVENT_DEVNAME, "/dev"},
             {"test_devpath_dirname", Subsystem::DEVNAME_UEVENT_DEVPATH, "/dev/graphics"}};
 
-    TestUeventdFile(ueventd_file, {subsystems, {}, {}, {}, {}, {}});
+    TestUeventdFile(ueventd_file, {subsystems, {}, {}, {}, {}, {}, {}});
+}
+
+TEST(ueventd_parser, Drivers) {
+    auto ueventd_file = R"(
+driver test_devname
+    devname uevent_devname
+
+driver test_devpath_no_dirname
+    devname uevent_devpath
+
+driver test_devname2
+    devname uevent_devname
+
+driver test_devpath_dirname
+    devname uevent_devpath
+    dirname /dev/graphics
+)";
+
+    auto drivers = std::vector<Subsystem>{
+            {"test_devname", Subsystem::DEVNAME_UEVENT_DEVNAME, "/dev"},
+            {"test_devpath_no_dirname", Subsystem::DEVNAME_UEVENT_DEVPATH, "/dev"},
+            {"test_devname2", Subsystem::DEVNAME_UEVENT_DEVNAME, "/dev"},
+            {"test_devpath_dirname", Subsystem::DEVNAME_UEVENT_DEVPATH, "/dev/graphics"}};
+
+    TestUeventdFile(ueventd_file, {{}, drivers, {}, {}, {}, {}, {}, {}});
 }
 
 TEST(ueventd_parser, Permissions) {
@@ -132,7 +157,7 @@
             {"/sys/devices/virtual/*/input", "poll_delay", 0660, AID_ROOT, AID_INPUT, true},
     };
 
-    TestUeventdFile(ueventd_file, {{}, sysfs_permissions, permissions, {}, {}, {}});
+    TestUeventdFile(ueventd_file, {{}, {}, sysfs_permissions, permissions, {}, {}, {}});
 }
 
 TEST(ueventd_parser, FirmwareDirectories) {
@@ -148,7 +173,7 @@
             "/more",
     };
 
-    TestUeventdFile(ueventd_file, {{}, {}, {}, firmware_directories, {}, {}});
+    TestUeventdFile(ueventd_file, {{}, {}, {}, {}, firmware_directories, {}, {}});
 }
 
 TEST(ueventd_parser, ExternalFirmwareHandlers) {
@@ -214,7 +239,7 @@
             },
     };
 
-    TestUeventdFile(ueventd_file, {{}, {}, {}, {}, external_firmware_handlers, {}});
+    TestUeventdFile(ueventd_file, {{}, {}, {}, {}, {}, external_firmware_handlers, {}});
 }
 
 TEST(ueventd_parser, ExternalFirmwareHandlersDuplicate) {
@@ -232,7 +257,7 @@
             },
     };
 
-    TestUeventdFile(ueventd_file, {{}, {}, {}, {}, external_firmware_handlers, {}});
+    TestUeventdFile(ueventd_file, {{}, {}, {}, {}, {}, external_firmware_handlers, {}});
 }
 
 TEST(ueventd_parser, ParallelRestoreconDirs) {
@@ -246,7 +271,7 @@
             "/sys/devices",
     };
 
-    TestUeventdFile(ueventd_file, {{}, {}, {}, {}, {}, parallel_restorecon_dirs});
+    TestUeventdFile(ueventd_file, {{}, {}, {}, {}, {}, {}, parallel_restorecon_dirs});
 }
 
 TEST(ueventd_parser, UeventSocketRcvbufSize) {
@@ -255,7 +280,7 @@
 uevent_socket_rcvbuf_size 8M
 )";
 
-    TestUeventdFile(ueventd_file, {{}, {}, {}, {}, {}, {}, false, 8 * 1024 * 1024});
+    TestUeventdFile(ueventd_file, {{}, {}, {}, {}, {}, {}, {}, false, 8 * 1024 * 1024});
 }
 
 TEST(ueventd_parser, EnabledDisabledLines) {
@@ -265,7 +290,7 @@
 modalias_handling disabled
 )";
 
-    TestUeventdFile(ueventd_file, {{}, {}, {}, {}, {}, {}, false, 0, true});
+    TestUeventdFile(ueventd_file, {{}, {}, {}, {}, {}, {}, {}, false, 0, true});
 
     auto ueventd_file2 = R"(
 parallel_restorecon enabled
@@ -273,7 +298,7 @@
 parallel_restorecon disabled
 )";
 
-    TestUeventdFile(ueventd_file2, {{}, {}, {}, {}, {}, {}, true, 0, false});
+    TestUeventdFile(ueventd_file2, {{}, {}, {}, {}, {}, {}, {}, true, 0, false});
 }
 
 TEST(ueventd_parser, AllTogether) {
@@ -286,6 +311,9 @@
 subsystem test_devname
     devname uevent_devname
 
+driver d_test_devpath
+    devname uevent_devpath
+
 /dev/graphics/*           0660   root       graphics
 
 subsystem test_devpath_no_dirname
@@ -303,6 +331,10 @@
     devname uevent_devpath
     dirname /dev/graphics
 
+driver d_test_devname_dirname
+    devname uevent_devname
+    dirname /dev/sound
+
 /dev/*/test               0660   root       system
 /sys/devices/virtual/*/input   poll_delay  0660  root   input    no_fnm_pathname
 firmware_directories /more
@@ -325,6 +357,10 @@
             {"test_devname2", Subsystem::DEVNAME_UEVENT_DEVNAME, "/dev"},
             {"test_devpath_dirname", Subsystem::DEVNAME_UEVENT_DEVPATH, "/dev/graphics"}};
 
+    auto drivers = std::vector<Subsystem>{
+            {"d_test_devpath", Subsystem::DEVNAME_UEVENT_DEVPATH, "/dev"},
+            {"d_test_devname_dirname", Subsystem::DEVNAME_UEVENT_DEVNAME, "/dev/graphics"}};
+
     auto permissions = std::vector<Permissions>{
             {"/dev/rtc0", 0640, AID_SYSTEM, AID_SYSTEM, false},
             {"/dev/graphics/*", 0660, AID_ROOT, AID_GRAPHICS, false},
@@ -356,7 +392,7 @@
     size_t uevent_socket_rcvbuf_size = 6 * 1024 * 1024;
 
     TestUeventdFile(ueventd_file,
-                    {subsystems, sysfs_permissions, permissions, firmware_directories,
+                    {subsystems, drivers, sysfs_permissions, permissions, firmware_directories,
                      external_firmware_handlers, parallel_restorecon_dirs, true,
                      uevent_socket_rcvbuf_size, true});
 }
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
index 1039288..ec9b754 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -21,6 +21,17 @@
     srcs: ["include/private/android_filesystem_config.h"],
 }
 
+rust_bindgen {
+    name: "libandroid_ids",
+    crate_name: "android_ids",
+    source_stem: "bindings",
+    wrapper_src: "rust/aid_bindings.h",
+    header_libs: ["libcutils_headers"],
+    visibility: [
+        "//system/bpf/loader",
+    ],
+}
+
 cc_defaults {
     name: "libcutils_defaults",
     cflags: [
diff --git a/libcutils/rust/aid_bindings.h b/libcutils/rust/aid_bindings.h
new file mode 100644
index 0000000..1b175a2
--- /dev/null
+++ b/libcutils/rust/aid_bindings.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <private/android_filesystem_config.h>