1#include "pedigree/kernel/LockGuard.h"
2#include "pedigree/kernel/processor/Processor.h"
4#include "PosixProcess.h"
5#include "modules/system/users/Group.h"
6#include "modules/system/users/User.h"
8#include "user-namespace.h"
15 subsystem->traceContext().taskToken(task, token);
30 authority = posix_task_credentials(*task);
34 out.uid = m_Credentials.ruid;
35 out.gid = m_Credentials.rgid;
36 out.groupCount = m_Credentials.groupCount;
37 for (
size_t i = 0; i < out.groupCount; ++i)
38 out.groups[i] = m_Credentials.groups[i];
40 out.enforceCapabilities =
true;
41 if (!out.uid && !authority.userNamespace) {
42 out.capabilities = authority.permitted;
47bool PosixProcess::snapshotFilesystemCredentials(
const Thread* task,
51 authority = posix_task_credentials(*
const_cast<Thread*
>(task));
57 out.uid = m_Credentials.euid;
58 out.gid = m_Credentials.egid;
60 loadFilesystemIds(*task, out.uid, out.gid);
61 out.groupCount = m_Credentials.groupCount;
62 for (
size_t i = 0; i < out.groupCount; ++i)
63 out.groups[i] = m_Credentials.groups[i];
65 out.enforceCapabilities =
true;
66 if (!authority.userNamespace) {
67 out.capabilities = authority.effective;
72PosixProcess::CredentialStatus PosixProcess::changeCredentials(
Thread& task,
73 CredentialChange change,
74 uint32_t first, uint32_t second,
78 const bool group = change == CredentialChange::SetGid || change == CredentialChange::SetReGid ||
79 change == CredentialChange::SetResGid;
80 const bool privileged =
81 posix_capable(group ? PosixCapabilities::Setgid : PosixCapabilities::Setuid);
82 auto space = posix_user_namespace(task);
84 if (space && !space->toGlobal(
false, 0, root)) {
89 return CredentialStatus::Invalid;
90 uint32_t fsuid = m_Credentials.euid, fsgid = m_Credentials.egid;
91 loadFilesystemIds(task, fsuid, fsgid);
92 CredentialSnapshot next;
94 const auto status = PosixCredentials::prepare(m_Credentials, change, first, second, third,
95 group ? fsgid : fsuid, next, nextFs, privileged);
96 if (status != CredentialStatus::Success)
99 !posix_capabilities_uid_change(task, m_Credentials.ruid, m_Credentials.euid,
100 m_Credentials.suid, next.ruid, next.euid, next.suid, root)) {
101 return CredentialStatus::NoMemory;
103 if (token && (m_Credentials.euid != next.euid || m_Credentials.egid != next.egid ||
104 (group ? fsgid : fsuid) != nextFs)) {
105 token->clearParentDeathSignal();
107 m_Credentials = next;
108 publishCredentialReadCache();
109 publishFilesystemIds(task, group ? fsuid : nextFs, group ? nextFs : fsgid);
113PosixProcess::CredentialStatus PosixProcess::replaceGroups(
Thread& task,
const uint32_t* groups,
115 if (count > FilesystemCredentials::MaximumGroups || (count && !groups))
116 return CredentialStatus::Invalid;
117 uint32_t ordered[FilesystemCredentials::MaximumGroups] = {};
118 for (
size_t i = 0; i < count; ++i) {
119 if (groups[i] == UINT32_MAX)
120 return CredentialStatus::Invalid;
122 while (position && ordered[position - 1] > groups[i]) {
123 ordered[position] = ordered[position - 1];
126 ordered[position] = groups[i];
129 const bool privileged = posix_capable(PosixCapabilities::Setgid);
132 return CredentialStatus::Invalid;
134 return CredentialStatus::Denied;
135 bool changed = count != m_Credentials.groupCount;
136 for (
size_t i = 0; i < count; ++i) {
137 changed |= m_Credentials.groups[i] != ordered[i];
138 m_Credentials.groups[i] = ordered[i];
140 m_Credentials.groupCount = count;
142 ++m_Credentials.generation;
143 return CredentialStatus::Success;
146uint32_t PosixProcess::changeFilesystemId(
Thread& task,
bool group, uint32_t requested) {
149 const bool privileged =
150 posix_capable(group ? PosixCapabilities::Setgid : PosixCapabilities::Setuid);
151 auto space = posix_user_namespace(task);
153 if (space && !space->toGlobal(
false, 0, root))
156 uint32_t uid = m_Credentials.euid, gid = m_Credentials.egid;
158 return group ? gid : uid;
159 loadFilesystemIds(task, uid, gid);
160 const uint32_t old = group ? gid : uid;
161 const uint32_t real = group ? m_Credentials.rgid : m_Credentials.ruid;
162 const uint32_t effective = group ? m_Credentials.egid : m_Credentials.euid;
163 const uint32_t saved = group ? m_Credentials.sgid : m_Credentials.suid;
164 if (requested != UINT32_MAX && requested != old &&
165 (privileged || requested == real || requested == effective || requested == saved)) {
166 if (!group && !posix_capabilities_fsuid_change(task, old, requested, root))
168 publishFilesystemIds(task, group ? uid : requested, group ? requested : gid);
170 token->clearParentDeathSignal();
172 m_Credentials.dumpable =
false;
173 ++m_Credentials.generation;
178void PosixProcess::setDumpable(
bool dumpable) {
181 if (m_Credentials.dumpable != dumpable) {
182 m_Credentials.dumpable = dumpable;
183 ++m_Credentials.generation;
187void PosixProcess::commitExecCredentials(
Thread& task,
bool readable) {
191 uint32_t fsuid = m_Credentials.euid, fsgid = m_Credentials.egid;
192 loadFilesystemIds(task, fsuid, fsgid);
193 if (token && (fsuid != m_Credentials.euid || fsgid != m_Credentials.egid)) {
194 token->clearParentDeathSignal();
196 m_Credentials.suid = m_Credentials.euid;
197 m_Credentials.sgid = m_Credentials.egid;
198 publishFilesystemIds(task, m_Credentials.euid, m_Credentials.egid);
199 m_Credentials.dumpable = readable && m_Credentials.ruid == m_Credentials.euid &&
200 m_Credentials.rgid == m_Credentials.egid;
201 ++m_Credentials.generation;
204bool PosixProcess::installUserIdentity(
User* user,
Group* group,
const uint32_t* groups,
206 if (!user || !group || user->
getId() >= UINT32_MAX || group->
getId() >= UINT32_MAX ||
207 count > FilesystemCredentials::MaximumGroups || (count && !groups))
209 for (
size_t i = 0; i < count; ++i)
210 if (groups[i] == UINT32_MAX)
215 CredentialSnapshot next;
216 next.ruid = next.euid = next.suid = user->
getId();
217 next.rgid = next.egid = next.sgid = group->
getId();
218 next.groupCount = count;
219 for (
size_t i = 0; i < count; ++i)
220 next.groups[i] = groups[i];
221 next.generation = m_Credentials.generation + 1;
222 next.dumpable =
false;
223 if (current && current->
getParent() ==
this &&
224 !posix_capabilities_uid_change(*current, m_Credentials.ruid, m_Credentials.euid,
225 m_Credentials.suid, next.ruid, next.euid, next.suid, 0)) {
228 m_Credentials = next;
229 publishCredentialReadCache();
230 publishAccountIdentity(user, group);
231 if (current && current->
getParent() ==
this)
232 publishFilesystemIds(*current, next.euid, next.egid);
236int64_t PosixProcess::getGroupId()
const {
237 return snapshotCredentials().rgid;
239int64_t PosixProcess::getEffectiveUserId()
const {
240 return snapshotCredentials().euid;
242int64_t PosixProcess::getEffectiveGroupId()
const {
243 return snapshotCredentials().egid;
245int64_t PosixProcess::getSavedUserId()
const {
246 return snapshotCredentials().suid;
248int64_t PosixProcess::getSavedGroupId()
const {
249 return snapshotCredentials().sgid;
251void PosixProcess::getSupplementalGroupIds(
Vector<int64_t>& groups)
const {
252 const auto snapshot = snapshotCredentials();
253 for (
size_t i = 0; i < snapshot.groupCount; ++i)
254 groups.
pushBack(snapshot.groups[i]);
259void PosixProcess::setTrustedIdentity(uint32_t CredentialSnapshot::* field, int64_t id) {
260 if (
id < 0 ||
static_cast<uint64_t
>(
id) >= UINT32_MAX)
264 m_Credentials.*field =
static_cast<uint32_t
>(id);
265 publishCredentialReadCache();
266 m_Credentials.dumpable =
false;
267 ++m_Credentials.generation;
270 publishFilesystemIds(*task, m_Credentials.euid, m_Credentials.egid);
272void PosixProcess::setUserId(int64_t
id) {
273 setTrustedIdentity(&CredentialSnapshot::ruid,
id);
275void PosixProcess::setGroupId(int64_t
id) {
276 setTrustedIdentity(&CredentialSnapshot::rgid,
id);
278void PosixProcess::setEffectiveUserId(int64_t
id) {
279 setTrustedIdentity(&CredentialSnapshot::euid,
id);
281void PosixProcess::setEffectiveGroupId(int64_t
id) {
282 setTrustedIdentity(&CredentialSnapshot::egid,
id);
284void PosixProcess::setSavedUserId(int64_t
id) {
285 setTrustedIdentity(&CredentialSnapshot::suid,
id);
287void PosixProcess::setSavedGroupId(int64_t
id) {
288 setTrustedIdentity(&CredentialSnapshot::sgid,
id);
291void PosixProcess::setSupplementalGroupIds(
const Vector<int64_t>& groups) {
292 if (groups.
count() > FilesystemCredentials::MaximumGroups)
294 for (int64_t
id : groups)
295 if (id < 0 || static_cast<uint64_t>(id) >= UINT32_MAX)
299 m_Credentials.groupCount = groups.
count();
300 for (
size_t i = 0; i < groups.
count(); ++i)
301 m_Credentials.groups[i] = groups[i];
302 ++m_Credentials.generation;
Memory-mapped file interface.
static MemoryMapManager & instance()
static ProcessorInformation & information()
Process * getParent() const
A vector / dynamic array.
void pushBack(const T &value)