diff --git a/Userland/su.cpp b/Userland/su.cpp index 8f7a10aa82..f600179b78 100644 --- a/Userland/su.cpp +++ b/Userland/su.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -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 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;