Merge "ueventd: Run external handler as non-root group" am: 5123a3eafc
Original change: https://android-review.googlesource.com/c/platform/system/core/+/1707926 Change-Id: Ia53c37cdfda92064fcf127793f77a727a0a9a59e
This commit is contained in:
commit
7db6b64f2d
5 changed files with 63 additions and 11 deletions
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
@ -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) {
|
||||
|
@ -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)) {
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <grp.h>
|
||||
#include <pwd.h>
|
||||
|
||||
#include <functional>
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
|
|
@ -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(),
|
||||
|
@ -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 {};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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});
|
||||
|
@ -205,6 +226,7 @@ external_firmware_handler devpath root handler_path2
|
|||
{
|
||||
"devpath",
|
||||
AID_ROOT,
|
||||
AID_ROOT,
|
||||
"handler_path",
|
||||
},
|
||||
};
|
||||
|
@ -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…
Reference in a new issue