1#ifndef POSIX_CREDENTIAL_STATE_H
2#define POSIX_CREDENTIAL_STATE_H
3#include "pedigree/kernel/process/FilesystemCredentials.h"
5namespace PosixCredentials {
7 uint32_t ruid = 0, euid = 0, suid = 0;
8 uint32_t rgid = 0, egid = 0, sgid = 0;
9 uint32_t groups[FilesystemCredentials::MaximumGroups] = {};
10 size_t groupCount = 0;
11 uint64_t generation = 0;
14enum class Change { SetUid, SetGid, SetReUid, SetReGid, SetResUid, SetResGid };
15enum class Status { Success, Invalid, Denied };
17inline Status prepare(
const Snapshot& old, Change change, uint32_t first, uint32_t second,
18 uint32_t third, uint32_t oldFs, Snapshot& next, uint32_t& nextFs) {
20 change == Change::SetGid || change == Change::SetReGid || change == Change::SetResGid;
21 const bool single = change == Change::SetUid || change == Change::SetGid;
22 const bool pair = change == Change::SetReUid || change == Change::SetReGid;
23 const bool privileged = old.euid == 0;
24 const uint32_t real = group ? old.rgid : old.ruid;
25 const uint32_t effective = group ? old.egid : old.euid;
26 const uint32_t saved = group ? old.sgid : old.suid;
29 uint32_t r = real, e = effective, s = saved;
30 const auto allowed = [&](uint32_t id) {
31 return id == UINT32_MAX ||
id == real ||
id == effective ||
id == saved || privileged;
34 if (first == UINT32_MAX)
35 return Status::Invalid;
38 else if (first != real && first != saved)
39 return Status::Denied;
42 if (first != UINT32_MAX && first != real && first != effective && !privileged)
43 return Status::Denied;
45 return Status::Denied;
46 if (first != UINT32_MAX)
48 if (second != UINT32_MAX)
50 if (first != UINT32_MAX || (second != UINT32_MAX && second != real))
53 if ((first == UINT32_MAX || first == real) &&
54 (second == UINT32_MAX || (second == effective && second == oldFs)) &&
55 (third == UINT32_MAX || third == saved))
56 return Status::Success;
57 if (!allowed(first) || !allowed(second) || !allowed(third))
58 return Status::Denied;
59 if (first != UINT32_MAX)
61 if (second != UINT32_MAX)
63 if (third != UINT32_MAX)
76 if (e != effective || nextFs != oldFs)
77 next.dumpable =
false;
78 if (r != real || e != effective || s != saved || nextFs != oldFs)
80 return Status::Success;