1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 15:48:12 +00:00

su: Use setgroups() to switch over to the target user's extra GIDs

Before this, su would leave the process's extra GIDs untouched,
simply inheriting them from whoever spawned su.

Now we grab the target user's groups from /etc/group and setgroups().
This commit is contained in:
Andreas Kling 2020-01-04 13:48:55 +01:00
parent 5abc30e057
commit c663b1034a

View file

@ -1,3 +1,4 @@
#include <AK/Vector.h>
#include <alloca.h>
#include <grp.h>
#include <pwd.h>
@ -10,8 +11,9 @@ int main(int argc, char** argv)
{
uid_t uid = 0;
gid_t gid = 0;
struct passwd* pwd = nullptr;
if (argc > 1) {
auto* pwd = getpwnam(argv[1]);
pwd = getpwnam(argv[1]);
if (!pwd) {
fprintf(stderr, "No such user: %s\n", argv[1]);
return 1;
@ -19,7 +21,30 @@ int main(int argc, char** argv)
uid = pwd->pw_uid;
gid = pwd->pw_gid;
}
int rc = setgid(uid);
if (!pwd)
pwd = getpwuid(0);
if (!pwd) {
fprintf(stderr, "No passwd entry.\n");
return 1;
}
Vector<gid_t> extra_gids;
for (auto* group = getgrent(); group; group = getgrent()) {
for (size_t i = 0; group->gr_mem[i]; ++i) {
if (!strcmp(pwd->pw_name, group->gr_mem[i]))
extra_gids.append(group->gr_gid);
}
}
endgrent();
int rc = setgroups(extra_gids.size(), extra_gids.data());
if (rc < 0) {
perror("setgroups");
return 1;
}
rc = setgid(uid);
if (rc < 0) {
perror("setgid");
return 1;