diff --git a/Kernel/API/Syscall.h b/Kernel/API/Syscall.h index 06b38e491df..a37696aea0e 100644 --- a/Kernel/API/Syscall.h +++ b/Kernel/API/Syscall.h @@ -163,6 +163,7 @@ enum class NeedsBigProcessLock { S(sethostname, NeedsBigProcessLock::No) \ S(setkeymap, NeedsBigProcessLock::No) \ S(setpgid, NeedsBigProcessLock::Yes) \ + S(setregid, NeedsBigProcessLock::No) \ S(setresgid, NeedsBigProcessLock::No) \ S(setresuid, NeedsBigProcessLock::No) \ S(setreuid, NeedsBigProcessLock::No) \ diff --git a/Kernel/Process.h b/Kernel/Process.h index d7d91c3986f..7db511e1b60 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -369,6 +369,7 @@ public: ErrorOr sys$setgid(GroupID); ErrorOr sys$setreuid(UserID, UserID); ErrorOr sys$setresuid(UserID, UserID, UserID); + ErrorOr sys$setregid(GroupID, GroupID); ErrorOr sys$setresgid(GroupID, GroupID, GroupID); ErrorOr sys$alarm(unsigned seconds); ErrorOr sys$faccessat(Userspace); diff --git a/Kernel/Syscalls/setuid.cpp b/Kernel/Syscalls/setuid.cpp index 5193a4b77b8..71070bdacf9 100644 --- a/Kernel/Syscalls/setuid.cpp +++ b/Kernel/Syscalls/setuid.cpp @@ -206,6 +206,40 @@ ErrorOr Process::sys$setresuid(UserID new_ruid, UserID new_euid, UserID }); } +ErrorOr Process::sys$setregid(GroupID new_rgid, GroupID new_egid) +{ + VERIFY_NO_PROCESS_BIG_LOCK(this); + TRY(require_promise(Pledge::id)); + + return with_mutable_protected_data([&](auto& protected_data) -> ErrorOr { + auto credentials = this->credentials(); + + if (new_rgid == (gid_t)-1) + new_rgid = credentials->gid(); + if (new_egid == (gid_t)-1) + new_egid = credentials->egid(); + + auto ok = [&credentials](GroupID id) { return id == credentials->gid() || id == credentials->egid() || id == credentials->sgid(); }; + if (!ok(new_rgid) || !ok(new_egid)) + return EPERM; + + auto new_credentials = TRY(Credentials::create( + credentials->uid(), + new_rgid, + credentials->euid(), + new_egid, + credentials->suid(), + credentials->sgid(), + credentials->extra_gids())); + + if (credentials->egid() != new_egid) + protected_data.dumpable = false; + + protected_data.credentials = move(new_credentials); + return 0; + }); +} + ErrorOr Process::sys$setresgid(GroupID new_rgid, GroupID new_egid, GroupID new_sgid) { VERIFY_NO_PROCESS_BIG_LOCK(this); diff --git a/Userland/Libraries/LibC/unistd.cpp b/Userland/Libraries/LibC/unistd.cpp index 54c8a51361e..108b3a2be1a 100644 --- a/Userland/Libraries/LibC/unistd.cpp +++ b/Userland/Libraries/LibC/unistd.cpp @@ -790,6 +790,12 @@ int setresuid(uid_t ruid, uid_t euid, uid_t suid) __RETURN_WITH_ERRNO(rc, rc, -1); } +int setregid(gid_t rgid, gid_t egid) +{ + int rc = syscall(SC_setresgid, rgid, egid); + __RETURN_WITH_ERRNO(rc, rc, -1); +} + int setresgid(gid_t rgid, gid_t egid, gid_t sgid) { int rc = syscall(SC_setresgid, rgid, egid, sgid); diff --git a/Userland/Libraries/LibC/unistd.h b/Userland/Libraries/LibC/unistd.h index a7c104b2cb5..e01e9ef6652 100644 --- a/Userland/Libraries/LibC/unistd.h +++ b/Userland/Libraries/LibC/unistd.h @@ -71,6 +71,7 @@ int setuid(uid_t); int setgid(gid_t); int setreuid(uid_t, uid_t); int setresuid(uid_t, uid_t, uid_t); +int setregid(gid_t, gid_t); int setresgid(gid_t, gid_t, gid_t); pid_t tcgetpgrp(int fd); int tcsetpgrp(int fd, pid_t pgid);