2#include "pedigree/kernel/process/Process.h"
3#include "pedigree/kernel/process/TerminationDeferral.h"
4#include "pedigree/kernel/process/Thread.h"
5#include "pedigree/kernel/processor/Processor.h"
6#include "pedigree/kernel/processor/ProcessorInformation.h"
7#include "pedigree/kernel/processor/SyscallManager.h"
8#include "pedigree/kernel/syscallError.h"
9#include "pedigree/kernel/utilities/Pointers.h"
13#include "PosixSubsystem.h"
14#include "ipc-namespace.h"
16#include "network-namespace.h"
17#include "sandbox-state.h"
18#include "seccomp-filter.h"
19#include "syscalls/translate.h"
20#include "user-namespace.h"
23constexpr uint32_t Allow = 0x7fff0000;
24constexpr uint32_t Errno = 0x00050000;
25constexpr uint32_t KillThread = 0;
26constexpr uint32_t ActionMask = 0xffff0000;
27constexpr size_t MaximumFilterPath = 32768;
28constexpr size_t MaximumFilters = 64;
30struct SeccompProgram {
33 size_t totalLength = 0;
40 bool noNewPrivileges =
false;
46 bool interceptSyscall(SyscallState& state, uintptr_t& result)
const override;
54 return current().securityState();
58 auto* replacement =
new SandboxState;
60 SYSCALL_ERROR(OutOfMemory);
64 *replacement = *
static_cast<SandboxState*
>(previous.
get());
68 SYSCALL_ERROR(OutOfMemory);
73uint32_t architecture() {
84bool restrictedOperation(uint64_t number) {
85 switch (posix_translate_syscall(number)) {
88 case POSIX_PIVOT_ROOT:
90 case POSIX_PROCESS_VM_READV:
91 case POSIX_PROCESS_VM_WRITEV:
92 case POSIX_OPEN_BY_HANDLE_AT:
93 case POSIX_INIT_MODULE:
94 case POSIX_DELETE_MODULE:
106bool SandboxState::interceptSyscall(SyscallState& state, uintptr_t& result)
const {
107 if (!filters && !domain) {
112 if (state.getSyscallService() != linuxCompat) {
113 result = uintptr_t(-1);
114 SYSCALL_ERROR(NotEnoughPermissions);
117 uint32_t decision = Allow;
120 data.nr =
static_cast<int32_t
>(state.getSyscallNumber());
121 data.arch = architecture();
122 data.instructionPointer = state.getInstructionPointer();
123 for (
size_t i = 0; i < 6; ++i) {
124 data.args[i] = state.getSyscallParameter(6 + i);
126 for (
auto filter = filters; filter; filter = filter->previous) {
127 const uint32_t value =
128 PosixSeccomp::evaluate(filter->instructions.get(), filter->length, data);
130 if (
static_cast<int32_t
>(value & ActionMask) <
static_cast<int32_t
>(decision & ActionMask)) {
135 if ((decision & ActionMask) == Allow) {
136 if (!domain || !restrictedOperation(state.getSyscallNumber())) {
139 SYSCALL_ERROR(NotEnoughPermissions);
140 result = uintptr_t(-1);
143 if ((decision & ActionMask) == Errno) {
144 const unsigned int error = decision & 0xffff;
145 current().setErrno(error > 4095 ? 4095 : error);
146 result = error ? uintptr_t(-1) : 0;
150 if ((decision & ActionMask) == KillThread && !current().getParent()->prepareThreadExit()) {
152 FATAL(
"seccomp thread exit could not be dispatched");
155 current().deferSignalExit(SIGSYS);
157 current().setErrno(0);
163bool posix_no_new_privs() {
164 auto owner = snapshot();
165 return owner &&
static_cast<SandboxState*
>(owner.get())->noNewPrivileges;
168int posix_set_no_new_privs() {
170 auto old = snapshot();
171 if (old &&
static_cast<SandboxState*
>(old.get())->noNewPrivileges) {
172 current().setErrno(0);
175 auto next = copyState(old);
179 static_cast<SandboxState*
>(next.get())->noNewPrivileges =
true;
180 current().setSecurityState(next);
181 current().setErrno(0);
185int posix_seccomp_mode() {
186 auto owner = snapshot();
187 current().setErrno(0);
188 return owner &&
static_cast<SandboxState*
>(owner.get())->filters ? 2 : 0;
191void posix_sandbox_inherit(
Thread& child,
Thread& parent) {
192 child.setSecurityState(parent.securityState());
195bool posix_sandbox_prepare_namespaces(
Thread& source,
200 auto previous = source.securityState();
201 if (!credentials && !ipc && !network) {
205 auto state = copyState(previous);
209 auto* replacement =
static_cast<SandboxState*
>(state.get());
211 replacement->credentials = credentials;
214 replacement->ipcNamespace = ipc;
217 replacement->networkNamespace = network;
224 auto state = thread.securityState();
225 return state ?
static_cast<SandboxState*
>(state.get())->credentials
229bool posix_sandbox_set_credentials(
Thread& thread,
232 auto state = copyState(thread.securityState());
236 static_cast<SandboxState*
>(state.get())->credentials = credentials;
237 thread.setSecurityState(state);
242 auto state = thread.securityState();
243 return state ?
static_cast<SandboxState*
>(state.get())->networkNamespace :
NetworkNamespaceRef();
248 auto state = copyState(thread.securityState());
252 static_cast<SandboxState*
>(state.get())->networkNamespace = space;
253 thread.setSecurityState(state);
258 auto state = thread.securityState();
259 return state ?
static_cast<SandboxState*
>(state.get())->ipcNamespace
265 auto state = copyState(thread.securityState());
269 static_cast<SandboxState*
>(state.get())->ipcNamespace = space;
270 thread.setSecurityState(state);
275 auto owner = snapshot();
281 if (!domain || !posix_no_new_privs()) {
282 SYSCALL_ERROR(NotEnoughPermissions);
285 auto next = copyState(snapshot());
289 static_cast<SandboxState*
>(next.get())->domain = domain;
290 current().setSecurityState(next);
294int posix_seccomp(
unsigned int operation,
unsigned int flags,
const void* args) {
298 SYSCALL_ERROR(InvalidArgument);
301 if (operation == 2) {
304 SYSCALL_ERROR(BadAddress);
307 if (action != Allow && action != Errno && action != KillThread &&
308 action != PosixSeccomp::KillProcess) {
309 SYSCALL_ERROR(OperationNotSupported);
312 current().setErrno(0);
315 if (operation != 1) {
316 SYSCALL_ERROR(InvalidArgument);
319 if (!posix_no_new_privs()) {
320 SYSCALL_ERROR(PermissionDenied);
328 SYSCALL_ERROR(BadAddress);
331 if (!program.length || program.length > PosixSeccomp::MaximumInstructions) {
332 SYSCALL_ERROR(InvalidArgument);
335 auto old = snapshot();
336 auto previous =
static_cast<SandboxState*
>(old.get())->filters;
337 const size_t total = program.length + (previous ? previous->totalLength + 4 : 0);
338 const size_t depth = previous ? previous->depth + 1 : 1;
339 if (total > MaximumFilterPath || depth > MaximumFilters) {
340 SYSCALL_ERROR(OutOfMemory);
345 SYSCALL_ERROR(OutOfMemory);
349 if (!filter->instructions) {
350 SYSCALL_ERROR(OutOfMemory);
355 SYSCALL_ERROR(BadAddress);
358 if (!PosixSeccomp::validate(filter->instructions.get(), program.length)) {
359 SYSCALL_ERROR(InvalidArgument);
362 filter->length = program.length;
363 filter->totalLength = total;
364 filter->depth = depth;
365 filter->previous = previous;
366 auto next = copyState(old);
370 static_cast<SandboxState*
>(next.get())->filters = filter;
371 current().setSecurityState(next);
372 current().setErrno(0);
static bool copyFromUser(void *destination, const void *source, size_t count, size_t elementSize=1)
static ProcessorInformation & information()
static SharedPointer< SecurityState > tryAdopt(SecurityState *ptr)
static SharedPointer< T > tryAllocate(Args...)
static EXPORTED_PUBLIC SyscallManager & instance()