The Pedigree Project 0.1
credential-state.h
1#ifndef POSIX_CREDENTIAL_STATE_H
2#define POSIX_CREDENTIAL_STATE_H
3#include "pedigree/kernel/process/FilesystemCredentials.h"
4
5namespace PosixCredentials {
6struct Snapshot {
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;
12 bool dumpable = true;
13};
14enum class Change { SetUid, SetGid, SetReUid, SetReGid, SetResUid, SetResGid };
15enum class Status { Success, Invalid, Denied };
16
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) {
19 const bool group =
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;
27 next = old;
28 nextFs = oldFs;
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;
32 };
33 if (single) {
34 if (first == UINT32_MAX)
35 return Status::Invalid;
36 if (privileged)
37 r = s = first;
38 else if (first != real && first != saved)
39 return Status::Denied;
40 e = first;
41 } else if (pair) {
42 if (first != UINT32_MAX && first != real && first != effective && !privileged)
43 return Status::Denied;
44 if (!allowed(second))
45 return Status::Denied;
46 if (first != UINT32_MAX)
47 r = first;
48 if (second != UINT32_MAX)
49 e = second;
50 if (first != UINT32_MAX || (second != UINT32_MAX && second != real))
51 s = e;
52 } else {
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)
60 r = first;
61 if (second != UINT32_MAX)
62 e = second;
63 if (third != UINT32_MAX)
64 s = third;
65 }
66 nextFs = e;
67 if (group) {
68 next.rgid = r;
69 next.egid = e;
70 next.sgid = s;
71 } else {
72 next.ruid = r;
73 next.euid = e;
74 next.suid = s;
75 }
76 if (e != effective || nextFs != oldFs)
77 next.dumpable = false;
78 if (r != real || e != effective || s != saved || nextFs != oldFs)
79 ++next.generation;
80 return Status::Success;
81}
82} // namespace PosixCredentials
83#endif