From e29101077c9fae5dbb9563d046ea37272e7f0b8f Mon Sep 17 00:00:00 2001 From: Tom Cherry Date: Thu, 6 Dec 2018 13:29:30 -0800 Subject: [PATCH] ueventd: allow configuring SO_RCVBUF(FORCE) for the ueventd socket Some configurations won't allow ueventd to have CAP_NET_ADMIN, so the new default size of 16M is not possible for those. Those configurations also won't need such a large buffer size, so this change allows devices to customize the SO_RCVBUF(FORCE) size for the uevent socket. This is done by adding the line 'uevent_socket_rcvbuf_size ' to your device's ueventd.rc file. is specified as a byte count, for example '16M' is 16MiB. The last parsed uevent_socket_rcvbuf_size line is the one that is used. Bug: 120485624 Test: boot sailfish Test: ueventd unit tests Change-Id: If8123b92ca8a9b089ad50318caada2f21bc94707 --- init/first_stage_mount.cpp | 4 +++- init/uevent_listener.cpp | 5 ++--- init/uevent_listener.h | 2 +- init/ueventd.cpp | 33 +++++++++++++++------------------ init/ueventd_parser.cpp | 23 +++++++++++++++++++++++ init/ueventd_parser.h | 1 + init/ueventd_parser_test.cpp | 19 +++++++++++++++++-- rootdir/ueventd.rc | 1 + 8 files changed, 63 insertions(+), 25 deletions(-) diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp index c1246567a..6ae112342 100644 --- a/init/first_stage_mount.cpp +++ b/init/first_stage_mount.cpp @@ -132,7 +132,9 @@ static bool IsRecoveryMode() { // Class Definitions // ----------------- FirstStageMount::FirstStageMount() - : need_dm_verity_(false), fstab_(fs_mgr_read_fstab_dt(), fs_mgr_free_fstab) { + : need_dm_verity_(false), + fstab_(fs_mgr_read_fstab_dt(), fs_mgr_free_fstab), + uevent_listener_(16 * 1024 * 1024) { // Stores fstab_->recs[] into mount_fstab_recs_ (vector) // for easier manipulation later, e.g., range-base for loop. if (fstab_) { diff --git a/init/uevent_listener.cpp b/init/uevent_listener.cpp index d6765b7a1..62cd2be3a 100644 --- a/init/uevent_listener.cpp +++ b/init/uevent_listener.cpp @@ -86,9 +86,8 @@ static void ParseEvent(const char* msg, Uevent* uevent) { } } -UeventListener::UeventListener() { - // is 16MB enough? udev uses 128MB! - device_fd_.reset(uevent_open_socket(16 * 1024 * 1024, true)); +UeventListener::UeventListener(size_t uevent_socket_rcvbuf_size) { + device_fd_.reset(uevent_open_socket(uevent_socket_rcvbuf_size, true)); if (device_fd_ == -1) { LOG(FATAL) << "Could not open uevent socket"; } diff --git a/init/uevent_listener.h b/init/uevent_listener.h index 5b453fe65..aea094e77 100644 --- a/init/uevent_listener.h +++ b/init/uevent_listener.h @@ -41,7 +41,7 @@ using ListenerCallback = std::function; class UeventListener { public: - UeventListener(); + UeventListener(size_t uevent_socket_rcvbuf_size); void RegenerateUevents(const ListenerCallback& callback) const; ListenerAction RegenerateUeventsForPath(const std::string& path, diff --git a/init/ueventd.cpp b/init/ueventd.cpp index 66491ddfd..7545d53b8 100644 --- a/init/ueventd.cpp +++ b/init/ueventd.cpp @@ -233,29 +233,26 @@ int ueventd_main(int argc, char** argv) { SelabelInitialize(); std::vector> uevent_handlers; - UeventListener uevent_listener; - { - // Keep the current product name base configuration so we remain backwards compatible and - // allow it to override everything. - // TODO: cleanup platform ueventd.rc to remove vendor specific device node entries (b/34968103) - auto hardware = android::base::GetProperty("ro.hardware", ""); + // Keep the current product name base configuration so we remain backwards compatible and + // allow it to override everything. + // TODO: cleanup platform ueventd.rc to remove vendor specific device node entries (b/34968103) + auto hardware = android::base::GetProperty("ro.hardware", ""); - auto ueventd_configuration = - ParseConfig({"/ueventd.rc", "/vendor/ueventd.rc", "/odm/ueventd.rc", - "/ueventd." + hardware + ".rc"}); + auto ueventd_configuration = ParseConfig({"/ueventd.rc", "/vendor/ueventd.rc", + "/odm/ueventd.rc", "/ueventd." + hardware + ".rc"}); - uevent_handlers.emplace_back(std::make_unique( - std::move(ueventd_configuration.dev_permissions), - std::move(ueventd_configuration.sysfs_permissions), - std::move(ueventd_configuration.subsystems), fs_mgr_get_boot_devices(), true)); - uevent_handlers.emplace_back(std::make_unique( - std::move(ueventd_configuration.firmware_directories))); + uevent_handlers.emplace_back(std::make_unique( + std::move(ueventd_configuration.dev_permissions), + std::move(ueventd_configuration.sysfs_permissions), + std::move(ueventd_configuration.subsystems), fs_mgr_get_boot_devices(), true)); + uevent_handlers.emplace_back(std::make_unique( + std::move(ueventd_configuration.firmware_directories))); - if (ueventd_configuration.enable_modalias_handling) { - uevent_handlers.emplace_back(std::make_unique()); - } + if (ueventd_configuration.enable_modalias_handling) { + uevent_handlers.emplace_back(std::make_unique()); } + UeventListener uevent_listener(ueventd_configuration.uevent_socket_rcvbuf_size); if (access(COLDBOOT_DONE, F_OK) != 0) { ColdBoot cold_boot(uevent_listener, uevent_handlers); diff --git a/init/ueventd_parser.cpp b/init/ueventd_parser.cpp index 677938e10..aac3fe5c1 100644 --- a/init/ueventd_parser.cpp +++ b/init/ueventd_parser.cpp @@ -19,9 +19,13 @@ #include #include +#include + #include "keyword_map.h" #include "parser.h" +using android::base::ParseByteCount; + namespace android { namespace init { @@ -101,6 +105,22 @@ Result ParseModaliasHandlingLine(std::vector&& args, return Success(); } +Result ParseUeventSocketRcvbufSizeLine(std::vector&& args, + size_t* uevent_socket_rcvbuf_size) { + if (args.size() != 2) { + return Error() << "uevent_socket_rcvbuf_size lines take exactly one parameter"; + } + + size_t parsed_size; + if (!ParseByteCount(args[1], &parsed_size)) { + return Error() << "could not parse size '" << args[1] << "' for uevent_socket_rcvbuf_line"; + } + + *uevent_socket_rcvbuf_size = parsed_size; + + return Success(); +} + class SubsystemParser : public SectionParser { public: SubsystemParser(std::vector* subsystems) : subsystems_(subsystems) {} @@ -202,6 +222,9 @@ UeventdConfiguration ParseConfig(const std::vector& configs) { parser.AddSingleLineParser("modalias_handling", std::bind(ParseModaliasHandlingLine, _1, &ueventd_configuration.enable_modalias_handling)); + parser.AddSingleLineParser("uevent_socket_rcvbuf_size", + std::bind(ParseUeventSocketRcvbufSizeLine, _1, + &ueventd_configuration.uevent_socket_rcvbuf_size)); for (const auto& config : configs) { parser.ParseConfig(config); diff --git a/init/ueventd_parser.h b/init/ueventd_parser.h index 7d30edf4f..d476decc9 100644 --- a/init/ueventd_parser.h +++ b/init/ueventd_parser.h @@ -31,6 +31,7 @@ struct UeventdConfiguration { std::vector dev_permissions; std::vector firmware_directories; bool enable_modalias_handling = false; + size_t uevent_socket_rcvbuf_size = 0; }; UeventdConfiguration ParseConfig(const std::vector& configs); diff --git a/init/ueventd_parser_test.cpp b/init/ueventd_parser_test.cpp index c3af341c6..9c1cedf8b 100644 --- a/init/ueventd_parser_test.cpp +++ b/init/ueventd_parser_test.cpp @@ -138,6 +138,15 @@ firmware_directories /more TestUeventdFile(ueventd_file, {{}, {}, {}, firmware_directories}); } +TEST(ueventd_parser, UeventSocketRcvbufSize) { + auto ueventd_file = R"( +uevent_socket_rcvbuf_size 8k +uevent_socket_rcvbuf_size 8M +)"; + + TestUeventdFile(ueventd_file, {{}, {}, {}, {}, false, 8 * 1024 * 1024}); +} + TEST(ueventd_parser, AllTogether) { auto ueventd_file = R"( @@ -169,6 +178,8 @@ subsystem test_devpath_dirname /sys/devices/virtual/*/input poll_delay 0660 root input firmware_directories /more +uevent_socket_rcvbuf_size 6M + #ending comment )"; @@ -197,8 +208,10 @@ firmware_directories /more "/more", }; - TestUeventdFile(ueventd_file, - {subsystems, sysfs_permissions, permissions, firmware_directories}); + size_t uevent_socket_rcvbuf_size = 6 * 1024 * 1024; + + TestUeventdFile(ueventd_file, {subsystems, sysfs_permissions, permissions, firmware_directories, + false, uevent_socket_rcvbuf_size}); } // All of these lines are ill-formed, so test that there is 0 output. @@ -213,6 +226,8 @@ firmware_directories #no directory listed /sys/devices/platform/trusty.* trusty_version 0440 baduidbad log /sys/devices/platform/trusty.* trusty_version 0440 root baduidbad +uevent_socket_rcvbuf_size blah + subsystem #no name )"; diff --git a/rootdir/ueventd.rc b/rootdir/ueventd.rc index d47506c44..a9658a46a 100644 --- a/rootdir/ueventd.rc +++ b/rootdir/ueventd.rc @@ -1,4 +1,5 @@ firmware_directories /etc/firmware/ /odm/firmware/ /vendor/firmware/ /firmware/image/ +uevent_socket_rcvbuf_size 16M subsystem adf devname uevent_devname