20#include "pedigree/kernel/ActivityDiagnostics.h"
21#include "pedigree/kernel/Log.h"
22#include "pedigree/kernel/Version.h"
23#include "pedigree/kernel/compiler.h"
24#include "pedigree/kernel/linker/Elf.h"
25#include "pedigree/kernel/linker/KernelElf.h"
26#include "pedigree/kernel/panic.h"
27#include "pedigree/kernel/process/PerProcessorScheduler.h"
28#include "pedigree/kernel/process/Process.h"
29#include "pedigree/kernel/process/Scheduler.h"
30#include "pedigree/kernel/process/TerminationDeferral.h"
31#include "pedigree/kernel/process/Thread.h"
32#include "pedigree/kernel/processor/PhysicalMemoryManager.h"
33#include "pedigree/kernel/processor/Processor.h"
34#include "pedigree/kernel/processor/StackFrame.h"
35#include "pedigree/kernel/processor/SyscallManager.h"
36#include "pedigree/kernel/processor/VirtualAddressSpace.h"
37#include "pedigree/kernel/processor/state.h"
38#include "pedigree/kernel/processor/types.h"
39#include "pedigree/kernel/syscallError.h"
40#include "pedigree/kernel/utilities/SecureRandom.h"
41#include "pedigree/kernel/utilities/String.h"
42#include "pedigree/kernel/utilities/Vector.h"
43#include "pedigree/kernel/utilities/ZombieQueue.h"
44#include "pedigree/kernel/utilities/lib.h"
45#include "pedigree/kernel/utilities/utility.h"
47#include "file-syscalls.h"
48#include "ipc-namespace.h"
49#include "linux-resource-abi.h"
50#include "modules/system/linker/DynamicLinker.h"
51#include "modules/system/vfs/File.h"
52#include "modules/system/vfs/MountView.h"
53#include "modules/system/vfs/Symlink.h"
54#include "modules/system/vfs/VFS.h"
55#include "network-namespace.h"
56#include "pipe-syscalls.h"
57#include "posixSyscallNumbers.h"
58#include "pthread-syscalls.h"
59#include "sandbox-state.h"
60#include "signal-syscalls.h"
61#include "system-syscalls.h"
62#include "sysv-semaphore-syscalls.h"
63#include "user-namespace.h"
65#define MACHINE_FORWARD_DECL_ONLY
66#include "pedigree/kernel/Subsystem.h"
67#include "pedigree/kernel/machine/Machine.h"
68#include "pedigree/kernel/machine/Timer.h"
70#include <PosixProcess.h>
71#include <PosixSubsystem.h>
78#include "modules/system/console/Console.h"
79#include "modules/system/users/Group.h"
80#include "modules/system/users/User.h"
81#include "modules/system/users/UserManager.h"
83#include <sys/resource.h>
85#include <sys/utsname.h>
89static_assert(RUSAGE_SELF == 0,
"musl RUSAGE_SELF selector changed");
90static_assert(RUSAGE_CHILDREN == -1,
"musl RUSAGE_CHILDREN selector changed");
91static_assert(RUSAGE_THREAD == 1,
"musl RUSAGE_THREAD selector changed");
92static_assert(offsetof(
struct rusage, __reserved) ==
sizeof(
LinuxRusage64),
93 "musl rusage prefix no longer matches the Linux amd64 syscall ABI");
94static_assert(
sizeof(
struct rusage) ==
sizeof(
LinuxRusage64) + 16 *
sizeof(
long),
95 "musl rusage reserve changed");
99#define ARCH_SET_GS 0x1001
100#define ARCH_SET_FS 0x1002
101#define ARCH_GET_FS 0x1003
102#define ARCH_GET_GS 0x1004
105#define LINUX_PR_SET_NAME 15
106#define LINUX_PR_GET_NAME 16
107#define LINUX_TASK_NAME_LENGTH 16
109#define LINUX_GRND_NONBLOCK 0x1
110#define LINUX_GRND_RANDOM 0x2
113class CloneInterruptScope {
115 explicit CloneInterruptScope(
bool enabled =
false) : m_Previous(
Processor::getInterrupts()) {
119 ~CloneInterruptScope() {
129CloneRoute cloneRoute(
unsigned long flags) {
130 constexpr unsigned long ExitSignalMask = 0xff;
131 constexpr unsigned long SpawnFlags = CLONE_VM | CLONE_VFORK | SIGCHLD;
132 constexpr unsigned long ProcessModifiers =
133 CLONE_NEWUTS | CLONE_NEWNS | CLONE_NEWUSER | CLONE_NEWPID | CLONE_NEWIPC | CLONE_NEWNET |
134 CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | CLONE_SETTLS;
135 constexpr unsigned long ThreadRequired =
136 CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD;
137 constexpr unsigned long ThreadAllowed = ThreadRequired | CLONE_SYSVSEM | CLONE_SETTLS |
138 CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID |
139 CLONE_DETACHED | CLONE_CHILD_SETTID;
141 if (flags & CLONE_THREAD) {
142 if ((flags & ExitSignalMask) || (flags & ThreadRequired) != ThreadRequired ||
143 (flags & ~ThreadAllowed)) {
144 return CloneRoute::Invalid;
146 return CloneRoute::Thread;
151 const unsigned long processFlags = flags & ~ProcessModifiers;
152 if (processFlags == SpawnFlags)
153 return CloneRoute::Vfork;
154 if (processFlags == 0 || processFlags == SIGCHLD) {
155 return CloneRoute::Process;
157 return CloneRoute::Invalid;
161#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
163using CloneBeforeStartHook = void (*)(
Thread*, size_t,
void*);
165CloneBeforeStartHook g_CloneBeforeStartHook =
nullptr;
166void* g_CloneBeforeStartHookContext =
nullptr;
169extern "C" EXPORTED_PUBLIC
void posixSetCloneBeforeStartHookForTest(CloneBeforeStartHook hook,
172 __atomic_store_n(&g_CloneBeforeStartHookContext, context, __ATOMIC_RELEASE);
173 __atomic_store_n(&g_CloneBeforeStartHook, hook, __ATOMIC_RELEASE);
175 __atomic_store_n(&g_CloneBeforeStartHook,
static_cast<CloneBeforeStartHook
>(
nullptr),
177 __atomic_store_n(&g_CloneBeforeStartHookContext,
static_cast<void*
>(
nullptr), __ATOMIC_RELEASE);
181extern "C" EXPORTED_PUBLIC
int posixCloneRouteForTest(
unsigned long flags) {
182 switch (cloneRoute(flags)) {
183 case CloneRoute::Process:
185 case CloneRoute::Thread:
187 case CloneRoute::Vfork:
189 case CloneRoute::Invalid:
205 if (pStockProcess->getType() != Process::Posix) {
212static bool copyUserString(
const char* userString,
String& copy) {
213 PosixSubsystem::UserStringResult result =
215 if (result == PosixSubsystem::UserStringBadAddress) {
216 SYSCALL_ERROR(BadAddress);
219 if (result == PosixSubsystem::UserStringTooLong) {
220 SYSCALL_ERROR(NameTooLong);
226ssize_t posix_getrandom(
void* buffer,
size_t length,
unsigned int flags) {
227 if (flags & ~(LINUX_GRND_NONBLOCK | LINUX_GRND_RANDOM)) {
228 SYSCALL_ERROR(InvalidArgument);
232 uint8_t snapshot[256];
233 const size_t requested = length <
sizeof(snapshot) ? length : sizeof(snapshot);
234 const size_t produced = secure_random_bytes(snapshot, requested);
235 if (requested && !produced) {
236 SYSCALL_ERROR(NoMoreProcesses);
240 pedigree_random::erase(snapshot,
sizeof(snapshot));
242 SYSCALL_ERROR(BadAddress);
245 return static_cast<ssize_t
>(produced);
256 result += pStr->length() + 1;
266 uintptr_t& arrayEndLoc) {
267 char** pMasterArray =
reinterpret_cast<char**
>(arrayLoc);
269 char* pPtr =
reinterpret_cast<char*
>(arrayLoc +
sizeof(
char*) * (rArray.count() + 1));
271 for (
auto it = rArray.begin(); it != rArray.end(); it++) {
272 const String* pStr = it->get();
274 StringCopy(pPtr, pStr->cstr());
275 pPtr[pStr->length()] =
'\0';
277 pMasterArray[i] = pPtr;
279 pPtr += pStr->length() + 1;
284 arrayEndLoc =
reinterpret_cast<uintptr_t
>(pPtr);
289long posix_sbrk(
int delta) {
290 SC_NOTICE(
"sbrk(" << delta <<
")");
294 SC_NOTICE(
" -> " << ret);
296 SYSCALL_ERROR(OutOfMemory);
302uintptr_t posix_brk(uintptr_t theBreak) {
303 SC_NOTICE(
"brk(" << theBreak <<
")");
306 const uintptr_t current =
reinterpret_cast<uintptr_t
>(space.getEndOfHeap());
310 if (theBreak <= current || theBreak - current >
static_cast<uintptr_t
>(INTPTR_MAX))
316 return reinterpret_cast<uintptr_t
>(space.getEndOfHeap());
319SyscallState posix_copy_clone_state(
const SyscallState& state) {
322 state.getUserEntryMetadata();
324 SyscallState clonedState = state;
328 clonedState.error_ptr = 0;
333long posix_clone(SyscallState& state,
unsigned long flags,
void* child_stack,
int* ptid,
int* ctid,
334 unsigned long newtls,
bool linuxAbi,
bool clearSignalHandlers) {
335 SC_NOTICE(
"clone(" <<
Hex << flags <<
", " << child_stack <<
", " << ptid <<
", " << ctid <<
", "
341 SYSCALL_ERROR(NoMoreProcesses);
347 CloneInterruptScope interrupts(
true);
350 SyscallState clonedState = posix_copy_clone_state(state);
353 if (flags & CLONE_PARENT) {
354 SC_NOTICE(
" -> CLONE_PARENT is not yet supported!");
357 const CloneRoute route = cloneRoute(flags);
358 if (route == CloneRoute::Invalid || (clearSignalHandlers && route == CloneRoute::Thread)) {
359 SYSCALL_ERROR(InvalidArgument);
360 SC_NOTICE(
" -> EINVAL (unsupported or inconsistent clone flags)");
363 if (route == CloneRoute::Thread && pParentProcess->isVforkChild()) {
366 SYSCALL_ERROR(InvalidArgument);
370 if (route != CloneRoute::Thread &&
371 (flags & (CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_SETTLS))) {
374 auto writableId = [&](
int* address) {
375 const uintptr_t target =
reinterpret_cast<uintptr_t
>(address);
377 mappings.faultIn(target,
true) && mappings.faultIn(target +
sizeof(
int) - 1,
true);
379 if (((flags & CLONE_PARENT_SETTID) && !writableId(ptid)) ||
380 ((flags & CLONE_CHILD_SETTID) && !writableId(ctid))) {
381 SYSCALL_ERROR(BadAddress);
386 || newtls >= 0x0000800000000000ULL
389 SYSCALL_ERROR(NotEnoughPermissions);
396 if ((flags & CLONE_NEWUSER) && !posix_user_namespace_prepare(
creator, childCredentials)) {
399 if (!(flags & CLONE_NEWUSER) &&
400 (flags & (CLONE_NEWNS | CLONE_NEWPID | CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWNET)) &&
401 !posix_capable(PosixCapabilities::SysAdmin)) {
402 SYSCALL_ERROR(NotEnoughPermissions);
405 const auto ownerNamespace =
406 childCredentials ? childCredentials->userNamespace : posix_user_namespace(
creator);
408 if ((flags & CLONE_NEWNET) && !posix_network_namespace_prepare(ownerNamespace, childNetwork)) {
412 if (flags & CLONE_NEWIPC) {
415 SYSCALL_ERROR(OutOfMemory);
420 if (!posix_sandbox_prepare_namespaces(
creator, childCredentials, childIpc, childNetwork,
428 if (!creatorSubsystem || !creatorSubsystem->traceContext().taskToken(
430 SYSCALL_ERROR(NoSuchProcess);
433 if (route == CloneRoute::Thread) {
434 if (creatorSubsystem->traceContext().reserveThreadCreation(traceCreation) !=
435 TraceStatus::Success) {
436 SYSCALL_ERROR(OperationNotSupported);
439 if (creatorSubsystem->traceContext().prepareTask(preparedTrace) != TraceStatus::Success) {
440 SYSCALL_ERROR(OutOfMemory);
444 auto creatorNamespaces = creatorSubsystem ? creatorSubsystem->namespaceContext()
448 if (!creatorNamespaces ||
450 return posix_uts_error(UtsStatus::Missing);
451 UtsStatus utsPrepared;
455 posix_uts_prepare_thread(creatorUts, flags & CLONE_NEWUTS, preparedUts, ownerNamespace);
457 if (utsPrepared != UtsStatus::Success)
458 return posix_uts_error(utsPrepared);
463 if (route == CloneRoute::Thread) {
468 SYSCALL_ERROR(InvalidArgument);
473 clonedState.setStackPointer(
reinterpret_cast<uintptr_t
>(child_stack));
476 clonedState.setSyscallReturnValue(0);
478 Thread* pThread =
nullptr;
480 bool copiedIds =
false;
484 auto writableId = [&](
int* address) {
485 const uintptr_t target =
reinterpret_cast<uintptr_t
>(address);
487 mappings.faultIn(target,
true) && mappings.faultIn(target +
sizeof(
int) - 1,
true);
489 if (((flags & CLONE_CHILD_SETTID) && !writableId(ctid)) ||
490 ((flags & CLONE_PARENT_SETTID) && !writableId(ptid))) {
491 SYSCALL_ERROR(BadAddress);
494 const bool setTls = !linuxAbi || (flags & CLONE_SETTLS);
497 || newtls >= 0x0000800000000000ULL
500 SYSCALL_ERROR(NotEnoughPermissions);
507 SYSCALL_ERROR(BadAddress);
511 pThread =
new Thread(pParentProcess, clonedState,
true, &placement);
513 SYSCALL_ERROR(OutOfMemory);
516 pThread->executionPersonality().inherit(
519 creatorNamespaces->publishThread(preparedUts, *pThread,
false);
520 if (creatorSubsystem->traceContext().publishTask(preparedTrace, *pThread) !=
521 TraceStatus::Success &&
523 FATAL(
"clone trace task publication failed");
524 pThread->setName(
"posix clone() thread");
530 if (linuxAbi && !threadId) {
533 SYSCALL_ERROR(OutOfMemory);
537 CloneInterruptScope enabled(
true);
539 flags & CLONE_SYSVSEM)) {
542 SYSCALL_ERROR(OutOfMemory);
546 const int id =
static_cast<int>(threadId);
550 if (copiedIds && (flags & CLONE_CHILD_CLEARTID)) {
558 SYSCALL_ERROR(BadAddress);
562#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
563 void* hookContext = __atomic_load_n(&g_CloneBeforeStartHookContext, __ATOMIC_ACQUIRE);
564 CloneBeforeStartHook hook = __atomic_load_n(&g_CloneBeforeStartHook, __ATOMIC_ACQUIRE);
566 hook(pThread, threadId, hookContext);
571 FATAL(
"clone(): delayed thread could not be started.");
575 SC_NOTICE(
" -> " << threadId <<
" [new thread]");
580 const bool borrowAddressSpace = route == CloneRoute::Vfork;
581 if (borrowAddressSpace) {
584 if (!vforkCompletion) {
585 SYSCALL_ERROR(OutOfMemory);
592 clonedState.setStackPointer(
reinterpret_cast<uintptr_t
>(child_stack));
596 if (!pParentSubsystem) {
597 ERROR(
"No subsystem for the parent process!");
598 SYSCALL_ERROR(InvalidArgument);
605 auto parentFilesystem = pParentProcess->acquireFilesystemContext();
606 auto* parentView = VfsMountView::fromContext(parentFilesystem);
607 if (!parentFilesystem || !parentView ||
608 ((flags & CLONE_NEWNS)
609 ? !parentView->forkNamespace(parentFilesystem, childFilesystem,
610 ownerNamespace ? ownerNamespace->identity() : 0)
611 : !parentFilesystem->forkForProcess(childFilesystem))) {
612 SYSCALL_ERROR(OutOfMemory);
617 for (
size_t sig = 0; sig < PosixSubsystem::SignalDispositionCount; sig++)
625 pProcess =
new PosixProcess(pParentProcess,
true, Process::FilesystemContextMode::Deferred,
627 if (!pProcess || !pProcess->
getAddressSpace() || !pProcess->jobControlReady() ||
628 !pProcess->pidNamespaceReady() ||
629 ((flags & CLONE_NEWPID) && !pProcess->createPidNamespace())) {
631 for (
size_t sig = 0; sig < PosixSubsystem::SignalDispositionCount; sig++)
633 SYSCALL_ERROR(OutOfMemory);
634 SC_NOTICE(
" -> ENOMEM");
638 pSubsystem =
new PosixSubsystem(*pParentSubsystem, clearSignalHandlers);
639 if (!pSubsystem || !pSubsystem->namespaceContext() ||
640 !pSubsystem->namespaceContext()->valid()) {
642 pProcess->setSubsystem(pSubsystem);
643 ERROR(
"Could not create a subsystem for the child process!");
646 SYSCALL_ERROR(OutOfMemory);
649 for (
size_t sig = 0; sig < PosixSubsystem::SignalDispositionCount; sig++)
651 SC_NOTICE(
" -> ENOMEM");
654 pProcess->setSubsystem(pSubsystem);
658 if (pParentProcess->getType() == Process::Posix) {
663 SC_NOTICE(
"fork parent was a group leader.");
665 SC_NOTICE(
"fork parent had status " <<
static_cast<int>(p->getGroupMembership()) <<
"...");
667 pProcess->inheritProcessGroup(p);
674 pProcess->setLinker(newLinker);
677 if (borrowAddressSpace) {
678 pProcess->borrowVforkAddressSpace(*pParentProcess, vforkCompletion);
681 for (
size_t sig = 0; sig < PosixSubsystem::SignalDispositionCount; ++sig)
683 SYSCALL_ERROR(OutOfMemory);
689 FATAL(
"Fork could not install its prepared filesystem context");
695 clonedState.setSyscallReturnValue(0);
698 for (
size_t sig = 0; sig < PosixSubsystem::SignalDispositionCount; sig++)
702 if (flags & CLONE_CHILD_SETTID) {
715 SYSCALL_ERROR(BadAddress);
720 if (flags & CLONE_PARENT_SETTID) {
722 static_cast<int>(pProcess->
getUserspaceId(pParentProcess->pidNamespace().
get()));
725 SYSCALL_ERROR(BadAddress);
730 pSubsystem->traceContext().setCreator(creatorTask);
731 if (pSubsystem->traceContext().prepareTask(preparedTrace) != TraceStatus::Success) {
733 SYSCALL_ERROR(OutOfMemory);
741 SYSCALL_ERROR(OutOfMemory);
746 Thread* pThread =
new Thread(pProcess, clonedState,
true, &placement);
749 SYSCALL_ERROR(OutOfMemory);
752 pThread->executionPersonality().inherit(
754 pThread->setSecurityState(childSecurity);
755 pSubsystem->namespaceContext()->publishThread(preparedUts, *pThread,
true);
756 if (pSubsystem->traceContext().publishTask(preparedTrace, *pThread) != TraceStatus::Success &&
758 FATAL(
"fork trace task publication failed");
759 pThread->setName(
"posix clone() forked thread");
760 if (flags & CLONE_SETTLS)
763 if (flags & CLONE_CHILD_CLEARTID) {
771 const size_t childId = pProcess->
getUserspaceId(pParentProcess->pidNamespace().
get());
774 if (!pThread->
start()) {
775 FATAL(
"fork(): delayed child thread could not be started.");
778 vforkCompletion->wait();
781 SC_NOTICE(
" -> " << childId <<
" [new process]");
785int posix_fork(SyscallState& state) {
788 return posix_clone(state, 0, 0, 0, 0, 0);
791int posix_vfork(SyscallState& state) {
792 return posix_clone(state, CLONE_VM | CLONE_VFORK | SIGCHLD,
nullptr,
nullptr,
nullptr, 0,
true);
795int posix_execve(
const char* name,
const char** argv,
const char** env, SyscallState& state) {
797 if (!copyUserString(name, nameCopy)) {
798 SC_NOTICE(
"execve -> invalid address");
802 SC_NOTICE(
"execve(\"" << nameCopy <<
"\")");
807 ERROR(
"No subsystem for this process!");
814 size_t remaining = PosixSubsystem::MaximumExecArgumentBytes - 2 *
sizeof(uintptr_t);
815 if (nameCopy.length() >= remaining) {
816 SYSCALL_ERROR(TooBig);
819 remaining -= nameCopy.length() + 1;
820 auto snapshot = [&](
const char** pointers,
Vector<String>& output) {
821 uintptr_t cursor =
reinterpret_cast<uintptr_t
>(pointers);
823 const char* argument =
nullptr;
826 SYSCALL_ERROR(BadAddress);
832 if (remaining <=
sizeof(uintptr_t)) {
833 SYSCALL_ERROR(TooBig);
836 remaining -=
sizeof(uintptr_t);
839 if (result != PosixSubsystem::UserStringSuccess) {
840 syscallError(result == PosixSubsystem::UserStringBadAddress ? Error::BadAddress
844 remaining -= value.length() + 1;
845 output.pushBack(value);
846 if (cursor > ~uintptr_t(0) -
sizeof(uintptr_t)) {
847 SYSCALL_ERROR(BadAddress);
850 cursor +=
sizeof(uintptr_t);
854 if (!snapshot(argv, listArgv) || !snapshot(env, listEnv)) {
861 normalisePath(invokePath, nameCopy.cstr());
863 if (!pSubsystem->
invoke(invokePath.cstr(), listArgv, listEnv, state)) {
864 SC_NOTICE(
" -> execve failed in invoke");
880 SC_NOTICE(
"getppid");
885 if (!expectedParent) {
891 if (pProcess->
getParent() != expectedParent) {
896 if (pProcess->
getParent() == parent.get()) {
902int posix_gettimeofday(timeval* tv,
struct timezone* tz) {
903 SC_NOTICE(
"gettimeofday");
905 const Time::Timestamp nanoseconds = Time::getTimeNanoseconds();
907 struct timeval result = {};
908 result.tv_sec = nanoseconds / Time::Multiplier::Second;
909 result.tv_usec = (nanoseconds % Time::Multiplier::Second) / Time::Multiplier::Microsecond;
911 SYSCALL_ERROR(BadAddress);
917 const struct timezone result = {};
919 SYSCALL_ERROR(BadAddress);
927int posix_settimeofday(
const timeval* tv,
const struct timezone* tz) {
928 SC_NOTICE(
"settimeofday");
929 SYSCALL_ERROR(Unimplemented);
933time_t posix_time(time_t* tval) {
936 time_t result = Time::getTime();
938 SYSCALL_ERROR(BadAddress);
945clock_t posix_times(
struct tms* tm) {
949 constexpr Time::Timestamp nanosecondsPerClockTick = Time::Multiplier::Second / 100;
951 struct tms result = {};
952 result.tms_utime = pProcess->
getUserTime() / nanosecondsPerClockTick;
953 result.tms_stime = pProcess->getKernelTime() / nanosecondsPerClockTick;
954 result.tms_cutime = pProcess->getReapedChildrenUserTime() / nanosecondsPerClockTick;
955 result.tms_cstime = pProcess->getReapedChildrenKernelTime() / nanosecondsPerClockTick;
957 SC_NOTICE(
"posix_times -> invalid address");
958 SYSCALL_ERROR(BadAddress);
962 SC_NOTICE(
"times: u=" << pProcess->
getUserTime() <<
", s=" << pProcess->getKernelTime());
964 return Time::getTicks() / nanosecondsPerClockTick;
967int posix_getrusage(
int who,
struct rusage* r) {
968 SC_NOTICE(
"getrusage who=" << who);
970 if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN && who != RUSAGE_THREAD) {
971 SC_NOTICE(
"posix_getrusage -> unsupported selector");
972 SYSCALL_ERROR(InvalidArgument);
978 const Time::Timestamp user = who == RUSAGE_THREAD ? currentThread->
getUserTime()
979 : who == RUSAGE_CHILDREN ? pProcess->getReapedChildrenUserTime()
981 const Time::Timestamp kernel = who == RUSAGE_THREAD ? currentThread->getKernelTime()
982 : who == RUSAGE_CHILDREN ? pProcess->getReapedChildrenKernelTime()
983 : pProcess->getKernelTime();
985 struct rusage result = {};
986 result.ru_utime.tv_sec = user / Time::Multiplier::Second;
987 result.ru_utime.tv_usec = (user % Time::Multiplier::Second) / Time::Multiplier::Microsecond;
988 result.ru_stime.tv_sec = kernel / Time::Multiplier::Second;
989 result.ru_stime.tv_usec = (kernel % Time::Multiplier::Second) / Time::Multiplier::Microsecond;
992 SC_NOTICE(
"posix_getrusage -> invalid address");
993 SYSCALL_ERROR(BadAddress);
1001 SC_NOTICE(
"Linux getrusage who=" << who);
1003 if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN && who != RUSAGE_THREAD) {
1004 SC_NOTICE(
"posix_linux_getrusage -> unsupported selector");
1005 SYSCALL_ERROR(InvalidArgument);
1011 const Time::Timestamp user = who == RUSAGE_THREAD ? currentThread->
getUserTime()
1012 : who == RUSAGE_CHILDREN ? pProcess->getReapedChildrenUserTime()
1014 const Time::Timestamp kernel = who == RUSAGE_THREAD ? currentThread->getKernelTime()
1015 : who == RUSAGE_CHILDREN ? pProcess->getReapedChildrenKernelTime()
1016 : pProcess->getKernelTime();
1019 result.userSeconds = user / Time::Multiplier::Second;
1020 result.userMicroseconds = (user % Time::Multiplier::Second) / Time::Multiplier::Microsecond;
1021 result.systemSeconds = kernel / Time::Multiplier::Second;
1022 result.systemMicroseconds = (kernel % Time::Multiplier::Second) / Time::Multiplier::Microsecond;
1025 SC_NOTICE(
"posix_linux_getrusage -> invalid address");
1026 SYSCALL_ERROR(BadAddress);
1034int copyPasswd(
User* user, passwd* output,
char* userStrings) {
1039 char strings[256] = {};
1042 const uintptr_t base =
reinterpret_cast<uintptr_t
>(userStrings);
1046 char** fields[] = {&result.pw_name, &result.pw_passwd, &result.pw_gecos, &result.pw_dir,
1048 for (
size_t i = 0; i < 5; ++i) {
1049 const size_t length = values[i]->length();
1050 if (length >=
sizeof(strings) - used) {
1051 SYSCALL_ERROR(BadRange);
1054 *fields[i] =
reinterpret_cast<char*
>(base + used);
1055 MemoryCopy(strings + used, values[i]->cstr(), length + 1);
1058 result.pw_uid = user->
getId();
1062 SYSCALL_ERROR(BadAddress);
1068int copyGroup(
Group* group,
struct group* output) {
1072 struct group result = {};
1074 SYSCALL_ERROR(BadAddress);
1079 if (name.length() >= 256) {
1080 SYSCALL_ERROR(BadRange);
1083 result.gr_gid = group->
getId();
1086 SYSCALL_ERROR(BadAddress);
1093int posix_getpwent(passwd* pw,
int n,
char* str) {
1097int posix_getpwnam(passwd* pw,
const char* name,
char* str) {
1099 if (!copyUserString(name, nameCopy)) {
1105int posix_getgrnam(
const char* name,
struct group* out) {
1107 if (!copyUserString(name, nameCopy)) {
1113int posix_getgrgid(gid_t
id,
struct group* out) {
1117EXPORTED_PUBLIC
int pedigree_login(
int uid) {
1120 SYSCALL_ERROR(NotEnoughPermissions);
1124 if (!posix_global_capable(PosixCapabilities::Setuid)) {
1125 SYSCALL_ERROR(NotEnoughPermissions);
1129 SYSCALL_ERROR(NoMoreProcesses);
1134 SYSCALL_ERROR(InvalidArgument);
1137 if (!user->
login()) {
1138 SYSCALL_ERROR(InvalidArgument);
1145mode_t posix_umask(mode_t mask) {
1146 SC_NOTICE(
"umask(" <<
Oct << mask <<
")");
1150 if (pStockProcess->getType() != Process::Posix) {
1151 SC_NOTICE(
"umask -> called on something not a POSIX process");
1152 SYSCALL_ERROR(InvalidArgument);
1158 uint32_t previous = pProcess->getMask();
1159 pProcess->setMask(mask);
1164int posix_linux_syslog(
int type,
char* buf,
int len) {
1172 return static_cast<int>(Log::textCapacity());
1173#if PEDIGREE_SYSCALL_COUNTER
1175 if (len !=
static_cast<int>(
sizeof(uint64_t))) {
1176 SYSCALL_ERROR(InvalidArgument);
1180 const uint64_t count = process->getReapedChildrenSyscallCount();
1182 SYSCALL_ERROR(BadAddress);
1185 return static_cast<int>(
sizeof(count));
1189 Process::SyscallLatencySnapshot snapshot = {};
1190 process->getReapedChildrenSyscallLatencySnapshot(snapshot);
1191 if (len !=
static_cast<int>(
sizeof(snapshot))) {
1192 SYSCALL_ERROR(InvalidArgument);
1196 SYSCALL_ERROR(BadAddress);
1199 return static_cast<int>(
sizeof(snapshot));
1202#if PEDIGREE_ACTIVITY_DIAGNOSTICS
1205 SYSCALL_ERROR(InvalidArgument);
1209 ActivityDiagnostics::snapshot(snapshot);
1211 SYSCALL_ERROR(BadAddress);
1214 return static_cast<int>(
sizeof(snapshot));
1217#if PEDIGREE_BENCHMARK_SYSCALL_TIMING
1219 if (buf || (len != 0 && len != 1)) {
1220 SYSCALL_ERROR(InvalidArgument);
1224 process->setBenchmarkSyscallTiming(len != 0);
1228 constexpr size_t snapshotSize =
1229 Process::SyscallTimingSlotCount *
sizeof(Process::SyscallTimingEntry);
1230 if (len !=
static_cast<int>(snapshotSize)) {
1231 SYSCALL_ERROR(InvalidArgument);
1235 for (
size_t i = 0; i < Process::SyscallTimingSlotCount; ++i) {
1236 Process::SyscallTimingEntry entry = {};
1237 process->getSyscallTimingEntry(i, entry);
1239 SYSCALL_ERROR(BadAddress);
1243 return static_cast<int>(snapshotSize);
1246#if PEDIGREE_BENCHMARK_VM_DIAGNOSTICS
1248 if (buf || (len != 0 && len != 1)) {
1249 SYSCALL_ERROR(InvalidArgument);
1253 process->setBenchmarkVmDiagnostics(len != 0);
1257 constexpr size_t snapshotSize = Process::BenchmarkVmCounterCount *
sizeof(uint64_t);
1258 if (len !=
static_cast<int>(snapshotSize)) {
1259 SYSCALL_ERROR(InvalidArgument);
1263 for (
size_t i = 0; i < Process::BenchmarkVmCounterCount; ++i) {
1264 const uint64_t value = process->getBenchmarkVmCounter(i);
1266 SYSCALL_ERROR(BadAddress);
1270 return static_cast<int>(snapshotSize);
1274#if PEDIGREE_BENCHMARK_SYSCALL_TRACE
1275 if (buf || (len != 0 && len != 1)) {
1276 SYSCALL_ERROR(InvalidArgument);
1280 process->setBenchmarkSyscallTrace(len != 0);
1283 SYSCALL_ERROR(Unimplemented);
1294 SYSCALL_ERROR(Unimplemented);
1297 SYSCALL_ERROR(InvalidArgument);
1302 SYSCALL_ERROR(InvalidArgument);
1307 const size_t capacity =
static_cast<size_t>(len) < Log::textCapacity() ?
static_cast<size_t>(len)
1308 :
Log::textCapacity();
1310 PosixSubsystem::SafeWrite)) {
1311 SYSCALL_ERROR(BadAddress);
1317 char* snapshot =
new char[capacity];
1319 SYSCALL_ERROR(OutOfMemory);
1326 SYSCALL_ERROR(BadAddress);
1329 return static_cast<int>(copied);
1332int posix_syslog(
const char* msg,
int prio) {
1334 if (!copyUserString(msg, msgCopy)) {
1335 SC_NOTICE(
"klog -> invalid address");
1341 if (prio <= LOG_CRIT)
1342 FATAL(
"[" <<
Dec <<
id <<
Hex <<
"]\tklog: " << msgCopy);
1345 if (prio <= LOG_ERR)
1346 ERROR(
"[" <<
Dec <<
id <<
Hex <<
"]\tklog: " << msgCopy);
1347 else if (prio == LOG_WARNING)
1348 WARNING(
"[" <<
Dec <<
id <<
Hex <<
"]\tklog: " << msgCopy);
1349 else if (prio == LOG_NOTICE || prio == LOG_INFO)
1350 NOTICE(
"[" <<
Dec <<
id <<
Hex <<
"]\tklog: " << msgCopy);
1353 NOTICE(
"[" <<
Dec <<
id <<
Hex <<
"]\tklog: " << msgCopy);
1358int posix_reboot(uint32_t magic1, uint32_t magic2, uint32_t command) {
1359 if (!posix_global_capable(PosixCapabilities::SysBoot)) {
1360 SYSCALL_ERROR(NotEnoughPermissions);
1363 if (magic1 != 0xfee1dead ||
1364 (magic2 != 672274793 && magic2 != 85072278 && magic2 != 369367448 && magic2 != 537993216)) {
1365 SYSCALL_ERROR(InvalidArgument);
1369 Machine::ShutdownType type;
1376 type = Machine::ShutdownType::Restart;
1379 type = Machine::ShutdownType::Halt;
1382 type = Machine::ShutdownType::PowerOff;
1386 SYSCALL_ERROR(InvalidArgument);
1394 if (status == Filesystem::SyncStatus::IoError || status == Filesystem::SyncStatus::NoMemory) {
1396 "Shutdown failed: filesystem synchronization failed");
1397 syscallError(status == Filesystem::SyncStatus::IoError ? Error::IoError : Error::OutOfMemory);
1401 SYSCALL_ERROR(DeviceBusy);
1407EXPORTED_PUBLIC
int pedigree_reboot() {
1408 return posix_reboot(0xfee1dead, 672274793, 0x01234567);
1411int posix_prctl(
int option, uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5) {
1412 NOTICE(
"prctl(" <<
Hex << option <<
", " << arg2 <<
", " << arg3 <<
", " << arg4 <<
", " << arg5
1416 if (option == 38 || option == 39) {
1417 if (arg3 || arg4 || arg5 || (option == 38 ? arg2 != 1 : arg2 != 0)) {
1418 SYSCALL_ERROR(InvalidArgument);
1422 return posix_set_no_new_privs();
1425 return posix_no_new_privs() ? 1 : 0;
1427 if (option == 7 || option == 8 || option == 23 || option == 24 || option == 27 || option == 28 ||
1429 return posix_capability_prctl(option, arg2, arg3, arg4, arg5);
1432 return posix_seccomp_mode();
1436 SYSCALL_ERROR(InvalidArgument);
1439 return posix_seccomp(1, 0,
reinterpret_cast<const void*
>(arg3));
1441 if (option == 1 || option == 2) {
1444 SYSCALL_ERROR(NoSuchProcess);
1448 if (arg2 >= PosixSubsystem::SignalDispositionCount) {
1449 SYSCALL_ERROR(InvalidArgument);
1452 if (!subsystem->traceContext().setParentDeathSignal(*thread,
static_cast<int>(arg2))) {
1453 SYSCALL_ERROR(NoSuchProcess);
1458 if (!subsystem->traceContext().taskToken(*thread, task)) {
1459 SYSCALL_ERROR(NoSuchProcess);
1462 const int signal = task->parentDeathSignal();
1464 SYSCALL_ERROR(BadAddress);
1471 if (option == 3 || option == 4) {
1474 SYSCALL_ERROR(InvalidArgument);
1479 return process->snapshotCredentials().dumpable ? 1 : 0;
1482 SYSCALL_ERROR(InvalidArgument);
1485 process->setDumpable(arg2 != 0);
1490 if (option == LINUX_PR_SET_NAME) {
1493 reinterpret_cast<const char*
>(arg2), requested, LINUX_TASK_NAME_LENGTH);
1494 if (result == PosixSubsystem::UserStringBadAddress) {
1495 SYSCALL_ERROR(BadAddress);
1501 const size_t length = requested.length() < (LINUX_TASK_NAME_LENGTH - 1)
1502 ? requested.length()
1503 : (LINUX_TASK_NAME_LENGTH - 1);
1504 thread->setName(
String(requested.cstr(), length,
true));
1508 if (option == LINUX_PR_GET_NAME) {
1509 char name[LINUX_TASK_NAME_LENGTH] = {};
1510 const String& current = thread->getName();
1511 const size_t length = current.length() < (LINUX_TASK_NAME_LENGTH - 1)
1513 : (LINUX_TASK_NAME_LENGTH - 1);
1514 MemoryCopy(name, current.cstr(), length);
1516 SYSCALL_ERROR(BadAddress);
1522 SYSCALL_ERROR(InvalidArgument);
1526int posix_arch_prctl(
int code,
unsigned long addr) {
1534 addr >= 0x0000800000000000ULL) {
1535 SYSCALL_ERROR(NotEnoughPermissions);
1538 current->setUserGsBase(addr);
1542 const unsigned long base = Processor::getUserGsBase();
1544 SYSCALL_ERROR(BadAddress);
1553 || addr >= 0x0000800000000000ULL
1556 SYSCALL_ERROR(NotEnoughPermissions);
1563 const unsigned long base = current->
getTlsBase();
1565 SYSCALL_ERROR(BadAddress);
1572 SYSCALL_ERROR(InvalidArgument);
1583 SYSCALL_ERROR(Interrupted);
1587int posix_membarrier(
int command,
unsigned int flags,
int cpuId) {
1588 SC_NOTICE(
"membarrier(" <<
Dec << command <<
", " << flags <<
", " << cpuId <<
")");
1592 if (command == 0 && flags == 0) {
1596 SYSCALL_ERROR(InvalidArgument);
1600int posix_getpriority(
int which,
int who,
bool linuxAbi) {
1601 SC_NOTICE(
"getpriority(" << which <<
", " <<
Dec << who <<
")");
1602 if (which != PRIO_PROCESS && which != PRIO_PGRP && which != PRIO_USER) {
1603 SYSCALL_ERROR(InvalidArgument);
1607 SYSCALL_ERROR(NoSuchProcess);
1613 SYSCALL_ERROR(NoSuchProcess);
1619 const int priority = linuxAbi ? 20 : 0;
1620 if (which == PRIO_PROCESS) {
1621 if (!who ||
static_cast<size_t>(who) == caller->
getUserspaceId()) {
1625 if (
Scheduler::instance().acquireProcessByUserspaceId(candidate,
static_cast<size_t>(who)) &&
1626 candidate->getType() == Process::Posix && candidate->getState() !=
Process::Reaped) {
1629 SYSCALL_ERROR(NoSuchProcess);
1633 if (which == PRIO_USER) {
1634 if (!who ||
static_cast<int64_t
>(who) == caller->
getUserId()) {
1639 SYSCALL_ERROR(Unimplemented);
1643 size_t callerGroup = 0;
1644 const bool hasCallerGroup = caller->getProcessGroupId(callerGroup);
1645 if (hasCallerGroup && (!who ||
static_cast<size_t>(who) == callerGroup)) {
1649 SYSCALL_ERROR(Unimplemented);
1653 SYSCALL_ERROR(NoSuchProcess);
1657int posix_setpriority(
int which,
int who,
int prio) {
1659 SC_NOTICE(
"setpriority(" << which <<
", " <<
Dec << who <<
", " << prio <<
")");
1663int posix_get_robust_list(
int pid,
struct robust_list_head** head_ptr,
size_t* len_ptr,
1665 SC_NOTICE(
"get_robust_list");
1667 Thread* target = current;
1670 if (pid < 0 || (pid &&
static_cast<size_t>(pid) != currentId &&
1672 : current->getParent()->acquireThreadById(targetLease, pid)))) {
1673 SYSCALL_ERROR(NoSuchProcess);
1677 target = targetLease.get();
1682 SYSCALL_ERROR(NotEnoughPermissions);
1686 auto* head =
reinterpret_cast<struct robust_list_head*
>(target->getRobustList());
1687 const size_t length = 3 *
sizeof(uintptr_t);
1690 SYSCALL_ERROR(BadAddress);
1696int posix_set_robust_list(
struct robust_list_head* head,
size_t len,
bool linuxAbi) {
1697 SC_NOTICE(
"set_robust_list");
1699 if (len != 3 *
sizeof(uintptr_t)) {
1700 SYSCALL_ERROR(InvalidArgument);
1707 current->setRobustList(
reinterpret_cast<uintptr_t
>(head),
1713int posix_ioperm(
unsigned long from,
unsigned long num,
int turn_on) {
1714 SC_NOTICE(
"ioperm(" << from <<
", " << num <<
", " << turn_on <<
")");
1721int posix_iopl(
int level) {
1722 SC_NOTICE(
"iopl(" << level <<
")");
1730constexpr Time::Timestamp MaximumLinuxTimerNanoseconds = 0x7FFFFFFFFFFFFFFFULL;
1735 return &process->getRealIntervalTimer();
1736 case ITIMER_VIRTUAL:
1737 return &process->getVirtualIntervalTimer();
1739 return &process->getProfileIntervalTimer();
1745bool validIntervalTimeval(
const struct timeval& value) {
1746 return value.tv_sec >= 0 && value.tv_usec >= 0 && value.tv_usec < 1000000;
1749Time::Timestamp intervalTimevalToNanoseconds(
const struct timeval& value) {
1750 const Time::Timestamp microseconds =
1751 static_cast<Time::Timestamp
>(value.tv_usec) * Time::Multiplier::Microsecond;
1752 const Time::Timestamp seconds =
static_cast<Time::Timestamp
>(value.tv_sec);
1753 if (seconds >= MaximumLinuxTimerNanoseconds / Time::Multiplier::Second) {
1754 return MaximumLinuxTimerNanoseconds;
1756 return seconds * Time::Multiplier::Second + microseconds;
1759struct itimerval intervalTimerToUser(Time::
Timestamp interval, Time::Timestamp value) {
1760 struct itimerval result = {};
1761 result.it_interval.tv_sec = interval / Time::Multiplier::Second;
1762 result.it_interval.tv_usec =
1763 (interval % Time::Multiplier::Second) / Time::Multiplier::Microsecond;
1764 result.it_value.tv_sec = value / Time::Multiplier::Second;
1765 result.it_value.tv_usec = (value % Time::Multiplier::Second) / Time::Multiplier::Microsecond;
1770int posix_getitimer(
int which,
struct itimerval* curr_value) {
1771 SC_NOTICE(
"posix_getitimer(" << which <<
", " << curr_value <<
")");
1776 Time::Timestamp interval = 0;
1777 Time::Timestamp value = 0;
1779 IntervalTimer* itimer = selectIntervalTimer(pProcess, which);
1781 SYSCALL_ERROR(InvalidArgument);
1785 if (which != ITIMER_REAL) {
1786 currentThread->
trackTime(CpuTimeMode::Kernel);
1788 itimer->getIntervalAndValue(interval, value);
1790 const struct itimerval result = intervalTimerToUser(interval, value);
1792 SYSCALL_ERROR(BadAddress);
1796 SC_NOTICE(
" -> period = " <<
Dec << result.it_interval.tv_sec <<
"s "
1797 << result.it_interval.tv_usec <<
"us");
1798 SC_NOTICE(
" -> value = " <<
Dec << result.it_value.tv_sec <<
"s " << result.it_value.tv_usec
1804int posix_setitimer(
int which,
const struct itimerval* new_value,
struct itimerval* old_value) {
1805 SC_NOTICE(
"posix_setitimer(" << which <<
", " << new_value <<
", " << old_value <<
")");
1807 struct itimerval requested = {};
1809 SYSCALL_ERROR(BadAddress);
1812 if (!validIntervalTimeval(requested.it_interval) || !validIntervalTimeval(requested.it_value)) {
1813 SYSCALL_ERROR(InvalidArgument);
1817 SC_NOTICE(
" -> period = " <<
Dec << requested.it_interval.tv_sec <<
"s "
1818 << requested.it_interval.tv_usec <<
"us");
1819 SC_NOTICE(
" -> value = " <<
Dec << requested.it_value.tv_sec <<
"s " << requested.it_value.tv_usec
1825 const Time::Timestamp interval = intervalTimevalToNanoseconds(requested.it_interval);
1826 const Time::Timestamp value = intervalTimevalToNanoseconds(requested.it_value);
1827 Time::Timestamp prevInterval = 0;
1828 Time::Timestamp prevValue = 0;
1830 IntervalTimer* itimer = selectIntervalTimer(pProcess, which);
1832 SYSCALL_ERROR(InvalidArgument);
1836 if (which != ITIMER_REAL) {
1837 currentThread->
trackTime(CpuTimeMode::Kernel);
1842 const struct itimerval previous = intervalTimerToUser(prevInterval, prevValue);
1844 SYSCALL_ERROR(BadAddress);
Memory-mapped file interface.
const String & getName() const
void setIntervalAndValue(Time::Timestamp interval, Time::Timestamp value, Time::Timestamp *prevInterval=nullptr, Time::Timestamp *prevValue=nullptr)
Set both interval and value atomically.
static EXPORTED_PUBLIC Log & instance()
EXPORTED_PUBLIC size_t copyText(char *buffer, size_t capacity)
void displayShutdownMessage(const char *message)
static MemoryMapManager & instance()
int64_t getUserId() const final
static bool copyFromUser(void *destination, const void *source, size_t count, size_t elementSize=1)
bool copyDescriptors(PosixSubsystem *pSubsystem)
static UserStringResult copyUserString(const char *userString, String ©, size_t maxLength)
void setProcess(Process *process) override
virtual bool invoke(const char *name, Vector< String > &argv, Vector< String > &env)
static bool copyToUser(void *destination, const void *source, size_t count, size_t elementSize=1)
static bool checkAddress(uintptr_t addr, size_t extent, size_t flags)
size_t getUserspaceId() const
@ Reaped
Terminal wait status is visible; the owner may still be on-stack.
MUST_USE_RESULT bool installFilesystemContext(FilesystemContextOwner &&context)
VirtualAddressSpace * getAddressSpace()
Time::Timestamp getUserTime() const
static ProcessorInformation & information()
static void switchAddressSpace(VirtualAddressSpace &AddressSpace)
static void setInterrupts(bool bEnable)
static Scheduler & instance()
static SharedPointer< T > tryAdopt(T *ptr)
static SharedPointer< T > tryAllocate(Args...)
static EXPORTED_PUBLIC SyscallManager & instance()
void setErrno(size_t err)
void setTlsBase(uintptr_t base)
void setUnwindState(UnwindType ut)
@ TerminateThread
Exit only this thread during Process exit.
Time::Timestamp getUserTime() const
UnwindType getUnwindState()
void setClearChildTid(uintptr_t address)
void trackTime(CpuTimeMode mode)
Process * getParent() const
size_t getUserspaceTaskId(const UserspacePidNamespace *space=nullptr) const
User * getUser(size_t id)
static UserManager & instance()
const String & getFullName() const
const String & getUsername() const
Group * getDefaultGroup()
const String & getHome() const
const String & getShell() const
Filesystem::SyncStatus syncAll()
A vector / dynamic array.
static const size_t Write
virtual uintptr_t getKernelStart() const =0