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 "linux-resource-abi.h"
49#include "modules/system/linker/DynamicLinker.h"
50#include "modules/system/vfs/File.h"
51#include "modules/system/vfs/Symlink.h"
52#include "modules/system/vfs/VFS.h"
53#include "pipe-syscalls.h"
54#include "posixSyscallNumbers.h"
55#include "pthread-syscalls.h"
56#include "signal-syscalls.h"
57#include "system-syscalls.h"
58#include "sysv-semaphore-syscalls.h"
60#define MACHINE_FORWARD_DECL_ONLY
61#include "pedigree/kernel/Subsystem.h"
62#include "pedigree/kernel/machine/Machine.h"
63#include "pedigree/kernel/machine/Timer.h"
65#include <PosixProcess.h>
66#include <PosixSubsystem.h>
73#include "modules/system/console/Console.h"
74#include "modules/system/users/Group.h"
75#include "modules/system/users/User.h"
76#include "modules/system/users/UserManager.h"
78#include <sys/resource.h>
80#include <sys/utsname.h>
84static_assert(RUSAGE_SELF == 0,
"musl RUSAGE_SELF selector changed");
85static_assert(RUSAGE_CHILDREN == -1,
"musl RUSAGE_CHILDREN selector changed");
86static_assert(RUSAGE_THREAD == 1,
"musl RUSAGE_THREAD selector changed");
87static_assert(offsetof(
struct rusage, __reserved) ==
sizeof(
LinuxRusage64),
88 "musl rusage prefix no longer matches the Linux amd64 syscall ABI");
89static_assert(
sizeof(
struct rusage) ==
sizeof(
LinuxRusage64) + 16 *
sizeof(
long),
90 "musl rusage reserve changed");
94#define ARCH_SET_GS 0x1001
95#define ARCH_SET_FS 0x1002
96#define ARCH_GET_FS 0x1003
97#define ARCH_GET_GS 0x1004
100#define LINUX_PR_SET_NAME 15
101#define LINUX_PR_GET_NAME 16
102#define LINUX_TASK_NAME_LENGTH 16
105#define _LINUX_CAPABILITY_VERSION_1 0x19980330
107#define LINUX_GRND_NONBLOCK 0x1
108#define LINUX_GRND_RANDOM 0x2
111class CloneInterruptScope {
113 explicit CloneInterruptScope(
bool enabled =
false) : m_Previous(
Processor::getInterrupts()) {
117 ~CloneInterruptScope() {
127CloneRoute cloneRoute(
unsigned long flags) {
128 constexpr unsigned long ExitSignalMask = 0xff;
129 constexpr unsigned long SpawnFlags = CLONE_VM | CLONE_VFORK | SIGCHLD;
130 constexpr unsigned long ProcessModifiers =
131 CLONE_NEWUTS | CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | CLONE_SETTLS;
132 constexpr unsigned long ThreadRequired =
133 CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD;
134 constexpr unsigned long ThreadAllowed = ThreadRequired | CLONE_SYSVSEM | CLONE_SETTLS |
135 CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID |
136 CLONE_DETACHED | CLONE_CHILD_SETTID;
138 if (flags & CLONE_THREAD) {
139 if ((flags & ExitSignalMask) || (flags & ThreadRequired) != ThreadRequired ||
140 (flags & ~ThreadAllowed)) {
141 return CloneRoute::Invalid;
143 return CloneRoute::Thread;
148 const unsigned long processFlags = flags & ~ProcessModifiers;
149 if (processFlags == SpawnFlags)
150 return CloneRoute::Vfork;
151 if (processFlags == 0 || processFlags == SIGCHLD) {
152 return CloneRoute::Process;
154 return CloneRoute::Invalid;
158#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
160using CloneBeforeStartHook = void (*)(
Thread*, size_t,
void*);
162CloneBeforeStartHook g_CloneBeforeStartHook =
nullptr;
163void* g_CloneBeforeStartHookContext =
nullptr;
166extern "C" EXPORTED_PUBLIC
void posixSetCloneBeforeStartHookForTest(CloneBeforeStartHook hook,
169 __atomic_store_n(&g_CloneBeforeStartHookContext, context, __ATOMIC_RELEASE);
170 __atomic_store_n(&g_CloneBeforeStartHook, hook, __ATOMIC_RELEASE);
172 __atomic_store_n(&g_CloneBeforeStartHook,
static_cast<CloneBeforeStartHook
>(
nullptr),
174 __atomic_store_n(&g_CloneBeforeStartHookContext,
static_cast<void*
>(
nullptr), __ATOMIC_RELEASE);
178extern "C" EXPORTED_PUBLIC
int posixCloneRouteForTest(
unsigned long flags) {
179 switch (cloneRoute(flags)) {
180 case CloneRoute::Process:
182 case CloneRoute::Thread:
184 case CloneRoute::Vfork:
186 case CloneRoute::Invalid:
202 uint32_t inheritable;
212 if (pStockProcess->getType() != Process::Posix) {
219static bool copyUserString(
const char* userString,
String& copy) {
220 PosixSubsystem::UserStringResult result =
222 if (result == PosixSubsystem::UserStringBadAddress) {
223 SYSCALL_ERROR(BadAddress);
226 if (result == PosixSubsystem::UserStringTooLong) {
227 SYSCALL_ERROR(NameTooLong);
233ssize_t posix_getrandom(
void* buffer,
size_t length,
unsigned int flags) {
234 if (flags & ~(LINUX_GRND_NONBLOCK | LINUX_GRND_RANDOM)) {
235 SYSCALL_ERROR(InvalidArgument);
239 uint8_t snapshot[256];
240 const size_t requested = length <
sizeof(snapshot) ? length : sizeof(snapshot);
241 const size_t produced = secure_random_bytes(snapshot, requested);
242 if (requested && !produced) {
243 SYSCALL_ERROR(NoMoreProcesses);
247 pedigree_random::erase(snapshot,
sizeof(snapshot));
249 SYSCALL_ERROR(BadAddress);
252 return static_cast<ssize_t
>(produced);
263 result += pStr->length() + 1;
273 uintptr_t& arrayEndLoc) {
274 char** pMasterArray =
reinterpret_cast<char**
>(arrayLoc);
276 char* pPtr =
reinterpret_cast<char*
>(arrayLoc +
sizeof(
char*) * (rArray.count() + 1));
278 for (
auto it = rArray.begin(); it != rArray.end(); it++) {
279 const String* pStr = it->get();
281 StringCopy(pPtr, pStr->cstr());
282 pPtr[pStr->length()] =
'\0';
284 pMasterArray[i] = pPtr;
286 pPtr += pStr->length() + 1;
291 arrayEndLoc =
reinterpret_cast<uintptr_t
>(pPtr);
296long posix_sbrk(
int delta) {
297 SC_NOTICE(
"sbrk(" << delta <<
")");
301 SC_NOTICE(
" -> " << ret);
303 SYSCALL_ERROR(OutOfMemory);
309uintptr_t posix_brk(uintptr_t theBreak) {
310 SC_NOTICE(
"brk(" << theBreak <<
")");
313 const uintptr_t current =
reinterpret_cast<uintptr_t
>(space.getEndOfHeap());
317 if (theBreak <= current || theBreak - current >
static_cast<uintptr_t
>(INTPTR_MAX))
323 return reinterpret_cast<uintptr_t
>(space.getEndOfHeap());
326SyscallState posix_copy_clone_state(
const SyscallState& state) {
329 state.getUserEntryMetadata();
331 SyscallState clonedState = state;
335 clonedState.error_ptr = 0;
340long posix_clone(SyscallState& state,
unsigned long flags,
void* child_stack,
int* ptid,
int* ctid,
341 unsigned long newtls,
bool linuxAbi,
bool clearSignalHandlers) {
342 SC_NOTICE(
"clone(" <<
Hex << flags <<
", " << child_stack <<
", " << ptid <<
", " << ctid <<
", "
348 SYSCALL_ERROR(NoMoreProcesses);
354 CloneInterruptScope interrupts(
true);
357 SyscallState clonedState = posix_copy_clone_state(state);
360 if (flags & CLONE_PARENT) {
361 SC_NOTICE(
" -> CLONE_PARENT is not yet supported!");
364 const CloneRoute route = cloneRoute(flags);
365 if (route == CloneRoute::Invalid || (clearSignalHandlers && route == CloneRoute::Thread)) {
366 SYSCALL_ERROR(InvalidArgument);
367 SC_NOTICE(
" -> EINVAL (unsupported or inconsistent clone flags)");
370 if (route == CloneRoute::Thread && pParentProcess->isVforkChild()) {
373 SYSCALL_ERROR(InvalidArgument);
377 if (route != CloneRoute::Thread &&
378 (flags & (CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_SETTLS))) {
381 auto writableId = [&](
int* address) {
382 const uintptr_t target =
reinterpret_cast<uintptr_t
>(address);
384 mappings.faultIn(target,
true) && mappings.faultIn(target +
sizeof(
int) - 1,
true);
386 if (((flags & CLONE_PARENT_SETTID) && !writableId(ptid)) ||
387 ((flags & CLONE_CHILD_SETTID) && !writableId(ctid))) {
388 SYSCALL_ERROR(BadAddress);
393 || newtls >= 0x0000800000000000ULL
396 SYSCALL_ERROR(NotEnoughPermissions);
405 if (!creatorSubsystem || !creatorSubsystem->traceContext().taskToken(
407 SYSCALL_ERROR(NoSuchProcess);
410 if (route == CloneRoute::Thread) {
411 if (creatorSubsystem->traceContext().reserveThreadCreation(traceCreation) !=
412 TraceStatus::Success) {
413 SYSCALL_ERROR(OperationNotSupported);
416 if (creatorSubsystem->traceContext().prepareTask(preparedTrace) != TraceStatus::Success) {
417 SYSCALL_ERROR(OutOfMemory);
421 auto creatorNamespaces = creatorSubsystem ? creatorSubsystem->namespaceContext()
425 if (!creatorNamespaces ||
427 return posix_uts_error(UtsStatus::Missing);
428 UtsStatus utsPrepared;
431 if ((flags & CLONE_NEWUTS) && getPosixProcess()->snapshotCredentials().euid != 0) {
432 SYSCALL_ERROR(NotEnoughPermissions);
435 utsPrepared = posix_uts_prepare_thread(creatorUts, flags & CLONE_NEWUTS, preparedUts);
437 if (utsPrepared != UtsStatus::Success)
438 return posix_uts_error(utsPrepared);
443 if (route == CloneRoute::Thread) {
448 SYSCALL_ERROR(InvalidArgument);
453 clonedState.setStackPointer(
reinterpret_cast<uintptr_t
>(child_stack));
456 clonedState.setSyscallReturnValue(0);
458 Thread* pThread =
nullptr;
460 bool copiedIds =
false;
464 auto writableId = [&](
int* address) {
465 const uintptr_t target =
reinterpret_cast<uintptr_t
>(address);
467 mappings.faultIn(target,
true) && mappings.faultIn(target +
sizeof(
int) - 1,
true);
469 if (((flags & CLONE_CHILD_SETTID) && !writableId(ctid)) ||
470 ((flags & CLONE_PARENT_SETTID) && !writableId(ptid))) {
471 SYSCALL_ERROR(BadAddress);
474 const bool setTls = !linuxAbi || (flags & CLONE_SETTLS);
477 || newtls >= 0x0000800000000000ULL
480 SYSCALL_ERROR(NotEnoughPermissions);
487 SYSCALL_ERROR(BadAddress);
491 pThread =
new Thread(pParentProcess, clonedState,
true, &placement);
493 SYSCALL_ERROR(OutOfMemory);
496 pThread->executionPersonality().inherit(
498 creatorNamespaces->publishThread(preparedUts, *pThread,
false);
499 if (creatorSubsystem->traceContext().publishTask(preparedTrace, *pThread) !=
500 TraceStatus::Success &&
502 FATAL(
"clone trace task publication failed");
503 pThread->setName(
"posix clone() thread");
510 CloneInterruptScope enabled(
true);
512 flags & CLONE_SYSVSEM)) {
515 SYSCALL_ERROR(OutOfMemory);
519 const int id =
static_cast<int>(threadId);
523 if (copiedIds && (flags & CLONE_CHILD_CLEARTID)) {
531 SYSCALL_ERROR(BadAddress);
535#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
536 void* hookContext = __atomic_load_n(&g_CloneBeforeStartHookContext, __ATOMIC_ACQUIRE);
537 CloneBeforeStartHook hook = __atomic_load_n(&g_CloneBeforeStartHook, __ATOMIC_ACQUIRE);
539 hook(pThread, threadId, hookContext);
544 FATAL(
"clone(): delayed thread could not be started.");
548 SC_NOTICE(
" -> " << threadId <<
" [new thread]");
553 const bool borrowAddressSpace = route == CloneRoute::Vfork;
554 if (borrowAddressSpace) {
557 if (!vforkCompletion) {
558 SYSCALL_ERROR(OutOfMemory);
565 clonedState.setStackPointer(
reinterpret_cast<uintptr_t
>(child_stack));
569 if (!pParentSubsystem) {
570 ERROR(
"No subsystem for the parent process!");
571 SYSCALL_ERROR(InvalidArgument);
578 auto parentFilesystem = pParentProcess->acquireFilesystemContext();
579 if (!parentFilesystem || !parentFilesystem->forkForProcess(childFilesystem)) {
580 SYSCALL_ERROR(OutOfMemory);
585 for (
size_t sig = 0; sig < PosixSubsystem::SignalDispositionCount; sig++)
593 pProcess =
new PosixProcess(pParentProcess,
true, Process::FilesystemContextMode::Deferred,
595 if (!pProcess || !pProcess->
getAddressSpace() || !pProcess->jobControlReady()) {
597 for (
size_t sig = 0; sig < PosixSubsystem::SignalDispositionCount; sig++)
599 SYSCALL_ERROR(OutOfMemory);
600 SC_NOTICE(
" -> ENOMEM");
604 pSubsystem =
new PosixSubsystem(*pParentSubsystem, clearSignalHandlers);
605 if (!pSubsystem || !pSubsystem->namespaceContext() ||
606 !pSubsystem->namespaceContext()->valid()) {
608 pProcess->setSubsystem(pSubsystem);
609 ERROR(
"Could not create a subsystem for the child process!");
612 SYSCALL_ERROR(OutOfMemory);
615 for (
size_t sig = 0; sig < PosixSubsystem::SignalDispositionCount; sig++)
617 SC_NOTICE(
" -> ENOMEM");
620 pProcess->setSubsystem(pSubsystem);
624 if (pParentProcess->getType() == Process::Posix) {
629 SC_NOTICE(
"fork parent was a group leader.");
631 SC_NOTICE(
"fork parent had status " <<
static_cast<int>(p->getGroupMembership()) <<
"...");
633 pProcess->inheritProcessGroup(p);
640 pProcess->setLinker(newLinker);
643 if (borrowAddressSpace) {
644 pProcess->borrowVforkAddressSpace(*pParentProcess, vforkCompletion);
647 for (
size_t sig = 0; sig < PosixSubsystem::SignalDispositionCount; ++sig)
649 SYSCALL_ERROR(OutOfMemory);
655 FATAL(
"Fork could not install its prepared filesystem context");
661 clonedState.setSyscallReturnValue(0);
664 for (
size_t sig = 0; sig < PosixSubsystem::SignalDispositionCount; sig++)
668 if (flags & CLONE_CHILD_SETTID) {
681 SYSCALL_ERROR(BadAddress);
686 if (flags & CLONE_PARENT_SETTID) {
690 SYSCALL_ERROR(BadAddress);
695 pSubsystem->traceContext().setCreator(creatorTask);
696 if (pSubsystem->traceContext().prepareTask(preparedTrace) != TraceStatus::Success) {
698 SYSCALL_ERROR(OutOfMemory);
706 SYSCALL_ERROR(OutOfMemory);
711 Thread* pThread =
new Thread(pProcess, clonedState,
true, &placement);
714 SYSCALL_ERROR(OutOfMemory);
717 pThread->executionPersonality().inherit(
719 pSubsystem->namespaceContext()->publishThread(preparedUts, *pThread,
true);
720 if (pSubsystem->traceContext().publishTask(preparedTrace, *pThread) != TraceStatus::Success &&
722 FATAL(
"fork trace task publication failed");
723 pThread->setName(
"posix clone() forked thread");
724 if (flags & CLONE_SETTLS)
727 if (flags & CLONE_CHILD_CLEARTID) {
738 if (!pThread->
start()) {
739 FATAL(
"fork(): delayed child thread could not be started.");
742 vforkCompletion->wait();
745 SC_NOTICE(
" -> " << childId <<
" [new process]");
749int posix_fork(SyscallState& state) {
752 return posix_clone(state, 0, 0, 0, 0, 0);
755int posix_vfork(SyscallState& state) {
756 return posix_clone(state, CLONE_VM | CLONE_VFORK | SIGCHLD,
nullptr,
nullptr,
nullptr, 0,
true);
759int posix_execve(
const char* name,
const char** argv,
const char** env, SyscallState& state) {
761 if (!copyUserString(name, nameCopy)) {
762 SC_NOTICE(
"execve -> invalid address");
766 SC_NOTICE(
"execve(\"" << nameCopy <<
"\")");
771 ERROR(
"No subsystem for this process!");
778 size_t remaining = PosixSubsystem::MaximumExecArgumentBytes - 2 *
sizeof(uintptr_t);
779 if (nameCopy.length() >= remaining) {
780 SYSCALL_ERROR(TooBig);
783 remaining -= nameCopy.length() + 1;
784 auto snapshot = [&](
const char** pointers,
Vector<String>& output) {
785 uintptr_t cursor =
reinterpret_cast<uintptr_t
>(pointers);
787 const char* argument =
nullptr;
790 SYSCALL_ERROR(BadAddress);
796 if (remaining <=
sizeof(uintptr_t)) {
797 SYSCALL_ERROR(TooBig);
800 remaining -=
sizeof(uintptr_t);
803 if (result != PosixSubsystem::UserStringSuccess) {
804 syscallError(result == PosixSubsystem::UserStringBadAddress ? Error::BadAddress
808 remaining -= value.length() + 1;
809 output.pushBack(value);
810 if (cursor > ~uintptr_t(0) -
sizeof(uintptr_t)) {
811 SYSCALL_ERROR(BadAddress);
814 cursor +=
sizeof(uintptr_t);
818 if (!snapshot(argv, listArgv) || !snapshot(env, listEnv)) {
825 normalisePath(invokePath, nameCopy.cstr());
827 if (!pSubsystem->
invoke(invokePath.cstr(), listArgv, listEnv, state)) {
828 SC_NOTICE(
" -> execve failed in invoke");
844 SC_NOTICE(
"getppid");
849 if (!expectedParent) {
855 if (pProcess->
getParent() != expectedParent) {
860 if (pProcess->
getParent() == parent.get()) {
866int posix_gettimeofday(timeval* tv,
struct timezone* tz) {
867 SC_NOTICE(
"gettimeofday");
869 const Time::Timestamp nanoseconds = Time::getTimeNanoseconds();
871 struct timeval result = {};
872 result.tv_sec = nanoseconds / Time::Multiplier::Second;
873 result.tv_usec = (nanoseconds % Time::Multiplier::Second) / Time::Multiplier::Microsecond;
875 SYSCALL_ERROR(BadAddress);
881 const struct timezone result = {};
883 SYSCALL_ERROR(BadAddress);
891int posix_settimeofday(
const timeval* tv,
const struct timezone* tz) {
892 SC_NOTICE(
"settimeofday");
893 SYSCALL_ERROR(Unimplemented);
897time_t posix_time(time_t* tval) {
900 time_t result = Time::getTime();
902 SYSCALL_ERROR(BadAddress);
909clock_t posix_times(
struct tms* tm) {
913 constexpr Time::Timestamp nanosecondsPerClockTick = Time::Multiplier::Second / 100;
915 struct tms result = {};
916 result.tms_utime = pProcess->
getUserTime() / nanosecondsPerClockTick;
917 result.tms_stime = pProcess->getKernelTime() / nanosecondsPerClockTick;
918 result.tms_cutime = pProcess->getReapedChildrenUserTime() / nanosecondsPerClockTick;
919 result.tms_cstime = pProcess->getReapedChildrenKernelTime() / nanosecondsPerClockTick;
921 SC_NOTICE(
"posix_times -> invalid address");
922 SYSCALL_ERROR(BadAddress);
926 SC_NOTICE(
"times: u=" << pProcess->
getUserTime() <<
", s=" << pProcess->getKernelTime());
928 return Time::getTicks() / nanosecondsPerClockTick;
931int posix_getrusage(
int who,
struct rusage* r) {
932 SC_NOTICE(
"getrusage who=" << who);
934 if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN && who != RUSAGE_THREAD) {
935 SC_NOTICE(
"posix_getrusage -> unsupported selector");
936 SYSCALL_ERROR(InvalidArgument);
942 const Time::Timestamp user = who == RUSAGE_THREAD ? currentThread->
getUserTime()
943 : who == RUSAGE_CHILDREN ? pProcess->getReapedChildrenUserTime()
945 const Time::Timestamp kernel = who == RUSAGE_THREAD ? currentThread->getKernelTime()
946 : who == RUSAGE_CHILDREN ? pProcess->getReapedChildrenKernelTime()
947 : pProcess->getKernelTime();
949 struct rusage result = {};
950 result.ru_utime.tv_sec = user / Time::Multiplier::Second;
951 result.ru_utime.tv_usec = (user % Time::Multiplier::Second) / Time::Multiplier::Microsecond;
952 result.ru_stime.tv_sec = kernel / Time::Multiplier::Second;
953 result.ru_stime.tv_usec = (kernel % Time::Multiplier::Second) / Time::Multiplier::Microsecond;
956 SC_NOTICE(
"posix_getrusage -> invalid address");
957 SYSCALL_ERROR(BadAddress);
965 SC_NOTICE(
"Linux getrusage who=" << who);
967 if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN && who != RUSAGE_THREAD) {
968 SC_NOTICE(
"posix_linux_getrusage -> unsupported selector");
969 SYSCALL_ERROR(InvalidArgument);
975 const Time::Timestamp user = who == RUSAGE_THREAD ? currentThread->
getUserTime()
976 : who == RUSAGE_CHILDREN ? pProcess->getReapedChildrenUserTime()
978 const Time::Timestamp kernel = who == RUSAGE_THREAD ? currentThread->getKernelTime()
979 : who == RUSAGE_CHILDREN ? pProcess->getReapedChildrenKernelTime()
980 : pProcess->getKernelTime();
983 result.userSeconds = user / Time::Multiplier::Second;
984 result.userMicroseconds = (user % Time::Multiplier::Second) / Time::Multiplier::Microsecond;
985 result.systemSeconds = kernel / Time::Multiplier::Second;
986 result.systemMicroseconds = (kernel % Time::Multiplier::Second) / Time::Multiplier::Microsecond;
989 SC_NOTICE(
"posix_linux_getrusage -> invalid address");
990 SYSCALL_ERROR(BadAddress);
998int copyPasswd(
User* user, passwd* output,
char* userStrings) {
1003 char strings[256] = {};
1006 const uintptr_t base =
reinterpret_cast<uintptr_t
>(userStrings);
1010 char** fields[] = {&result.pw_name, &result.pw_passwd, &result.pw_gecos, &result.pw_dir,
1012 for (
size_t i = 0; i < 5; ++i) {
1013 const size_t length = values[i]->length();
1014 if (length >=
sizeof(strings) - used) {
1015 SYSCALL_ERROR(BadRange);
1018 *fields[i] =
reinterpret_cast<char*
>(base + used);
1019 MemoryCopy(strings + used, values[i]->cstr(), length + 1);
1022 result.pw_uid = user->
getId();
1026 SYSCALL_ERROR(BadAddress);
1032int copyGroup(
Group* group,
struct group* output) {
1036 struct group result = {};
1038 SYSCALL_ERROR(BadAddress);
1043 if (name.length() >= 256) {
1044 SYSCALL_ERROR(BadRange);
1047 result.gr_gid = group->
getId();
1050 SYSCALL_ERROR(BadAddress);
1057int posix_getpwent(passwd* pw,
int n,
char* str) {
1061int posix_getpwnam(passwd* pw,
const char* name,
char* str) {
1063 if (!copyUserString(name, nameCopy)) {
1069int posix_getgrnam(
const char* name,
struct group* out) {
1071 if (!copyUserString(name, nameCopy)) {
1077int posix_getgrgid(gid_t
id,
struct group* out) {
1081EXPORTED_PUBLIC
int pedigree_login(
int uid) {
1084 SYSCALL_ERROR(NotEnoughPermissions);
1088 if (process->snapshotCredentials().euid != 0) {
1089 SYSCALL_ERROR(NotEnoughPermissions);
1093 SYSCALL_ERROR(NoMoreProcesses);
1098 SYSCALL_ERROR(InvalidArgument);
1101 if (!user->
login()) {
1102 SYSCALL_ERROR(InvalidArgument);
1109mode_t posix_umask(mode_t mask) {
1110 SC_NOTICE(
"umask(" <<
Oct << mask <<
")");
1114 if (pStockProcess->getType() != Process::Posix) {
1115 SC_NOTICE(
"umask -> called on something not a POSIX process");
1116 SYSCALL_ERROR(InvalidArgument);
1122 uint32_t previous = pProcess->getMask();
1123 pProcess->setMask(mask);
1128int posix_linux_syslog(
int type,
char* buf,
int len) {
1136 return static_cast<int>(Log::textCapacity());
1137#if PEDIGREE_SYSCALL_COUNTER
1139 if (len !=
static_cast<int>(
sizeof(uint64_t))) {
1140 SYSCALL_ERROR(InvalidArgument);
1144 const uint64_t count = process->getReapedChildrenSyscallCount();
1146 SYSCALL_ERROR(BadAddress);
1149 return static_cast<int>(
sizeof(count));
1153 Process::SyscallLatencySnapshot snapshot = {};
1154 process->getReapedChildrenSyscallLatencySnapshot(snapshot);
1155 if (len !=
static_cast<int>(
sizeof(snapshot))) {
1156 SYSCALL_ERROR(InvalidArgument);
1160 SYSCALL_ERROR(BadAddress);
1163 return static_cast<int>(
sizeof(snapshot));
1166#if PEDIGREE_ACTIVITY_DIAGNOSTICS
1169 SYSCALL_ERROR(InvalidArgument);
1173 ActivityDiagnostics::snapshot(snapshot);
1175 SYSCALL_ERROR(BadAddress);
1178 return static_cast<int>(
sizeof(snapshot));
1181#if PEDIGREE_BENCHMARK_SYSCALL_TIMING
1183 if (buf || (len != 0 && len != 1)) {
1184 SYSCALL_ERROR(InvalidArgument);
1188 process->setBenchmarkSyscallTiming(len != 0);
1192 constexpr size_t snapshotSize =
1193 Process::SyscallTimingSlotCount *
sizeof(Process::SyscallTimingEntry);
1194 if (len !=
static_cast<int>(snapshotSize)) {
1195 SYSCALL_ERROR(InvalidArgument);
1199 for (
size_t i = 0; i < Process::SyscallTimingSlotCount; ++i) {
1200 Process::SyscallTimingEntry entry = {};
1201 process->getSyscallTimingEntry(i, entry);
1203 SYSCALL_ERROR(BadAddress);
1207 return static_cast<int>(snapshotSize);
1210#if PEDIGREE_BENCHMARK_VM_DIAGNOSTICS
1212 if (buf || (len != 0 && len != 1)) {
1213 SYSCALL_ERROR(InvalidArgument);
1217 process->setBenchmarkVmDiagnostics(len != 0);
1221 constexpr size_t snapshotSize = Process::BenchmarkVmCounterCount *
sizeof(uint64_t);
1222 if (len !=
static_cast<int>(snapshotSize)) {
1223 SYSCALL_ERROR(InvalidArgument);
1227 for (
size_t i = 0; i < Process::BenchmarkVmCounterCount; ++i) {
1228 const uint64_t value = process->getBenchmarkVmCounter(i);
1230 SYSCALL_ERROR(BadAddress);
1234 return static_cast<int>(snapshotSize);
1238#if PEDIGREE_BENCHMARK_SYSCALL_TRACE
1239 if (buf || (len != 0 && len != 1)) {
1240 SYSCALL_ERROR(InvalidArgument);
1244 process->setBenchmarkSyscallTrace(len != 0);
1247 SYSCALL_ERROR(Unimplemented);
1258 SYSCALL_ERROR(Unimplemented);
1261 SYSCALL_ERROR(InvalidArgument);
1266 SYSCALL_ERROR(InvalidArgument);
1271 const size_t capacity =
static_cast<size_t>(len) < Log::textCapacity() ?
static_cast<size_t>(len)
1272 :
Log::textCapacity();
1274 PosixSubsystem::SafeWrite)) {
1275 SYSCALL_ERROR(BadAddress);
1281 char* snapshot =
new char[capacity];
1283 SYSCALL_ERROR(OutOfMemory);
1290 SYSCALL_ERROR(BadAddress);
1293 return static_cast<int>(copied);
1296int posix_syslog(
const char* msg,
int prio) {
1298 if (!copyUserString(msg, msgCopy)) {
1299 SC_NOTICE(
"klog -> invalid address");
1305 if (prio <= LOG_CRIT)
1306 FATAL(
"[" <<
Dec <<
id <<
Hex <<
"]\tklog: " << msgCopy);
1309 if (prio <= LOG_ERR)
1310 ERROR(
"[" <<
Dec <<
id <<
Hex <<
"]\tklog: " << msgCopy);
1311 else if (prio == LOG_WARNING)
1312 WARNING(
"[" <<
Dec <<
id <<
Hex <<
"]\tklog: " << msgCopy);
1313 else if (prio == LOG_NOTICE || prio == LOG_INFO)
1314 NOTICE(
"[" <<
Dec <<
id <<
Hex <<
"]\tklog: " << msgCopy);
1317 NOTICE(
"[" <<
Dec <<
id <<
Hex <<
"]\tklog: " << msgCopy);
1322int posix_reboot(uint32_t magic1, uint32_t magic2, uint32_t command) {
1324 SYSCALL_ERROR(NotEnoughPermissions);
1327 if (magic1 != 0xfee1dead ||
1328 (magic2 != 672274793 && magic2 != 85072278 && magic2 != 369367448 && magic2 != 537993216)) {
1329 SYSCALL_ERROR(InvalidArgument);
1333 Machine::ShutdownType type;
1340 type = Machine::ShutdownType::Restart;
1343 type = Machine::ShutdownType::Halt;
1346 type = Machine::ShutdownType::PowerOff;
1350 SYSCALL_ERROR(InvalidArgument);
1357 if (status == Filesystem::SyncStatus::IoError || status == Filesystem::SyncStatus::NoMemory) {
1358 syscallError(status == Filesystem::SyncStatus::IoError ? Error::IoError : Error::OutOfMemory);
1362 SYSCALL_ERROR(DeviceBusy);
1368EXPORTED_PUBLIC
int pedigree_reboot() {
1369 return posix_reboot(0xfee1dead, 672274793, 0x01234567);
1372int posix_prctl(
int option, uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5) {
1373 NOTICE(
"prctl(" <<
Hex << option <<
", " << arg2 <<
", " << arg3 <<
", " << arg4 <<
", " << arg5
1377 if (option == 3 || option == 4) {
1380 SYSCALL_ERROR(InvalidArgument);
1385 return process->snapshotCredentials().dumpable ? 1 : 0;
1388 SYSCALL_ERROR(InvalidArgument);
1391 process->setDumpable(arg2 != 0);
1396 if (option == LINUX_PR_SET_NAME) {
1399 reinterpret_cast<const char*
>(arg2), requested, LINUX_TASK_NAME_LENGTH);
1400 if (result == PosixSubsystem::UserStringBadAddress) {
1401 SYSCALL_ERROR(BadAddress);
1407 const size_t length = requested.length() < (LINUX_TASK_NAME_LENGTH - 1)
1408 ? requested.length()
1409 : (LINUX_TASK_NAME_LENGTH - 1);
1410 thread->setName(
String(requested.cstr(), length,
true));
1414 if (option == LINUX_PR_GET_NAME) {
1415 char name[LINUX_TASK_NAME_LENGTH] = {};
1416 const String& current = thread->getName();
1417 const size_t length = current.length() < (LINUX_TASK_NAME_LENGTH - 1)
1419 : (LINUX_TASK_NAME_LENGTH - 1);
1420 MemoryCopy(name, current.cstr(), length);
1422 SYSCALL_ERROR(BadAddress);
1428 SYSCALL_ERROR(InvalidArgument);
1432int posix_arch_prctl(
int code,
unsigned long addr) {
1440 addr >= 0x0000800000000000ULL) {
1441 SYSCALL_ERROR(NotEnoughPermissions);
1444 current->setUserGsBase(addr);
1448 const unsigned long base = Processor::getUserGsBase();
1450 SYSCALL_ERROR(BadAddress);
1459 || addr >= 0x0000800000000000ULL
1462 SYSCALL_ERROR(NotEnoughPermissions);
1469 const unsigned long base = current->
getTlsBase();
1471 SYSCALL_ERROR(BadAddress);
1478 SYSCALL_ERROR(InvalidArgument);
1489 SYSCALL_ERROR(Interrupted);
1493int posix_membarrier(
int command,
unsigned int flags,
int cpuId) {
1494 SC_NOTICE(
"membarrier(" <<
Dec << command <<
", " << flags <<
", " << cpuId <<
")");
1498 if (command == 0 && flags == 0) {
1502 SYSCALL_ERROR(InvalidArgument);
1506int posix_getpriority(
int which,
int who,
bool linuxAbi) {
1507 SC_NOTICE(
"getpriority(" << which <<
", " <<
Dec << who <<
")");
1508 if (which != PRIO_PROCESS && which != PRIO_PGRP && which != PRIO_USER) {
1509 SYSCALL_ERROR(InvalidArgument);
1513 SYSCALL_ERROR(NoSuchProcess);
1519 SYSCALL_ERROR(NoSuchProcess);
1525 const int priority = linuxAbi ? 20 : 0;
1526 if (which == PRIO_PROCESS) {
1527 if (!who ||
static_cast<size_t>(who) == caller->
getUserspaceId()) {
1531 if (
Scheduler::instance().acquireProcessByUserspaceId(candidate,
static_cast<size_t>(who)) &&
1532 candidate->getType() == Process::Posix && candidate->getState() !=
Process::Reaped) {
1535 SYSCALL_ERROR(NoSuchProcess);
1539 if (which == PRIO_USER) {
1540 if (!who ||
static_cast<int64_t
>(who) == caller->
getUserId()) {
1545 SYSCALL_ERROR(Unimplemented);
1549 size_t callerGroup = 0;
1550 const bool hasCallerGroup = caller->getProcessGroupId(callerGroup);
1551 if (hasCallerGroup && (!who ||
static_cast<size_t>(who) == callerGroup)) {
1555 SYSCALL_ERROR(Unimplemented);
1559 SYSCALL_ERROR(NoSuchProcess);
1563int posix_setpriority(
int which,
int who,
int prio) {
1565 SC_NOTICE(
"setpriority(" << which <<
", " <<
Dec << who <<
", " << prio <<
")");
1569int posix_get_robust_list(
int pid,
struct robust_list_head** head_ptr,
size_t* len_ptr,
1571 SC_NOTICE(
"get_robust_list");
1573 Thread* target = current;
1575 const size_t currentId = linuxAbi ? current->
getTaskId() : current->
getId();
1576 if (pid < 0 || (pid &&
static_cast<size_t>(pid) != currentId &&
1578 : current->getParent()->acquireThreadById(targetLease, pid)))) {
1579 SYSCALL_ERROR(NoSuchProcess);
1583 target = targetLease.get();
1588 SYSCALL_ERROR(NotEnoughPermissions);
1592 auto* head =
reinterpret_cast<struct robust_list_head*
>(target->getRobustList());
1593 const size_t length = 3 *
sizeof(uintptr_t);
1596 SYSCALL_ERROR(BadAddress);
1602int posix_set_robust_list(
struct robust_list_head* head,
size_t len,
bool linuxAbi) {
1603 SC_NOTICE(
"set_robust_list");
1605 if (len != 3 *
sizeof(uintptr_t)) {
1606 SYSCALL_ERROR(InvalidArgument);
1613 current->setRobustList(
reinterpret_cast<uintptr_t
>(head),
1614 linuxAbi ? current->
getTaskId() : current->getId());
1619int posix_ioperm(
unsigned long from,
unsigned long num,
int turn_on) {
1620 SC_NOTICE(
"ioperm(" << from <<
", " << num <<
", " << turn_on <<
")");
1627int posix_iopl(
int level) {
1628 SC_NOTICE(
"iopl(" << level <<
")");
1636constexpr Time::Timestamp MaximumLinuxTimerNanoseconds = 0x7FFFFFFFFFFFFFFFULL;
1641 return &process->getRealIntervalTimer();
1642 case ITIMER_VIRTUAL:
1643 return &process->getVirtualIntervalTimer();
1645 return &process->getProfileIntervalTimer();
1651bool validIntervalTimeval(
const struct timeval& value) {
1652 return value.tv_sec >= 0 && value.tv_usec >= 0 && value.tv_usec < 1000000;
1655Time::Timestamp intervalTimevalToNanoseconds(
const struct timeval& value) {
1656 const Time::Timestamp microseconds =
1657 static_cast<Time::Timestamp
>(value.tv_usec) * Time::Multiplier::Microsecond;
1658 const Time::Timestamp seconds =
static_cast<Time::Timestamp
>(value.tv_sec);
1659 if (seconds >= MaximumLinuxTimerNanoseconds / Time::Multiplier::Second) {
1660 return MaximumLinuxTimerNanoseconds;
1662 return seconds * Time::Multiplier::Second + microseconds;
1665struct itimerval intervalTimerToUser(Time::
Timestamp interval, Time::Timestamp value) {
1666 struct itimerval result = {};
1667 result.it_interval.tv_sec = interval / Time::Multiplier::Second;
1668 result.it_interval.tv_usec =
1669 (interval % Time::Multiplier::Second) / Time::Multiplier::Microsecond;
1670 result.it_value.tv_sec = value / Time::Multiplier::Second;
1671 result.it_value.tv_usec = (value % Time::Multiplier::Second) / Time::Multiplier::Microsecond;
1676int posix_getitimer(
int which,
struct itimerval* curr_value) {
1677 SC_NOTICE(
"posix_getitimer(" << which <<
", " << curr_value <<
")");
1682 Time::Timestamp interval = 0;
1683 Time::Timestamp value = 0;
1685 IntervalTimer* itimer = selectIntervalTimer(pProcess, which);
1687 SYSCALL_ERROR(InvalidArgument);
1691 if (which != ITIMER_REAL) {
1692 currentThread->
trackTime(CpuTimeMode::Kernel);
1694 itimer->getIntervalAndValue(interval, value);
1696 const struct itimerval result = intervalTimerToUser(interval, value);
1698 SYSCALL_ERROR(BadAddress);
1702 SC_NOTICE(
" -> period = " <<
Dec << result.it_interval.tv_sec <<
"s "
1703 << result.it_interval.tv_usec <<
"us");
1704 SC_NOTICE(
" -> value = " <<
Dec << result.it_value.tv_sec <<
"s " << result.it_value.tv_usec
1710int posix_setitimer(
int which,
const struct itimerval* new_value,
struct itimerval* old_value) {
1711 SC_NOTICE(
"posix_setitimer(" << which <<
", " << new_value <<
", " << old_value <<
")");
1713 struct itimerval requested = {};
1715 SYSCALL_ERROR(BadAddress);
1718 if (!validIntervalTimeval(requested.it_interval) || !validIntervalTimeval(requested.it_value)) {
1719 SYSCALL_ERROR(InvalidArgument);
1723 SC_NOTICE(
" -> period = " <<
Dec << requested.it_interval.tv_sec <<
"s "
1724 << requested.it_interval.tv_usec <<
"us");
1725 SC_NOTICE(
" -> value = " <<
Dec << requested.it_value.tv_sec <<
"s " << requested.it_value.tv_usec
1731 const Time::Timestamp interval = intervalTimevalToNanoseconds(requested.it_interval);
1732 const Time::Timestamp value = intervalTimevalToNanoseconds(requested.it_value);
1733 Time::Timestamp prevInterval = 0;
1734 Time::Timestamp prevValue = 0;
1736 IntervalTimer* itimer = selectIntervalTimer(pProcess, which);
1738 SYSCALL_ERROR(InvalidArgument);
1742 if (which != ITIMER_REAL) {
1743 currentThread->
trackTime(CpuTimeMode::Kernel);
1748 const struct itimerval previous = intervalTimerToUser(prevInterval, prevValue);
1750 SYSCALL_ERROR(BadAddress);
1758int posix_capget(
void* hdrp,
void* datap) {
1759 if (!getPosixProcess()) {
1764 SYSCALL_ERROR(BadAddress);
1767 if (header.version != _LINUX_CAPABILITY_VERSION_1) {
1768 const uint32_t version = _LINUX_CAPABILITY_VERSION_1;
1770 SYSCALL_ERROR(BadAddress);
1773 SYSCALL_ERROR(InvalidArgument);
1777 const cap_data data = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF};
1779 SYSCALL_ERROR(BadAddress);
1786int posix_capset(
void* hdrp,
const void* datap) {
1789 SYSCALL_ERROR(BadAddress);
1792 if (header.version != _LINUX_CAPABILITY_VERSION_1) {
1793 const uint32_t version = _LINUX_CAPABILITY_VERSION_1;
1795 SYSCALL_ERROR(BadAddress);
1798 SYSCALL_ERROR(InvalidArgument);
1803 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)
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 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
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