aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Stephen Bennett <spb@exherbo.org> 2010-04-17 16:42:11 +0100
committerAvatar Stephen Bennett <spb@exherbo.org> 2010-04-17 21:43:25 +0100
commitf54a64cc365a018468db7ded009351ec8396ead7 (patch)
tree41bbaf17890d5f8683f654353c6242a414aa4fe2
parentafbe428be49be19081a1cfbcc3ad48472222657a (diff)
downloadpaludis-f54a64cc365a018468db7ded009351ec8396ead7.tar.gz
paludis-f54a64cc365a018468db7ded009351ec8396ead7.tar.xz
When given a uid and gid under which to run a command, also apply the supplemental groups for that uid
-rw-r--r--paludis/util/system.cc47
1 files changed, 40 insertions, 7 deletions
diff --git a/paludis/util/system.cc b/paludis/util/system.cc
index 3898955..2c11e57 100644
--- a/paludis/util/system.cc
+++ b/paludis/util/system.cc
@@ -43,6 +43,7 @@
#include <signal.h>
#include <fcntl.h>
#include <map>
+#include <vector>
#include <iostream>
#include <cstring>
#include "config.h"
@@ -471,21 +472,53 @@ namespace
{
std::string command(cmd.command());
- if (cmd.gid() && *cmd.gid() != getgid())
+ // If we're not changing uid or gid, do nothing.
+ if ((!cmd.uid() || *cmd.uid() == getuid()) &&
+ (!cmd.gid() || *cmd.gid() == getgid()))
{
- gid_t g(*cmd.gid());
+ return;
+ }
- if (0 != ::setgid(*cmd.gid()))
- std::cerr << "setgid(" << *cmd.uid() << ") failed for exec of '" << command << "': "
- << strerror(errno) << std::endl;
- else if (0 != ::setgroups(1, &g))
- std::cerr << "setgroups failed for exec of '" << command << "': " << strerror(errno) << std::endl;
+ int ngids(0);
+ std::vector<gid_t> gids;
+ gid_t gid = cmd.gid() ? *cmd.gid() : getgid();
+
+ if (cmd.uid())
+ {
+ // Fetch the list of supplemental groups for the given uid
+ struct passwd *pwd_entry(getpwuid(*cmd.uid()));
+ getgrouplist(pwd_entry->pw_name, gid, 0, &ngids);
+ gids.resize(ngids);
+ if (-1 == getgrouplist(pwd_entry->pw_name, gid, &gids[0], &ngids))
+ {
+ std::cerr << "getgrouplist failed. Did something change group?" << std::endl;
+ _exit(1);
+ }
+ }
+ else
+ {
+ gids.push_back(gid);
+ }
+
+ if (0 != ::setgid(gid))
+ {
+ std::cerr << "setgid(" << gid << ") failed for exec of '" << command << "': "
+ << strerror(errno) << std::endl;
+ _exit(1);
+ }
+ if (0 != ::setgroups(gids.size(), &gids[0]))
+ {
+ std::cerr << "setgroups failed for exec of '" << command << "': " << strerror(errno) << std::endl;
+ _exit(1);
}
if (cmd.uid() && *cmd.uid() != getuid())
if (0 != ::setuid(*cmd.uid()))
+ {
std::cerr << "setuid(" << *cmd.uid() << ") failed for exec of '" << command << "': "
<< strerror(errno) << std::endl;
+ _exit(1);
+ }
}
}