1#include "pedigree/kernel/process/Scheduler.h"
2#include "pedigree/kernel/process/TerminationDeferral.h"
3#include "pedigree/kernel/syscallError.h"
7#include "PosixProcess.h"
8#include "modules/system/vfs/VFS.h"
9#include "sandbox-state.h"
10#include "system-syscalls.h"
11#include "user-namespace.h"
16 if (process->getType() != Process::Posix) {
17 SYSCALL_ERROR(InvalidArgument);
22int complete(PosixProcess::CredentialStatus status) {
24 case PosixProcess::CredentialStatus::NoMemory:
25 SYSCALL_ERROR(OutOfMemory);
27 case PosixProcess::CredentialStatus::Denied:
28 SYSCALL_ERROR(NotEnoughPermissions);
30 case PosixProcess::CredentialStatus::Invalid:
31 SYSCALL_ERROR(InvalidArgument);
33 case PosixProcess::CredentialStatus::Success:
37 SYSCALL_ERROR(InvalidArgument);
40int change(PosixProcess::CredentialChange type, uint32_t first, uint32_t second = UINT32_MAX,
41 uint32_t third = UINT32_MAX) {
45 const bool group = type == PosixProcess::CredentialChange::SetGid ||
46 type == PosixProcess::CredentialChange::SetReGid ||
47 type == PosixProcess::CredentialChange::SetResGid;
48 if (!posix_global_id(group, first, first) || !posix_global_id(group, second, second) ||
49 !posix_global_id(group, third, third)) {
50 SYSCALL_ERROR(InvalidArgument);
54 first, second, third));
60 return posix_visible_id(
false, process->
getUserId());
63 return posix_visible_id(
true,
66uid_t posix_geteuid() {
67 return posix_visible_id(
70gid_t posix_getegid() {
71 return posix_visible_id(
74int posix_setuid(uid_t
id) {
75 return change(PosixProcess::CredentialChange::SetUid,
id);
77int posix_setgid(gid_t
id) {
78 return change(PosixProcess::CredentialChange::SetGid,
id);
80int posix_seteuid(uid_t
id) {
81 return posix_setresuid(UINT32_MAX,
id, UINT32_MAX);
83int posix_setegid(gid_t
id) {
84 return posix_setresgid(UINT32_MAX,
id, UINT32_MAX);
86int posix_setreuid(uid_t real, uid_t effective) {
87 return change(PosixProcess::CredentialChange::SetReUid, real, effective);
89int posix_setregid(gid_t real, gid_t effective) {
90 return change(PosixProcess::CredentialChange::SetReGid, real, effective);
92int posix_setresuid(uid_t real, uid_t effective, uid_t saved) {
93 return change(PosixProcess::CredentialChange::SetResUid, real, effective, saved);
95int posix_setresgid(gid_t real, gid_t effective, gid_t saved) {
96 return change(PosixProcess::CredentialChange::SetResGid, real, effective, saved);
99long posix_setfsuid(uid_t
id) {
105 if (!posix_global_id(
false,
id, global))
107 const uint32_t previous = process->changeFilesystemId(*task,
false, global);
109 return static_cast<long>(posix_visible_id(
false, previous));
111long posix_setfsgid(gid_t
id) {
117 if (!posix_global_id(
true,
id, global))
119 const uint32_t previous = process->changeFilesystemId(*task,
true, global);
121 return static_cast<long>(posix_visible_id(
true, previous));
124int posix_getresuid(uid_t* real, uid_t* effective, uid_t* saved) {
128 auto snapshot = process->snapshotCredentials();
129 snapshot.ruid = posix_visible_id(
false, snapshot.ruid);
130 snapshot.euid = posix_visible_id(
false, snapshot.euid);
131 snapshot.suid = posix_visible_id(
false, snapshot.suid);
135 SYSCALL_ERROR(BadAddress);
138 return complete(PosixProcess::CredentialStatus::Success);
140int posix_getresgid(gid_t* real, gid_t* effective, gid_t* saved) {
144 auto snapshot = process->snapshotCredentials();
145 snapshot.rgid = posix_visible_id(
true, snapshot.rgid);
146 snapshot.egid = posix_visible_id(
true, snapshot.egid);
147 snapshot.sgid = posix_visible_id(
true, snapshot.sgid);
151 SYSCALL_ERROR(BadAddress);
154 return complete(PosixProcess::CredentialStatus::Success);
156int posix_setgroups(
size_t count,
const gid_t* groups) {
161 if (!posix_capable(PosixCapabilities::Setgid) || (space && !space->groupsAllowed())) {
162 SYSCALL_ERROR(NotEnoughPermissions);
165 if (count > FilesystemCredentials::MaximumGroups) {
166 SYSCALL_ERROR(InvalidArgument);
169 uint32_t imported[FilesystemCredentials::MaximumGroups] = {};
171 SYSCALL_ERROR(BadAddress);
174 for (
size_t i = 0; i < count; ++i) {
175 if (!posix_global_id(
true, imported[i], imported[i])) {
176 SYSCALL_ERROR(InvalidArgument);
183int posix_getgroups(
size_t count, gid_t* groups) {
187 if (count > INT_MAX) {
188 SYSCALL_ERROR(InvalidArgument);
191 auto snapshot = process->snapshotCredentials();
192 for (
size_t i = 0; i < snapshot.groupCount; ++i)
193 snapshot.groups[i] = posix_visible_id(
true, snapshot.groups[i]);
195 if (count < snapshot.groupCount) {
196 SYSCALL_ERROR(InvalidArgument);
199 if (snapshot.groupCount &&
201 SYSCALL_ERROR(BadAddress);
206 return snapshot.groupCount;
209bool posix_exec_file_readable(
File* file) {
218struct CapabilityHeader {
222struct CapabilityData {
223 uint32_t effective, permitted, inheritable;
225int capabilityHeader(
void* user, CapabilityHeader& header) {
227 SYSCALL_ERROR(BadAddress);
230 if (header.version == 0x19980330)
232 if (header.version == 0x20071026 || header.version == 0x20080522)
234 const uint32_t version = 0x20080522;
236 SYSCALL_ERROR(BadAddress);
238 SYSCALL_ERROR(InvalidArgument);
244int posix_capget(
void* hdrp,
void* datap) {
245 CapabilityHeader header = {};
246 const int words = capabilityHeader(hdrp, header);
250 if (header.pid < 0) {
251 SYSCALL_ERROR(InvalidArgument);
256 if (header.pid &&
static_cast<size_t>(header.pid) !=
260 SYSCALL_ERROR(NoSuchProcess);
263 selected = target.get();
265 const auto credentials = posix_task_credentials(*selected);
266 CapabilityData data[2] = {};
267 for (
int i = 0; i < words; ++i) {
268 data[i].effective = credentials.effective >> (32 * i);
269 data[i].permitted = credentials.permitted >> (32 * i);
270 data[i].inheritable = credentials.inheritable >> (32 * i);
273 SYSCALL_ERROR(BadAddress);
280int posix_capset(
void* hdrp,
const void* datap) {
282 CapabilityHeader header = {};
283 const int words = capabilityHeader(hdrp, header);
288 (header.pid < 0 ||
static_cast<size_t>(header.pid) !=
290 SYSCALL_ERROR(NotEnoughPermissions);
293 CapabilityData data[2] = {};
295 SYSCALL_ERROR(BadAddress);
298 auto value = posix_task_credentials(task);
299 const uint64_t effective = (uint64_t(data[1].effective) << 32) | data[0].effective;
300 const uint64_t permitted = (uint64_t(data[1].permitted) << 32) | data[0].permitted;
301 const uint64_t inheritable = (uint64_t(data[1].inheritable) << 32) | data[0].inheritable;
302 const bool setpcap = value.effective & (uint64_t(1) << PosixCapabilities::Setpcap);
303 if (((effective | permitted | inheritable) & ~PosixCapabilities::All) ||
304 (effective & ~permitted) || (permitted & ~value.permitted) ||
305 (inheritable & ~(value.inheritable | value.bounding)) ||
306 (!setpcap && (inheritable & ~(value.inheritable | value.permitted)))) {
307 SYSCALL_ERROR(NotEnoughPermissions);
310 value.permitted = permitted;
311 value.effective = effective;
312 value.inheritable = inheritable;
313 value.ambient &= permitted & inheritable;
316 SYSCALL_ERROR(OutOfMemory);
319 if (!posix_sandbox_set_credentials(task, next))
static bool copyFromUser(void *destination, const void *source, size_t count, size_t elementSize=1)
static bool copyToUser(void *destination, const void *source, size_t count, size_t elementSize=1)
virtual int64_t getUserId() const
static ProcessorInformation & information()
static Scheduler & instance()
static SharedPointer< T > tryAllocate(Args...)
void setErrno(size_t err)
Process * getParent() const
size_t getUserspaceTaskId(const UserspacePidNamespace *space=nullptr) const
static bool checkAccess(File *pFile, bool bRead, bool bWrite, bool bExecute)