Loading init/README.ueventd.md +4 −1 Original line number Diff line number Diff line Loading @@ -123,7 +123,10 @@ not present. The exact firmware file to be served can be customized by running an external program by a `external_firmware_handler` line in a ueventd.rc file. This line takes the format of external_firmware_handler <devpath> <user name to run as> <path to external program> external_firmware_handler <devpath> <user [group]> <path to external program> The handler will be run as the given user, or if a group is provided, as the given user and group. For example external_firmware_handler /devices/leds/red/firmware/coeffs.bin system /vendor/bin/led_coeffs.bin Loading init/firmware_handler.cpp +17 −5 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include <fcntl.h> #include <fnmatch.h> #include <glob.h> #include <grp.h> #include <pwd.h> #include <signal.h> #include <stdlib.h> Loading Loading @@ -81,9 +82,9 @@ static bool IsBooting() { return access("/dev/.booting", F_OK) == 0; } ExternalFirmwareHandler::ExternalFirmwareHandler(std::string devpath, uid_t uid, ExternalFirmwareHandler::ExternalFirmwareHandler(std::string devpath, uid_t uid, gid_t gid, std::string handler_path) : devpath(std::move(devpath)), uid(uid), handler_path(std::move(handler_path)) { : devpath(std::move(devpath)), uid(uid), gid(gid), handler_path(std::move(handler_path)) { auto wildcard_position = this->devpath.find('*'); if (wildcard_position != std::string::npos) { if (wildcard_position == this->devpath.length() - 1) { Loading @@ -97,13 +98,17 @@ ExternalFirmwareHandler::ExternalFirmwareHandler(std::string devpath, uid_t uid, } } ExternalFirmwareHandler::ExternalFirmwareHandler(std::string devpath, uid_t uid, std::string handler_path) : ExternalFirmwareHandler(devpath, uid, 0, handler_path) {} FirmwareHandler::FirmwareHandler(std::vector<std::string> firmware_directories, std::vector<ExternalFirmwareHandler> external_firmware_handlers) : firmware_directories_(std::move(firmware_directories)), external_firmware_handlers_(std::move(external_firmware_handlers)) {} Result<std::string> FirmwareHandler::RunExternalHandler(const std::string& handler, uid_t uid, const Uevent& uevent) const { gid_t gid, const Uevent& uevent) const { unique_fd child_stdout; unique_fd parent_stdout; if (!Socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, &child_stdout, &parent_stdout)) { Loading Loading @@ -140,6 +145,13 @@ Result<std::string> FirmwareHandler::RunExternalHandler(const std::string& handl } c_args.emplace_back(nullptr); if (gid != 0) { if (setgid(gid) != 0) { fprintf(stderr, "setgid() failed: %s", strerror(errno)); _exit(EXIT_FAILURE); } } if (setuid(uid) != 0) { fprintf(stderr, "setuid() failed: %s", strerror(errno)); _exit(EXIT_FAILURE); Loading Loading @@ -196,8 +208,8 @@ std::string FirmwareHandler::GetFirmwarePath(const Uevent& uevent) const { << "' for devpath: '" << uevent.path << "' firmware: '" << uevent.firmware << "'"; auto result = RunExternalHandler(external_handler.handler_path, external_handler.uid, uevent); auto result = RunExternalHandler(external_handler.handler_path, external_handler.uid, external_handler.gid, uevent); if (!result.ok()) { LOG(ERROR) << "Using default firmware; External firmware handler failed: " << result.error(); Loading init/firmware_handler.h +4 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #pragma once #include <grp.h> #include <pwd.h> #include <functional> Loading @@ -31,9 +32,11 @@ namespace init { struct ExternalFirmwareHandler { ExternalFirmwareHandler(std::string devpath, uid_t uid, std::string handler_path); ExternalFirmwareHandler(std::string devpath, uid_t uid, gid_t gid, std::string handler_path); std::string devpath; uid_t uid; gid_t gid; std::string handler_path; std::function<bool(const std::string&)> match; Loading @@ -51,7 +54,7 @@ class FirmwareHandler : public UeventHandler { friend void FirmwareTestWithExternalHandler(const std::string& test_name, bool expect_new_firmware); Result<std::string> RunExternalHandler(const std::string& handler, uid_t uid, Result<std::string> RunExternalHandler(const std::string& handler, uid_t uid, gid_t gid, const Uevent& uevent) const; std::string GetFirmwarePath(const Uevent& uevent) const; void ProcessFirmwareEvent(const std::string& root, const std::string& firmware) const; Loading init/ueventd_parser.cpp +15 −3 Original line number Diff line number Diff line Loading @@ -101,8 +101,8 @@ Result<void> ParseFirmwareDirectoriesLine(std::vector<std::string>&& args, Result<void> ParseExternalFirmwareHandlerLine( std::vector<std::string>&& args, std::vector<ExternalFirmwareHandler>* external_firmware_handlers) { if (args.size() != 4) { return Error() << "external_firmware_handler lines must have exactly 3 parameters"; if (args.size() != 4 && args.size() != 5) { return Error() << "external_firmware_handler lines must have 3 or 4 parameters"; } if (std::find_if(external_firmware_handlers->begin(), external_firmware_handlers->end(), Loading @@ -117,7 +117,19 @@ Result<void> ParseExternalFirmwareHandlerLine( return ErrnoError() << "invalid handler uid'" << args[2] << "'"; } ExternalFirmwareHandler handler(std::move(args[1]), pwd->pw_uid, std::move(args[3])); gid_t gid = 0; int handler_index = 3; if (args.size() == 5) { struct group* grp = getgrnam(args[3].c_str()); if (!grp) { return ErrnoError() << "invalid handler gid '" << args[3] << "'"; } gid = grp->gr_gid; handler_index = 4; } ExternalFirmwareHandler handler(std::move(args[1]), pwd->pw_uid, gid, std::move(args[handler_index])); external_firmware_handlers->emplace_back(std::move(handler)); return {}; Loading init/ueventd_parser_test.cpp +23 −1 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ void TestExternalFirmwareHandler(const ExternalFirmwareHandler& expected, const ExternalFirmwareHandler& test) { EXPECT_EQ(expected.devpath, test.devpath) << expected.devpath; EXPECT_EQ(expected.uid, test.uid) << expected.uid; EXPECT_EQ(expected.gid, test.gid) << expected.gid; EXPECT_EQ(expected.handler_path, test.handler_path) << expected.handler_path; } Loading Loading @@ -157,39 +158,59 @@ external_firmware_handler /devices/path/firmware/something002.bin radio "/vendor external_firmware_handler /devices/path/firmware/* root "/vendor/bin/firmware_handler.sh" external_firmware_handler /devices/path/firmware/something* system "/vendor/bin/firmware_handler.sh" external_firmware_handler /devices/path/*/firmware/something*.bin radio "/vendor/bin/firmware_handler.sh" external_firmware_handler /devices/path/firmware/something003.bin system system /vendor/bin/firmware_handler.sh external_firmware_handler /devices/path/firmware/something004.bin radio radio "/vendor/bin/firmware_handler.sh --has --arguments" )"; auto external_firmware_handlers = std::vector<ExternalFirmwareHandler>{ { "devpath", AID_ROOT, AID_ROOT, "handler_path", }, { "/devices/path/firmware/something001.bin", AID_SYSTEM, AID_ROOT, "/vendor/bin/firmware_handler.sh", }, { "/devices/path/firmware/something002.bin", AID_RADIO, AID_ROOT, "/vendor/bin/firmware_handler.sh --has --arguments", }, { "/devices/path/firmware/", AID_ROOT, AID_ROOT, "/vendor/bin/firmware_handler.sh", }, { "/devices/path/firmware/something", AID_SYSTEM, AID_ROOT, "/vendor/bin/firmware_handler.sh", }, { "/devices/path/*/firmware/something*.bin", AID_RADIO, AID_ROOT, "/vendor/bin/firmware_handler.sh", }, { "/devices/path/firmware/something003.bin", AID_SYSTEM, AID_SYSTEM, "/vendor/bin/firmware_handler.sh", }, { "/devices/path/firmware/something004.bin", AID_RADIO, AID_RADIO, "/vendor/bin/firmware_handler.sh --has --arguments", }, }; TestUeventdFile(ueventd_file, {{}, {}, {}, {}, external_firmware_handlers}); Loading @@ -205,6 +226,7 @@ external_firmware_handler devpath root handler_path2 { "devpath", AID_ROOT, AID_ROOT, "handler_path", }, }; Loading Loading @@ -305,7 +327,7 @@ parallel_restorecon enabled }; auto external_firmware_handlers = std::vector<ExternalFirmwareHandler>{ {"/devices/path/firmware/firmware001.bin", AID_ROOT, "/vendor/bin/touch.sh"}, {"/devices/path/firmware/firmware001.bin", AID_ROOT, AID_ROOT, "/vendor/bin/touch.sh"}, }; size_t uevent_socket_rcvbuf_size = 6 * 1024 * 1024; Loading Loading
init/README.ueventd.md +4 −1 Original line number Diff line number Diff line Loading @@ -123,7 +123,10 @@ not present. The exact firmware file to be served can be customized by running an external program by a `external_firmware_handler` line in a ueventd.rc file. This line takes the format of external_firmware_handler <devpath> <user name to run as> <path to external program> external_firmware_handler <devpath> <user [group]> <path to external program> The handler will be run as the given user, or if a group is provided, as the given user and group. For example external_firmware_handler /devices/leds/red/firmware/coeffs.bin system /vendor/bin/led_coeffs.bin Loading
init/firmware_handler.cpp +17 −5 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include <fcntl.h> #include <fnmatch.h> #include <glob.h> #include <grp.h> #include <pwd.h> #include <signal.h> #include <stdlib.h> Loading Loading @@ -81,9 +82,9 @@ static bool IsBooting() { return access("/dev/.booting", F_OK) == 0; } ExternalFirmwareHandler::ExternalFirmwareHandler(std::string devpath, uid_t uid, ExternalFirmwareHandler::ExternalFirmwareHandler(std::string devpath, uid_t uid, gid_t gid, std::string handler_path) : devpath(std::move(devpath)), uid(uid), handler_path(std::move(handler_path)) { : devpath(std::move(devpath)), uid(uid), gid(gid), handler_path(std::move(handler_path)) { auto wildcard_position = this->devpath.find('*'); if (wildcard_position != std::string::npos) { if (wildcard_position == this->devpath.length() - 1) { Loading @@ -97,13 +98,17 @@ ExternalFirmwareHandler::ExternalFirmwareHandler(std::string devpath, uid_t uid, } } ExternalFirmwareHandler::ExternalFirmwareHandler(std::string devpath, uid_t uid, std::string handler_path) : ExternalFirmwareHandler(devpath, uid, 0, handler_path) {} FirmwareHandler::FirmwareHandler(std::vector<std::string> firmware_directories, std::vector<ExternalFirmwareHandler> external_firmware_handlers) : firmware_directories_(std::move(firmware_directories)), external_firmware_handlers_(std::move(external_firmware_handlers)) {} Result<std::string> FirmwareHandler::RunExternalHandler(const std::string& handler, uid_t uid, const Uevent& uevent) const { gid_t gid, const Uevent& uevent) const { unique_fd child_stdout; unique_fd parent_stdout; if (!Socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, &child_stdout, &parent_stdout)) { Loading Loading @@ -140,6 +145,13 @@ Result<std::string> FirmwareHandler::RunExternalHandler(const std::string& handl } c_args.emplace_back(nullptr); if (gid != 0) { if (setgid(gid) != 0) { fprintf(stderr, "setgid() failed: %s", strerror(errno)); _exit(EXIT_FAILURE); } } if (setuid(uid) != 0) { fprintf(stderr, "setuid() failed: %s", strerror(errno)); _exit(EXIT_FAILURE); Loading Loading @@ -196,8 +208,8 @@ std::string FirmwareHandler::GetFirmwarePath(const Uevent& uevent) const { << "' for devpath: '" << uevent.path << "' firmware: '" << uevent.firmware << "'"; auto result = RunExternalHandler(external_handler.handler_path, external_handler.uid, uevent); auto result = RunExternalHandler(external_handler.handler_path, external_handler.uid, external_handler.gid, uevent); if (!result.ok()) { LOG(ERROR) << "Using default firmware; External firmware handler failed: " << result.error(); Loading
init/firmware_handler.h +4 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #pragma once #include <grp.h> #include <pwd.h> #include <functional> Loading @@ -31,9 +32,11 @@ namespace init { struct ExternalFirmwareHandler { ExternalFirmwareHandler(std::string devpath, uid_t uid, std::string handler_path); ExternalFirmwareHandler(std::string devpath, uid_t uid, gid_t gid, std::string handler_path); std::string devpath; uid_t uid; gid_t gid; std::string handler_path; std::function<bool(const std::string&)> match; Loading @@ -51,7 +54,7 @@ class FirmwareHandler : public UeventHandler { friend void FirmwareTestWithExternalHandler(const std::string& test_name, bool expect_new_firmware); Result<std::string> RunExternalHandler(const std::string& handler, uid_t uid, Result<std::string> RunExternalHandler(const std::string& handler, uid_t uid, gid_t gid, const Uevent& uevent) const; std::string GetFirmwarePath(const Uevent& uevent) const; void ProcessFirmwareEvent(const std::string& root, const std::string& firmware) const; Loading
init/ueventd_parser.cpp +15 −3 Original line number Diff line number Diff line Loading @@ -101,8 +101,8 @@ Result<void> ParseFirmwareDirectoriesLine(std::vector<std::string>&& args, Result<void> ParseExternalFirmwareHandlerLine( std::vector<std::string>&& args, std::vector<ExternalFirmwareHandler>* external_firmware_handlers) { if (args.size() != 4) { return Error() << "external_firmware_handler lines must have exactly 3 parameters"; if (args.size() != 4 && args.size() != 5) { return Error() << "external_firmware_handler lines must have 3 or 4 parameters"; } if (std::find_if(external_firmware_handlers->begin(), external_firmware_handlers->end(), Loading @@ -117,7 +117,19 @@ Result<void> ParseExternalFirmwareHandlerLine( return ErrnoError() << "invalid handler uid'" << args[2] << "'"; } ExternalFirmwareHandler handler(std::move(args[1]), pwd->pw_uid, std::move(args[3])); gid_t gid = 0; int handler_index = 3; if (args.size() == 5) { struct group* grp = getgrnam(args[3].c_str()); if (!grp) { return ErrnoError() << "invalid handler gid '" << args[3] << "'"; } gid = grp->gr_gid; handler_index = 4; } ExternalFirmwareHandler handler(std::move(args[1]), pwd->pw_uid, gid, std::move(args[handler_index])); external_firmware_handlers->emplace_back(std::move(handler)); return {}; Loading
init/ueventd_parser_test.cpp +23 −1 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ void TestExternalFirmwareHandler(const ExternalFirmwareHandler& expected, const ExternalFirmwareHandler& test) { EXPECT_EQ(expected.devpath, test.devpath) << expected.devpath; EXPECT_EQ(expected.uid, test.uid) << expected.uid; EXPECT_EQ(expected.gid, test.gid) << expected.gid; EXPECT_EQ(expected.handler_path, test.handler_path) << expected.handler_path; } Loading Loading @@ -157,39 +158,59 @@ external_firmware_handler /devices/path/firmware/something002.bin radio "/vendor external_firmware_handler /devices/path/firmware/* root "/vendor/bin/firmware_handler.sh" external_firmware_handler /devices/path/firmware/something* system "/vendor/bin/firmware_handler.sh" external_firmware_handler /devices/path/*/firmware/something*.bin radio "/vendor/bin/firmware_handler.sh" external_firmware_handler /devices/path/firmware/something003.bin system system /vendor/bin/firmware_handler.sh external_firmware_handler /devices/path/firmware/something004.bin radio radio "/vendor/bin/firmware_handler.sh --has --arguments" )"; auto external_firmware_handlers = std::vector<ExternalFirmwareHandler>{ { "devpath", AID_ROOT, AID_ROOT, "handler_path", }, { "/devices/path/firmware/something001.bin", AID_SYSTEM, AID_ROOT, "/vendor/bin/firmware_handler.sh", }, { "/devices/path/firmware/something002.bin", AID_RADIO, AID_ROOT, "/vendor/bin/firmware_handler.sh --has --arguments", }, { "/devices/path/firmware/", AID_ROOT, AID_ROOT, "/vendor/bin/firmware_handler.sh", }, { "/devices/path/firmware/something", AID_SYSTEM, AID_ROOT, "/vendor/bin/firmware_handler.sh", }, { "/devices/path/*/firmware/something*.bin", AID_RADIO, AID_ROOT, "/vendor/bin/firmware_handler.sh", }, { "/devices/path/firmware/something003.bin", AID_SYSTEM, AID_SYSTEM, "/vendor/bin/firmware_handler.sh", }, { "/devices/path/firmware/something004.bin", AID_RADIO, AID_RADIO, "/vendor/bin/firmware_handler.sh --has --arguments", }, }; TestUeventdFile(ueventd_file, {{}, {}, {}, {}, external_firmware_handlers}); Loading @@ -205,6 +226,7 @@ external_firmware_handler devpath root handler_path2 { "devpath", AID_ROOT, AID_ROOT, "handler_path", }, }; Loading Loading @@ -305,7 +327,7 @@ parallel_restorecon enabled }; auto external_firmware_handlers = std::vector<ExternalFirmwareHandler>{ {"/devices/path/firmware/firmware001.bin", AID_ROOT, "/vendor/bin/touch.sh"}, {"/devices/path/firmware/firmware001.bin", AID_ROOT, AID_ROOT, "/vendor/bin/touch.sh"}, }; size_t uevent_socket_rcvbuf_size = 6 * 1024 * 1024; Loading