mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-29 11:00:29 +00:00
c663b1034a
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().
60 lines
1.3 KiB
C++
60 lines
1.3 KiB
C++
#include <AK/Vector.h>
|
|
#include <alloca.h>
|
|
#include <grp.h>
|
|
#include <pwd.h>
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
|
|
extern "C" int main(int, char**);
|
|
|
|
int main(int argc, char** argv)
|
|
{
|
|
uid_t uid = 0;
|
|
gid_t gid = 0;
|
|
struct passwd* pwd = nullptr;
|
|
if (argc > 1) {
|
|
pwd = getpwnam(argv[1]);
|
|
if (!pwd) {
|
|
fprintf(stderr, "No such user: %s\n", argv[1]);
|
|
return 1;
|
|
}
|
|
uid = pwd->pw_uid;
|
|
gid = pwd->pw_gid;
|
|
}
|
|
|
|
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;
|
|
}
|
|
rc = setuid(gid);
|
|
if (rc < 0) {
|
|
perror("setuid");
|
|
return 1;
|
|
}
|
|
rc = execl("/bin/sh", "sh", nullptr);
|
|
perror("execl");
|
|
return 1;
|
|
}
|