Support multiple users interacting with shm with starterd
The permission restrictions of signals make it hard to have AOS
applications started as arbitrary users communicate. Instead, make
starter run as the provided --user with the effective UID that it
started with. This makes shmem end up with all the right permissions so
everything can communicate.
Change-Id: I3c7fbfe8a73e7341ca32c010da1c38b5ba787523
Signed-off-by: Austin Schuh <austin.linux@gmail.com>
diff --git a/aos/starter/starterd_lib.cc b/aos/starter/starterd_lib.cc
index edf61b9..2c9d6aa 100644
--- a/aos/starter/starterd_lib.cc
+++ b/aos/starter/starterd_lib.cc
@@ -23,6 +23,9 @@
args_(1),
user_(application->has_user() ? FindUid(application->user()->c_str())
: std::nullopt),
+ group_(application->has_user()
+ ? FindPrimaryGidForUser(application->user()->c_str())
+ : std::nullopt),
autostart_(application->autostart()),
event_loop_(event_loop),
start_timer_(event_loop_->AddTimer([this] {
@@ -82,6 +85,14 @@
PLOG(FATAL) << "Could not set PR_SET_PDEATHSIG to SIGKILL";
}
+ if (group_) {
+ if (setgid(*group_) == -1) {
+ write_pipe_.Write(
+ static_cast<uint32_t>(aos::starter::LastStopReason::SET_GRP_ERR));
+ PLOG(FATAL) << "Could not set group for " << name_ << " to " << *group_;
+ }
+ }
+
if (user_) {
if (setuid(*user_) == -1) {
write_pipe_.Write(
@@ -93,7 +104,7 @@
// argv[0] should be the program name
args_.insert(args_.begin(), path_.data());
- execv(path_.c_str(), args_.data());
+ execvp(path_.c_str(), args_.data());
// If we got here, something went wrong
write_pipe_.Write(
@@ -172,6 +183,7 @@
}
std::optional<uid_t> Application::FindUid(const char *name) {
+ // TODO(austin): Use the reentrant version. This should be safe.
struct passwd *user_data = getpwnam(name);
if (user_data != nullptr) {
return user_data->pw_uid;
@@ -181,6 +193,17 @@
}
}
+std::optional<gid_t> Application::FindPrimaryGidForUser(const char *name) {
+ // TODO(austin): Use the reentrant version. This should be safe.
+ struct passwd *user_data = getpwnam(name);
+ if (user_data != nullptr) {
+ return user_data->pw_gid;
+ } else {
+ LOG(FATAL) << "Could not find user " << name;
+ return std::nullopt;
+ }
+}
+
flatbuffers::Offset<aos::starter::ApplicationStatus>
Application::PopulateStatus(flatbuffers::FlatBufferBuilder *builder) {
CHECK_NOTNULL(builder);