2#include "pedigree/kernel/process/TerminationDeferral.h"
3#include "pedigree/kernel/process/Thread.h"
4#include "pedigree/kernel/processor/Processor.h"
5#include "pedigree/kernel/processor/ProcessorInformation.h"
6#include "pedigree/kernel/syscallError.h"
8#include "sandbox-state.h"
9#include "user-namespace.h"
12constexpr uint32_t NoRoot = 1, NoSetuidFixup = 4, KeepCaps = 16, KeepCapsLocked = 32;
13constexpr uint32_t NoAmbientRaise = 64;
18 SYSCALL_ERROR(InvalidArgument);
22 SYSCALL_ERROR(NotEnoughPermissions);
28 SYSCALL_ERROR(OutOfMemory);
31 return posix_sandbox_set_credentials(task, next);
35int posix_capability_prctl(
int option,
unsigned long arg2,
unsigned long arg3,
unsigned long arg4,
38 auto next = posix_task_credentials(current());
39 if (arg4 || arg5 || (option != 47 && arg3)) {
49 result = bool(next.secureBits & KeepCaps);
55 if (next.secureBits & KeepCapsLocked) {
58 next.secureBits = (next.secureBits & ~KeepCaps) | (arg2 ? KeepCaps : 0);
62 if (arg2 > PosixCapabilities::Last) {
65 result = bool(next.bounding & (uint64_t(1) << arg2));
68 if (arg2 > PosixCapabilities::Last) {
71 if (!(next.effective & (uint64_t(1) << PosixCapabilities::Setpcap))) {
74 next.bounding &= ~(uint64_t(1) << arg2);
81 result = next.secureBits;
87 if (!(next.effective & (uint64_t(1) << PosixCapabilities::Setpcap))) {
90 for (
unsigned bit = 1; bit < 8; bit += 2) {
91 if ((next.secureBits & (1U << bit)) && ((next.secureBits ^ arg2) & (3U << (bit - 1)))) {
95 next.secureBits = arg2;
106 if (arg3 > PosixCapabilities::Last) {
109 const uint64_t bit = uint64_t(1) << arg3;
112 result = bool(next.ambient & bit);
115 if ((next.secureBits & NoAmbientRaise) || !(next.permitted & bit) ||
116 !(next.inheritable & bit)) {
123 next.ambient &= ~bit;
134 if (changed && !publish(current(), next)) {
137 current().setErrno(0);
141bool posix_capabilities_exec(
Thread& task, uint32_t globalUid) {
143 auto next = posix_task_credentials(task);
144 const uint64_t oldPermitted = next.permitted;
146 const bool rootMapped = !next.userNamespace || next.userNamespace->toGlobal(
false, 0, root);
147 if (!(next.secureBits & NoRoot) && rootMapped && globalUid == root) {
148 next.permitted = next.inheritable | next.bounding;
149 if (posix_no_new_privs()) {
150 next.permitted &= oldPermitted;
152 next.effective = next.permitted;
155 next.permitted = next.effective = next.ambient;
157 next.secureBits &= ~KeepCaps;
158 return publish(task, next);
161bool posix_capabilities_uid_change(
Thread& task, uint32_t oldReal, uint32_t oldEffective,
162 uint32_t oldSaved, uint32_t newReal, uint32_t newEffective,
163 uint32_t newSaved, uint32_t namespaceRoot) {
164 if (oldReal == newReal && oldEffective == newEffective && oldSaved == newSaved) {
167 auto stored = posix_sandbox_credentials(task);
171 }
else if (!oldEffective) {
172 next.permitted = next.effective = PosixCapabilities::All;
174 if (next.secureBits & NoSetuidFixup) {
177 if ((oldReal == namespaceRoot || oldEffective == namespaceRoot || oldSaved == namespaceRoot) &&
178 newReal != namespaceRoot && newEffective != namespaceRoot && newSaved != namespaceRoot) {
179 if (!(next.secureBits & KeepCaps)) {
184 if (oldEffective == namespaceRoot && newEffective != namespaceRoot) {
186 }
else if (oldEffective != namespaceRoot && newEffective == namespaceRoot) {
187 next.effective = next.permitted;
189 return publish(task, next);
192bool posix_capabilities_fsuid_change(
Thread& task, uint32_t oldUid, uint32_t newUid,
193 uint32_t namespaceRoot) {
194 if (oldUid == newUid) {
197 auto stored = posix_sandbox_credentials(task);
201 }
else if (!oldUid) {
202 next.permitted = next.effective = PosixCapabilities::All;
204 if (next.secureBits & NoSetuidFixup) {
207 constexpr uint64_t filesystemCaps = (uint64_t(1) << 0) | (uint64_t(1) << 1) | (uint64_t(1) << 2) |
208 (uint64_t(1) << 3) | (uint64_t(1) << 4) | (uint64_t(1) << 9) |
210 if (oldUid == namespaceRoot && newUid != namespaceRoot) {
211 next.effective &= ~filesystemCaps;
212 }
else if (oldUid != namespaceRoot && newUid == namespaceRoot) {
213 next.effective |= next.permitted & filesystemCaps;
217 return publish(task, next);
static ProcessorInformation & information()
static SharedPointer< T > tryAllocate(Args...)