The Pedigree Project 0.1
system-syscalls.cc
1/*
2 * Copyright (c) 2008-2014, Pedigree Developers
3 *
4 * Please see the CONTRIB file in the root of the source tree for a full
5 * list of contributors.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
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"
46
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"
59
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"
64
65#include <PosixProcess.h>
66#include <PosixSubsystem.h>
67#include <grp.h>
68#include <limits.h>
69#include <pwd.h>
70#include <sched.h>
71#include <syslog.h>
72
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>
79#include <sys/times.h>
80#include <sys/utsname.h>
81#include <sys/wait.h>
82
83#if X64 && !HOSTED
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");
91#endif
92
93// arch_prctl
94#define ARCH_SET_GS 0x1001
95#define ARCH_SET_FS 0x1002
96#define ARCH_GET_FS 0x1003
97#define ARCH_GET_GS 0x1004
98
99// Linux prctl operations used by musl's current-thread naming helpers.
100#define LINUX_PR_SET_NAME 15
101#define LINUX_PR_GET_NAME 16
102#define LINUX_TASK_NAME_LENGTH 16
103
104// capget/capset
105#define _LINUX_CAPABILITY_VERSION_1 0x19980330
106
107#define LINUX_GRND_NONBLOCK 0x1
108#define LINUX_GRND_RANDOM 0x2
109
110namespace {
111class CloneInterruptScope {
112 public:
113 explicit CloneInterruptScope(bool enabled = false) : m_Previous(Processor::getInterrupts()) {
115 }
116
117 ~CloneInterruptScope() {
118 Processor::setInterrupts(m_Previous);
119 }
120
121 private:
122 bool m_Previous;
123};
124
125enum class CloneRoute { Process, Vfork, Thread, Invalid };
126
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;
137
138 if (flags & CLONE_THREAD) {
139 if ((flags & ExitSignalMask) || (flags & ThreadRequired) != ThreadRequired ||
140 (flags & ~ThreadAllowed)) {
141 return CloneRoute::Invalid;
142 }
143 return CloneRoute::Thread;
144 }
145
146 // Process sharing is limited to vfork's bounded borrow. Other sharing and
147 // namespace combinations must not silently receive fork semantics.
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;
153 }
154 return CloneRoute::Invalid;
155}
156} // namespace
157
158#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
159namespace {
160using CloneBeforeStartHook = void (*)(Thread*, size_t, void*);
161
162CloneBeforeStartHook g_CloneBeforeStartHook = nullptr;
163void* g_CloneBeforeStartHookContext = nullptr;
164} // namespace
165
166extern "C" EXPORTED_PUBLIC void posixSetCloneBeforeStartHookForTest(CloneBeforeStartHook hook,
167 void* context) {
168 if (hook) {
169 __atomic_store_n(&g_CloneBeforeStartHookContext, context, __ATOMIC_RELEASE);
170 __atomic_store_n(&g_CloneBeforeStartHook, hook, __ATOMIC_RELEASE);
171 } else {
172 __atomic_store_n(&g_CloneBeforeStartHook, static_cast<CloneBeforeStartHook>(nullptr),
173 __ATOMIC_RELEASE);
174 __atomic_store_n(&g_CloneBeforeStartHookContext, static_cast<void*>(nullptr), __ATOMIC_RELEASE);
175 }
176}
177
178extern "C" EXPORTED_PUBLIC int posixCloneRouteForTest(unsigned long flags) {
179 switch (cloneRoute(flags)) {
180 case CloneRoute::Process:
181 return 0;
182 case CloneRoute::Thread:
183 return 1;
184 case CloneRoute::Vfork:
185 return 2;
186 case CloneRoute::Invalid:
187 return -1;
188 }
189
190 return -1;
191}
192#endif
193
195 uint32_t version;
196 int pid;
197};
198
199struct cap_data {
200 uint32_t effective;
201 uint32_t permitted;
202 uint32_t inheritable;
203};
204
205//
206// Syscalls pertaining to system operations.
207//
208
209static PosixProcess* getPosixProcess() {
210 // Not a POSIX process
211 Process* pStockProcess = Processor::information().getCurrentThread()->getParent();
212 if (pStockProcess->getType() != Process::Posix) {
213 return nullptr;
214 }
215
216 return static_cast<PosixProcess*>(pStockProcess);
217}
218
219static bool copyUserString(const char* userString, String& copy) {
220 PosixSubsystem::UserStringResult result =
221 PosixSubsystem::copyUserString(userString, copy, PATH_MAX);
222 if (result == PosixSubsystem::UserStringBadAddress) {
223 SYSCALL_ERROR(BadAddress);
224 return false;
225 }
226 if (result == PosixSubsystem::UserStringTooLong) {
227 SYSCALL_ERROR(NameTooLong);
228 return false;
229 }
230 return true;
231}
232
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);
236 return -1;
237 }
238
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);
244 return -1;
245 }
246 const bool copied = PosixSubsystem::copyToUser(buffer, snapshot, produced);
247 pedigree_random::erase(snapshot, sizeof(snapshot));
248 if (!copied) {
249 SYSCALL_ERROR(BadAddress);
250 return -1;
251 }
252 return static_cast<ssize_t>(produced);
253}
254
256static size_t save_string_array(const char** array, Vector<SharedPointer<String>>& rArray) {
257 size_t result = 0;
258 while (*array) {
259 String* pStr = new String(*array);
260 rArray.pushBack(SharedPointer<String>(pStr));
261 array++;
262
263 result += pStr->length() + 1;
264 }
265
266 return result;
267}
268
272static char** load_string_array(Vector<SharedPointer<String>>& rArray, uintptr_t arrayLoc,
273 uintptr_t& arrayEndLoc) {
274 char** pMasterArray = reinterpret_cast<char**>(arrayLoc);
275
276 char* pPtr = reinterpret_cast<char*>(arrayLoc + sizeof(char*) * (rArray.count() + 1));
277 int i = 0;
278 for (auto it = rArray.begin(); it != rArray.end(); it++) {
279 const String* pStr = it->get();
280
281 StringCopy(pPtr, pStr->cstr());
282 pPtr[pStr->length()] = '\0'; // Ensure NULL-termination.
283
284 pMasterArray[i] = pPtr;
285
286 pPtr += pStr->length() + 1;
287 i++;
288 }
289
290 pMasterArray[i] = 0; // Null terminate.
291 arrayEndLoc = reinterpret_cast<uintptr_t>(pPtr);
292
293 return pMasterArray;
294}
295
296long posix_sbrk(int delta) {
297 SC_NOTICE("sbrk(" << delta << ")");
298
299 long ret = reinterpret_cast<long>(Processor::information().getVirtualAddressSpace().expandHeap(
301 SC_NOTICE(" -> " << ret);
302 if (ret == 0) {
303 SYSCALL_ERROR(OutOfMemory);
304 return -1;
305 } else
306 return ret;
307}
308
309uintptr_t posix_brk(uintptr_t theBreak) {
310 SC_NOTICE("brk(" << theBreak << ")");
312 auto& space = Processor::information().getVirtualAddressSpace();
313 const uintptr_t current = reinterpret_cast<uintptr_t>(space.getEndOfHeap());
314 // The Linux syscall returns the unchanged break on failed growth. Musl's
315 // allocator compares this value with the requested address.
316 Processor::information().getCurrentThread()->setErrno(0);
317 if (theBreak <= current || theBreak - current > static_cast<uintptr_t>(INTPTR_MAX))
318 return current;
319 if (!space.expandHeap(static_cast<intptr_t>(theBreak - current), VirtualAddressSpace::Write)) {
320 Processor::information().getCurrentThread()->setErrno(0);
321 return current;
322 }
323 return reinterpret_cast<uintptr_t>(space.getEndOfHeap());
324}
325
326SyscallState posix_copy_clone_state(const SyscallState& state) {
327#if X64 && !HOSTED
328 // The child's frame must own its metadata before it leaves this CPU.
329 state.getUserEntryMetadata();
330#endif
331 SyscallState clonedState = state;
332#if HOSTED
333 // The hosted bridge's errno destination is stack-local to the parent's
334 // translator frame and cannot survive in the child return state.
335 clonedState.error_ptr = 0;
336#endif
337 return clonedState;
338}
339
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 << ", "
343 << newtls << ")");
344
345 Process* pParentProcess = Processor::information().getCurrentThread()->getParent();
346 Process::ThreadCreationScope creation(*pParentProcess);
347 if (!creation) {
348 SYSCALL_ERROR(NoMoreProcesses);
349 return -1;
350 }
351
352 // Allocation and the mapping policy may wait. Low-level page-table changes
353 // provide their own short critical sections; restore the caller's IRQ state.
354 CloneInterruptScope interrupts(true);
355
356 // Must clone state as we make modifications for the new thread here.
357 SyscallState clonedState = posix_copy_clone_state(state);
358
359 // Basic warnings to start with.
360 if (flags & CLONE_PARENT) {
361 SC_NOTICE(" -> CLONE_PARENT is not yet supported!");
362 }
363
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)");
368 return -1;
369 }
370 if (route == CloneRoute::Thread && pParentProcess->isVforkChild()) {
371 // Detach is owned by the sole child thread; it cannot strand peers in
372 // the borrowed image when exec or exit wakes the creator.
373 SYSCALL_ERROR(InvalidArgument);
374 return -1;
375 }
376
377 if (route != CloneRoute::Thread &&
378 (flags & (CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_SETTLS))) {
380 MemoryMapManager::OperationGuard mappingGuard(mappings);
381 auto writableId = [&](int* address) {
382 const uintptr_t target = reinterpret_cast<uintptr_t>(address);
383 return PosixSubsystem::checkAddress(target, sizeof(int), PosixSubsystem::SafeWrite) &&
384 mappings.faultIn(target, true) && mappings.faultIn(target + sizeof(int) - 1, true);
385 };
386 if (((flags & CLONE_PARENT_SETTID) && !writableId(ptid)) ||
387 ((flags & CLONE_CHILD_SETTID) && !writableId(ctid))) {
388 SYSCALL_ERROR(BadAddress);
389 return -1;
390 }
391 if ((flags & CLONE_SETTLS) && (newtls >= pParentProcess->getAddressSpace()->getKernelStart()
392#if X64
393 || newtls >= 0x0000800000000000ULL
394#endif
395 )) {
396 SYSCALL_ERROR(NotEnoughPermissions);
397 return -1;
398 }
399 }
400
401 PosixSubsystem* creatorSubsystem = getSubsystem();
402 TraceCloneAdmission traceCreation;
403 TraceTaskRef creatorTask;
405 if (!creatorSubsystem || !creatorSubsystem->traceContext().taskToken(
406 *Processor::information().getCurrentThread(), creatorTask)) {
407 SYSCALL_ERROR(NoSuchProcess);
408 return -1;
409 }
410 if (route == CloneRoute::Thread) {
411 if (creatorSubsystem->traceContext().reserveThreadCreation(traceCreation) !=
412 TraceStatus::Success) {
413 SYSCALL_ERROR(OperationNotSupported);
414 return -1;
415 }
416 if (creatorSubsystem->traceContext().prepareTask(preparedTrace) != TraceStatus::Success) {
417 SYSCALL_ERROR(OutOfMemory);
418 return -1;
419 }
420 }
421 auto creatorNamespaces = creatorSubsystem ? creatorSubsystem->namespaceContext()
423 UtsRef creatorUts;
425 if (!creatorNamespaces ||
426 !creatorNamespaces->acquireThread(*Processor::information().getCurrentThread(), creatorUts))
427 return posix_uts_error(UtsStatus::Missing);
428 UtsStatus utsPrepared;
429 {
431 if ((flags & CLONE_NEWUTS) && getPosixProcess()->snapshotCredentials().euid != 0) {
432 SYSCALL_ERROR(NotEnoughPermissions);
433 return -1;
434 }
435 utsPrepared = posix_uts_prepare_thread(creatorUts, flags & CLONE_NEWUTS, preparedUts);
436 }
437 if (utsPrepared != UtsStatus::Success)
438 return posix_uts_error(utsPrepared);
439
440 const ThreadPlacement placement =
441 ThreadPlacement::inherit(*Processor::information().getCurrentThread());
442
443 if (route == CloneRoute::Thread) {
444 // clone vm doesn't actually copy the address space, it shares it
445
446 // New child's stack. Must be valid as we're sharing the address space.
447 if (!child_stack) {
448 SYSCALL_ERROR(InvalidArgument);
449 return -1;
450 }
451
452 // Set up stack for new thread.
453 clonedState.setStackPointer(reinterpret_cast<uintptr_t>(child_stack));
454
455 // Child returns 0 -- parent returns the new thread ID.
456 clonedState.setSyscallReturnValue(0);
457
458 Thread* pThread = nullptr;
459 size_t threadId = 0;
460 bool copiedIds = false;
461 {
463 MemoryMapManager::OperationGuard mappingGuard(mappings);
464 auto writableId = [&](int* address) {
465 const uintptr_t target = reinterpret_cast<uintptr_t>(address);
466 return PosixSubsystem::checkAddress(target, sizeof(int), PosixSubsystem::SafeWrite) &&
467 mappings.faultIn(target, true) && mappings.faultIn(target + sizeof(int) - 1, true);
468 };
469 if (((flags & CLONE_CHILD_SETTID) && !writableId(ctid)) ||
470 ((flags & CLONE_PARENT_SETTID) && !writableId(ptid))) {
471 SYSCALL_ERROR(BadAddress);
472 return -1;
473 }
474 const bool setTls = !linuxAbi || (flags & CLONE_SETTLS);
475 if (setTls && (newtls >= pParentProcess->getAddressSpace()->getKernelStart()
476#if X64
477 || newtls >= 0x0000800000000000ULL
478#endif
479 )) {
480 SYSCALL_ERROR(NotEnoughPermissions);
481 return -1;
482 }
483 // The native ABI initializes its TLS self pointer. Linux supplies an
484 // opaque FS base and owns initialization of any memory it points to.
485 if (!linuxAbi &&
486 !PosixSubsystem::copyToUser(reinterpret_cast<void*>(newtls), &newtls, sizeof(newtls))) {
487 SYSCALL_ERROR(BadAddress);
488 return -1;
489 }
490
491 pThread = new Thread(pParentProcess, clonedState, true, &placement);
492 if (!pThread) {
493 SYSCALL_ERROR(OutOfMemory);
494 return -1;
495 }
496 pThread->executionPersonality().inherit(
497 Processor::information().getCurrentThread()->executionPersonality());
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");
504 if (setTls) {
505 pThread->setTlsBase(newtls);
506 }
507 threadId = linuxAbi ? pThread->getTaskId() : pThread->getId();
508 }
509 {
510 CloneInterruptScope enabled(true);
511 if (!posix_sem_clone(Processor::information().getCurrentThread(), pThread,
512 flags & CLONE_SYSVSEM)) {
514 pThread->startDetached();
515 SYSCALL_ERROR(OutOfMemory);
516 return -1;
517 }
518 }
519 const int id = static_cast<int>(threadId);
520 copiedIds =
521 (!(flags & CLONE_CHILD_SETTID) || PosixSubsystem::copyToUser(ctid, &id, sizeof(id))) &&
522 (!(flags & CLONE_PARENT_SETTID) || PosixSubsystem::copyToUser(ptid, &id, sizeof(id)));
523 if (copiedIds && (flags & CLONE_CHILD_CLEARTID)) {
524 pThread->setClearChildTid(reinterpret_cast<uintptr_t>(ctid));
525 }
526 if (!copiedIds) {
527 // The existing delayed-start cancellation path owns retirement. A
528 // published Thread cannot be deleted directly on this error path.
530 pThread->startDetached();
531 SYSCALL_ERROR(BadAddress);
532 return -1;
533 }
534
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);
538 if (hook) {
539 hook(pThread, threadId, hookContext);
540 }
541#endif
542
543 if (!pThread->startDetached()) {
544 FATAL("clone(): delayed thread could not be started.");
545 }
546
547 // Parent gets the new thread ID.
548 SC_NOTICE(" -> " << threadId << " [new thread]");
549 return threadId;
550 }
551
553 const bool borrowAddressSpace = route == CloneRoute::Vfork;
554 if (borrowAddressSpace) {
555 vforkCompletion =
557 if (!vforkCompletion) {
558 SYSCALL_ERROR(OutOfMemory);
559 return -1;
560 }
561 }
562
563 // A vfork caller may borrow its current stack; clone wrappers supply one.
564 if (child_stack) {
565 clonedState.setStackPointer(reinterpret_cast<uintptr_t>(child_stack));
566 }
567
568 PosixSubsystem* pParentSubsystem = static_cast<PosixSubsystem*>(pParentProcess->getSubsystem());
569 if (!pParentSubsystem) {
570 ERROR("No subsystem for the parent process!");
571 SYSCALL_ERROR(InvalidArgument);
572 return -1;
573 }
574
575 // Enrollment precedes MM admission. Pivot updates this unpublished context
576 // too; any rollback retires its owner after the mapping guard has unwound.
577 FilesystemContextOwner childFilesystem;
578 auto parentFilesystem = pParentProcess->acquireFilesystemContext();
579 if (!parentFilesystem || !parentFilesystem->forkForProcess(childFilesystem)) {
580 SYSCALL_ERROR(OutOfMemory);
581 return -1;
582 }
583
584 // Inhibit signals to the parent
585 for (size_t sig = 0; sig < PosixSubsystem::SignalDispositionCount; sig++)
586 Processor::information().getCurrentThread()->inhibitEvent(sig, true);
587
588 PosixProcess* pProcess;
589 PosixSubsystem* pSubsystem;
590 {
591 // PTEs, raw allocation inventory, and managed metadata describe one snapshot.
593 pProcess = new PosixProcess(pParentProcess, true, Process::FilesystemContextMode::Deferred,
594 borrowAddressSpace);
595 if (!pProcess || !pProcess->getAddressSpace() || !pProcess->jobControlReady()) {
596 delete pProcess;
597 for (size_t sig = 0; sig < PosixSubsystem::SignalDispositionCount; sig++)
598 Processor::information().getCurrentThread()->inhibitEvent(sig, false);
599 SYSCALL_ERROR(OutOfMemory);
600 SC_NOTICE(" -> ENOMEM");
601 return -1;
602 }
603
604 pSubsystem = new PosixSubsystem(*pParentSubsystem, clearSignalHandlers);
605 if (!pSubsystem || !pSubsystem->namespaceContext() ||
606 !pSubsystem->namespaceContext()->valid()) {
607 if (pSubsystem)
608 pProcess->setSubsystem(pSubsystem);
609 ERROR("Could not create a subsystem for the child process!");
610 delete pProcess;
611
612 SYSCALL_ERROR(OutOfMemory);
613
614 // Allow signals again, something went wrong
615 for (size_t sig = 0; sig < PosixSubsystem::SignalDispositionCount; sig++)
616 Processor::information().getCurrentThread()->inhibitEvent(sig, false);
617 SC_NOTICE(" -> ENOMEM");
618 return -1;
619 }
620 pProcess->setSubsystem(pSubsystem);
621 pSubsystem->setProcess(pProcess);
622
623 // Copy POSIX Process Group information if needed
624 if (pParentProcess->getType() == Process::Posix) {
625 PosixProcess* p = static_cast<PosixProcess*>(pParentProcess);
626
627 // Do not adopt leadership status.
628 if (p->getGroupMembership() == PosixProcess::Leader) {
629 SC_NOTICE("fork parent was a group leader.");
630 } else {
631 SC_NOTICE("fork parent had status " << static_cast<int>(p->getGroupMembership()) << "...");
632 }
633 pProcess->inheritProcessGroup(p);
634 }
635
636 // Register with the dynamic linker.
637 DynamicLinker* oldLinker = pProcess->getLinker();
638 if (oldLinker) {
639 DynamicLinker* newLinker = new DynamicLinker(*oldLinker);
640 pProcess->setLinker(newLinker);
641 }
642
643 if (borrowAddressSpace) {
644 pProcess->borrowVforkAddressSpace(*pParentProcess, vforkCompletion);
645 } else if (!MemoryMapManager::instance().clone(pProcess)) {
646 delete pProcess;
647 for (size_t sig = 0; sig < PosixSubsystem::SignalDispositionCount; ++sig)
648 Processor::information().getCurrentThread()->inhibitEvent(sig, false);
649 SYSCALL_ERROR(OutOfMemory);
650 return -1;
651 }
652 }
653
654 if (!pProcess->installFilesystemContext(pedigree_std::move(childFilesystem)))
655 FATAL("Fork could not install its prepared filesystem context");
656
657 // Copy the file descriptors from the parent
658 pSubsystem->copyDescriptors(pParentSubsystem);
659
660 // Child returns 0.
661 clonedState.setSyscallReturnValue(0);
662
663 // Allow signals to the parent again
664 for (size_t sig = 0; sig < PosixSubsystem::SignalDispositionCount; sig++)
665 Processor::information().getCurrentThread()->inhibitEvent(sig, false);
666
667 // Set ctid in the new address space if we are required to.
668 if (flags & CLONE_CHILD_SETTID) {
669 VirtualAddressSpace& curr = Processor::information().getVirtualAddressSpace();
670 VirtualAddressSpace* va = pProcess->getAddressSpace();
671 const int childId = static_cast<int>(pProcess->getUserspaceId());
672 bool copied = false;
673 {
676 copied = PosixSubsystem::copyToUser(ctid, &childId, sizeof(childId));
678 }
679 if (!copied) {
680 delete pProcess;
681 SYSCALL_ERROR(BadAddress);
682 return -1;
683 }
684 }
685
686 if (flags & CLONE_PARENT_SETTID) {
687 const int childId = static_cast<int>(pProcess->getUserspaceId());
688 if (!PosixSubsystem::copyToUser(ptid, &childId, sizeof(childId))) {
689 delete pProcess;
690 SYSCALL_ERROR(BadAddress);
691 return -1;
692 }
693 }
694
695 pSubsystem->traceContext().setCreator(creatorTask);
696 if (pSubsystem->traceContext().prepareTask(preparedTrace) != TraceStatus::Success) {
697 delete pProcess;
698 SYSCALL_ERROR(OutOfMemory);
699 return -1;
700 }
701
702 // The process is still unpublished, so this image is not remotely reachable
703 // until its remaining thread state is assembled and publish() runs below.
704 if (!pSubsystem->publishUserImage(*pProcess->getAddressSpace())) {
705 delete pProcess;
706 SYSCALL_ERROR(OutOfMemory);
707 return -1;
708 }
709
710 // Create a new thread for the new process.
711 Thread* pThread = new Thread(pProcess, clonedState, true, &placement);
712 if (!pThread) {
713 delete pProcess;
714 SYSCALL_ERROR(OutOfMemory);
715 return -1;
716 }
717 pThread->executionPersonality().inherit(
718 Processor::information().getCurrentThread()->executionPersonality());
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)
725 pThread->setTlsBase(newtls);
726 pThread->detach();
727 if (flags & CLONE_CHILD_CLEARTID) {
728 // The exit hook clears this before releasing a borrowed vfork image.
729 pThread->setClearChildTid(reinterpret_cast<uintptr_t>(ctid));
730 }
731
732 // Finish publishing the child-side POSIX state before it can execute.
733 pedigree_copy_posix_thread(Processor::information().getCurrentThread(), pParentSubsystem, pThread,
734 pSubsystem);
735 const size_t childId = pProcess->getUserspaceId();
736 Uninterruptible parentEvents;
737 pProcess->publish();
738 if (!pThread->start()) {
739 FATAL("fork(): delayed child thread could not be started.");
740 }
741 if (vforkCompletion)
742 vforkCompletion->wait();
743
744 // Parent returns child ID.
745 SC_NOTICE(" -> " << childId << " [new process]");
746 return childId;
747}
748
749int posix_fork(SyscallState& state) {
750 SC_NOTICE("fork");
751
752 return posix_clone(state, 0, 0, 0, 0, 0);
753}
754
755int posix_vfork(SyscallState& state) {
756 return posix_clone(state, CLONE_VM | CLONE_VFORK | SIGCHLD, nullptr, nullptr, nullptr, 0, true);
757}
758
759int posix_execve(const char* name, const char** argv, const char** env, SyscallState& state) {
760 String nameCopy;
761 if (!copyUserString(name, nameCopy)) {
762 SC_NOTICE("execve -> invalid address");
763 return -1;
764 }
765
766 SC_NOTICE("execve(\"" << nameCopy << "\")");
767
768 Process* pProcess = Processor::information().getCurrentThread()->getParent();
769 PosixSubsystem* pSubsystem = static_cast<PosixSubsystem*>(pProcess->getSubsystem());
770 if (!pSubsystem) {
771 ERROR("No subsystem for this process!");
772 return -1;
773 }
774
775 Vector<String> listArgv, listEnv;
776 {
778 size_t remaining = PosixSubsystem::MaximumExecArgumentBytes - 2 * sizeof(uintptr_t);
779 if (nameCopy.length() >= remaining) {
780 SYSCALL_ERROR(TooBig);
781 return -1;
782 }
783 remaining -= nameCopy.length() + 1;
784 auto snapshot = [&](const char** pointers, Vector<String>& output) {
785 uintptr_t cursor = reinterpret_cast<uintptr_t>(pointers);
786 while (cursor) {
787 const char* argument = nullptr;
788 if (!PosixSubsystem::copyFromUser(&argument, reinterpret_cast<void*>(cursor),
789 sizeof(argument))) {
790 SYSCALL_ERROR(BadAddress);
791 return false;
792 }
793 if (!argument) {
794 return true;
795 }
796 if (remaining <= sizeof(uintptr_t)) {
797 SYSCALL_ERROR(TooBig);
798 return false;
799 }
800 remaining -= sizeof(uintptr_t);
801 String value;
802 const auto result = PosixSubsystem::copyUserString(argument, value, remaining);
803 if (result != PosixSubsystem::UserStringSuccess) {
804 syscallError(result == PosixSubsystem::UserStringBadAddress ? Error::BadAddress
805 : Error::TooBig);
806 return false;
807 }
808 remaining -= value.length() + 1;
809 output.pushBack(value);
810 if (cursor > ~uintptr_t(0) - sizeof(uintptr_t)) {
811 SYSCALL_ERROR(BadAddress);
812 return false;
813 }
814 cursor += sizeof(uintptr_t);
815 }
816 return true;
817 };
818 if (!snapshot(argv, listArgv) || !snapshot(env, listEnv)) {
819 return -1;
820 }
821 }
822
823 // Normalise path to ensure we have the correct path to invoke.
824 String invokePath;
825 normalisePath(invokePath, nameCopy.cstr());
826
827 if (!pSubsystem->invoke(invokePath.cstr(), listArgv, listEnv, state)) {
828 SC_NOTICE(" -> execve failed in invoke");
829 return -1;
830 }
831
832 // Technically, we never get here.
833 return 0;
834}
835
836int posix_getpid() {
837 SC_NOTICE("getpid");
838
839 Process* pProcess = Processor::information().getCurrentThread()->getParent();
840 return pProcess->getUserspaceId();
841}
842
843int posix_getppid() {
844 SC_NOTICE("getppid");
845
846 Process* pProcess = Processor::information().getCurrentThread()->getParent();
847 while (true) {
848 Process* expectedParent = pProcess->getParent();
849 if (!expectedParent) {
850 return 0;
851 }
852
854 if (!Scheduler::instance().acquireProcess(parent, expectedParent)) {
855 if (pProcess->getParent() != expectedParent) {
856 continue;
857 }
858 return 0;
859 }
860 if (pProcess->getParent() == parent.get()) {
861 return parent->getUserspaceId();
862 }
863 }
864}
865
866int posix_gettimeofday(timeval* tv, struct timezone* tz) {
867 SC_NOTICE("gettimeofday");
868
869 const Time::Timestamp nanoseconds = Time::getTimeNanoseconds();
870 if (tv) {
871 struct timeval result = {};
872 result.tv_sec = nanoseconds / Time::Multiplier::Second;
873 result.tv_usec = (nanoseconds % Time::Multiplier::Second) / Time::Multiplier::Microsecond;
874 if (!PosixSubsystem::copyToUser(tv, &result, sizeof(result))) {
875 SYSCALL_ERROR(BadAddress);
876 return -1;
877 }
878 }
879
880 if (tz) {
881 const struct timezone result = {};
882 if (!PosixSubsystem::copyToUser(tz, &result, sizeof(result))) {
883 SYSCALL_ERROR(BadAddress);
884 return -1;
885 }
886 }
887
888 return 0;
889}
890
891int posix_settimeofday(const timeval* tv, const struct timezone* tz) {
892 SC_NOTICE("settimeofday");
893 SYSCALL_ERROR(Unimplemented);
894 return -1;
895}
896
897time_t posix_time(time_t* tval) {
898 SC_NOTICE("time");
899
900 time_t result = Time::getTime();
901 if (tval && !PosixSubsystem::copyToUser(tval, &result, sizeof(result))) {
902 SYSCALL_ERROR(BadAddress);
903 return -1;
904 }
905
906 return result;
907}
908
909clock_t posix_times(struct tms* tm) {
910 SC_NOTICE("times");
911
912 Process* pProcess = Processor::information().getCurrentThread()->getParent();
913 constexpr Time::Timestamp nanosecondsPerClockTick = Time::Multiplier::Second / 100;
914
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;
920 if (tm && !PosixSubsystem::copyToUser(tm, &result, sizeof(result))) {
921 SC_NOTICE("posix_times -> invalid address");
922 SYSCALL_ERROR(BadAddress);
923 return -1;
924 }
925
926 SC_NOTICE("times: u=" << pProcess->getUserTime() << ", s=" << pProcess->getKernelTime());
927
928 return Time::getTicks() / nanosecondsPerClockTick;
929}
930
931int posix_getrusage(int who, struct rusage* r) {
932 SC_NOTICE("getrusage who=" << who);
933
934 if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN && who != RUSAGE_THREAD) {
935 SC_NOTICE("posix_getrusage -> unsupported selector");
936 SYSCALL_ERROR(InvalidArgument);
937 return -1;
938 }
939
940 Thread* currentThread = Processor::information().getCurrentThread();
941 Process* pProcess = currentThread->getParent();
942 const Time::Timestamp user = who == RUSAGE_THREAD ? currentThread->getUserTime()
943 : who == RUSAGE_CHILDREN ? pProcess->getReapedChildrenUserTime()
944 : pProcess->getUserTime();
945 const Time::Timestamp kernel = who == RUSAGE_THREAD ? currentThread->getKernelTime()
946 : who == RUSAGE_CHILDREN ? pProcess->getReapedChildrenKernelTime()
947 : pProcess->getKernelTime();
948
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;
954
955 if (!PosixSubsystem::copyToUser(r, &result, sizeof(result))) {
956 SC_NOTICE("posix_getrusage -> invalid address");
957 SYSCALL_ERROR(BadAddress);
958 return -1;
959 }
960
961 return 0;
962}
963
964int posix_linux_getrusage(int who, LinuxRusage64* r) {
965 SC_NOTICE("Linux getrusage who=" << who);
966
967 if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN && who != RUSAGE_THREAD) {
968 SC_NOTICE("posix_linux_getrusage -> unsupported selector");
969 SYSCALL_ERROR(InvalidArgument);
970 return -1;
971 }
972
973 Thread* currentThread = Processor::information().getCurrentThread();
974 Process* pProcess = currentThread->getParent();
975 const Time::Timestamp user = who == RUSAGE_THREAD ? currentThread->getUserTime()
976 : who == RUSAGE_CHILDREN ? pProcess->getReapedChildrenUserTime()
977 : pProcess->getUserTime();
978 const Time::Timestamp kernel = who == RUSAGE_THREAD ? currentThread->getKernelTime()
979 : who == RUSAGE_CHILDREN ? pProcess->getReapedChildrenKernelTime()
980 : pProcess->getKernelTime();
981
982 LinuxRusage64 result = {};
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;
987
988 if (!PosixSubsystem::copyToUser(r, &result, sizeof(result))) {
989 SC_NOTICE("posix_linux_getrusage -> invalid address");
990 SYSCALL_ERROR(BadAddress);
991 return -1;
992 }
993
994 return 0;
995}
996
997namespace {
998int copyPasswd(User* user, passwd* output, char* userStrings) {
999 if (!user) {
1000 return -1;
1001 }
1002 // The native glue supplies one 256-byte buffer for all passwd strings.
1003 char strings[256] = {};
1004 passwd result = {};
1005 size_t used = 0;
1006 const uintptr_t base = reinterpret_cast<uintptr_t>(userStrings);
1007 const String empty;
1008 const String* values[] = {&user->getUsername(), &empty, &user->getFullName(), &user->getHome(),
1009 &user->getShell()};
1010 char** fields[] = {&result.pw_name, &result.pw_passwd, &result.pw_gecos, &result.pw_dir,
1011 &result.pw_shell};
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);
1016 return -1;
1017 }
1018 *fields[i] = reinterpret_cast<char*>(base + used);
1019 MemoryCopy(strings + used, values[i]->cstr(), length + 1);
1020 used += length + 1;
1021 }
1022 result.pw_uid = user->getId();
1023 result.pw_gid = user->getDefaultGroup()->getId();
1024 if (!PosixSubsystem::copyToUser(userStrings, strings, used) ||
1025 !PosixSubsystem::copyToUser(output, &result, sizeof(result))) {
1026 SYSCALL_ERROR(BadAddress);
1027 return -1;
1028 }
1029 return 0;
1030}
1031
1032int copyGroup(Group* group, struct group* output) {
1033 if (!group) {
1034 return -1;
1035 }
1036 struct group result = {};
1037 if (!PosixSubsystem::copyFromUser(&result, output, sizeof(result))) {
1038 SYSCALL_ERROR(BadAddress);
1039 return -1;
1040 }
1041 // The native getgr* glue allocates 256 bytes for the caller-owned name.
1042 const String& name = group->getName();
1043 if (name.length() >= 256) {
1044 SYSCALL_ERROR(BadRange);
1045 return -1;
1046 }
1047 result.gr_gid = group->getId();
1048 if (!PosixSubsystem::copyToUser(result.gr_name, name.cstr(), name.length() + 1) ||
1049 !PosixSubsystem::copyToUser(output, &result, sizeof(result))) {
1050 SYSCALL_ERROR(BadAddress);
1051 return -1;
1052 }
1053 return 0;
1054}
1055} // namespace
1056
1057int posix_getpwent(passwd* pw, int n, char* str) {
1058 return copyPasswd(UserManager::instance().getUser(n), pw, str);
1059}
1060
1061int posix_getpwnam(passwd* pw, const char* name, char* str) {
1062 String nameCopy;
1063 if (!copyUserString(name, nameCopy)) {
1064 return -1;
1065 }
1066 return copyPasswd(UserManager::instance().getUser(nameCopy), pw, str);
1067}
1068
1069int posix_getgrnam(const char* name, struct group* out) {
1070 String nameCopy;
1071 if (!copyUserString(name, nameCopy)) {
1072 return -1;
1073 }
1074 return copyGroup(UserManager::instance().getGroup(nameCopy), out);
1075}
1076
1077int posix_getgrgid(gid_t id, struct group* out) {
1078 return copyGroup(UserManager::instance().getGroup(id), out);
1079}
1080
1081EXPORTED_PUBLIC int pedigree_login(int uid) {
1082 PosixProcess* process = getPosixProcess();
1083 if (!process) {
1084 SYSCALL_ERROR(NotEnoughPermissions);
1085 return -1;
1086 }
1088 if (process->snapshotCredentials().euid != 0) {
1089 SYSCALL_ERROR(NotEnoughPermissions);
1090 return -1;
1091 }
1092 if (process->getNumThreads() != 1) {
1093 SYSCALL_ERROR(NoMoreProcesses);
1094 return -1;
1095 }
1096 User* user = uid < 0 ? nullptr : UserManager::instance().getUser(uid);
1097 if (!user) {
1098 SYSCALL_ERROR(InvalidArgument);
1099 return -1;
1100 }
1101 if (!user->login()) {
1102 SYSCALL_ERROR(InvalidArgument);
1103 return -1;
1104 }
1105 Processor::information().getCurrentThread()->setErrno(0);
1106 return 0;
1107}
1108
1109mode_t posix_umask(mode_t mask) {
1110 SC_NOTICE("umask(" << Oct << mask << ")");
1111
1112 // Not a POSIX process
1113 Process* pStockProcess = Processor::information().getCurrentThread()->getParent();
1114 if (pStockProcess->getType() != Process::Posix) {
1115 SC_NOTICE("umask -> called on something not a POSIX process");
1116 SYSCALL_ERROR(InvalidArgument);
1117 return -1;
1118 }
1119
1120 PosixProcess* pProcess = static_cast<PosixProcess*>(pStockProcess);
1121
1122 uint32_t previous = pProcess->getMask();
1123 pProcess->setMask(mask);
1124
1125 return previous;
1126}
1127
1128int posix_linux_syslog(int type, char* buf, int len) {
1129 switch (type) {
1130 case 0:
1131 case 1:
1132 return 0;
1133 case 3:
1134 break;
1135 case 10:
1136 return static_cast<int>(Log::textCapacity());
1137#if PEDIGREE_SYSCALL_COUNTER
1138 case 11: {
1139 if (len != static_cast<int>(sizeof(uint64_t))) {
1140 SYSCALL_ERROR(InvalidArgument);
1141 return -1;
1142 }
1143 Process* process = Processor::information().getCurrentThread()->getParent();
1144 const uint64_t count = process->getReapedChildrenSyscallCount();
1145 if (!PosixSubsystem::copyToUser(buf, &count, sizeof(count))) {
1146 SYSCALL_ERROR(BadAddress);
1147 return -1;
1148 }
1149 return static_cast<int>(sizeof(count));
1150 }
1151 case 12: {
1152 Process* process = Processor::information().getCurrentThread()->getParent();
1153 Process::SyscallLatencySnapshot snapshot = {};
1154 process->getReapedChildrenSyscallLatencySnapshot(snapshot);
1155 if (len != static_cast<int>(sizeof(snapshot))) {
1156 SYSCALL_ERROR(InvalidArgument);
1157 return -1;
1158 }
1159 if (!PosixSubsystem::copyToUser(buf, &snapshot, sizeof(snapshot))) {
1160 SYSCALL_ERROR(BadAddress);
1161 return -1;
1162 }
1163 return static_cast<int>(sizeof(snapshot));
1164 }
1165#endif
1166#if PEDIGREE_ACTIVITY_DIAGNOSTICS
1167 case 13: {
1168 if (len != static_cast<int>(sizeof(ActivityDiagnostics::Snapshot))) {
1169 SYSCALL_ERROR(InvalidArgument);
1170 return -1;
1171 }
1172 ActivityDiagnostics::Snapshot snapshot = {};
1173 ActivityDiagnostics::snapshot(snapshot);
1174 if (!PosixSubsystem::copyToUser(buf, &snapshot, sizeof(snapshot))) {
1175 SYSCALL_ERROR(BadAddress);
1176 return -1;
1177 }
1178 return static_cast<int>(sizeof(snapshot));
1179 }
1180#endif
1181#if PEDIGREE_BENCHMARK_SYSCALL_TIMING
1182 case 15: {
1183 if (buf || (len != 0 && len != 1)) {
1184 SYSCALL_ERROR(InvalidArgument);
1185 return -1;
1186 }
1187 Process* process = Processor::information().getCurrentThread()->getParent();
1188 process->setBenchmarkSyscallTiming(len != 0);
1189 return 0;
1190 }
1191 case 16: {
1192 constexpr size_t snapshotSize =
1193 Process::SyscallTimingSlotCount * sizeof(Process::SyscallTimingEntry);
1194 if (len != static_cast<int>(snapshotSize)) {
1195 SYSCALL_ERROR(InvalidArgument);
1196 return -1;
1197 }
1198 Process* process = Processor::information().getCurrentThread()->getParent();
1199 for (size_t i = 0; i < Process::SyscallTimingSlotCount; ++i) {
1200 Process::SyscallTimingEntry entry = {};
1201 process->getSyscallTimingEntry(i, entry);
1202 if (!PosixSubsystem::copyToUser(buf + i * sizeof(entry), &entry, sizeof(entry))) {
1203 SYSCALL_ERROR(BadAddress);
1204 return -1;
1205 }
1206 }
1207 return static_cast<int>(snapshotSize);
1208 }
1209#endif
1210#if PEDIGREE_BENCHMARK_VM_DIAGNOSTICS
1211 case 17: {
1212 if (buf || (len != 0 && len != 1)) {
1213 SYSCALL_ERROR(InvalidArgument);
1214 return -1;
1215 }
1216 Process* process = Processor::information().getCurrentThread()->getParent();
1217 process->setBenchmarkVmDiagnostics(len != 0);
1218 return 0;
1219 }
1220 case 18: {
1221 constexpr size_t snapshotSize = Process::BenchmarkVmCounterCount * sizeof(uint64_t);
1222 if (len != static_cast<int>(snapshotSize)) {
1223 SYSCALL_ERROR(InvalidArgument);
1224 return -1;
1225 }
1226 Process* process = Processor::information().getCurrentThread()->getParent();
1227 for (size_t i = 0; i < Process::BenchmarkVmCounterCount; ++i) {
1228 const uint64_t value = process->getBenchmarkVmCounter(i);
1229 if (!PosixSubsystem::copyToUser(buf + i * sizeof(value), &value, sizeof(value))) {
1230 SYSCALL_ERROR(BadAddress);
1231 return -1;
1232 }
1233 }
1234 return static_cast<int>(snapshotSize);
1235 }
1236#endif
1237 case 20: {
1238#if PEDIGREE_BENCHMARK_SYSCALL_TRACE
1239 if (buf || (len != 0 && len != 1)) {
1240 SYSCALL_ERROR(InvalidArgument);
1241 return -1;
1242 }
1243 Process* process = Processor::information().getCurrentThread()->getParent();
1244 process->setBenchmarkSyscallTrace(len != 0);
1245 return 0;
1246#else
1247 SYSCALL_ERROR(Unimplemented);
1248 return -1;
1249#endif
1250 }
1251 case 2:
1252 case 4:
1253 case 5:
1254 case 6:
1255 case 7:
1256 case 8:
1257 case 9:
1258 SYSCALL_ERROR(Unimplemented);
1259 return -1;
1260 default:
1261 SYSCALL_ERROR(InvalidArgument);
1262 return -1;
1263 }
1264
1265 if (len < 0) {
1266 SYSCALL_ERROR(InvalidArgument);
1267 return -1;
1268 }
1269 if (!len)
1270 return 0;
1271 const size_t capacity = static_cast<size_t>(len) < Log::textCapacity() ? static_cast<size_t>(len)
1272 : Log::textCapacity();
1273 if (!PosixSubsystem::checkAddress(reinterpret_cast<uintptr_t>(buf), capacity,
1274 PosixSubsystem::SafeWrite)) {
1275 SYSCALL_ERROR(BadAddress);
1276 return -1;
1277 }
1278
1279 // User memory may fault: never copy to it while holding the log spinlock.
1280 TerminationDeferral lifetime;
1281 char* snapshot = new char[capacity];
1282 if (!snapshot) {
1283 SYSCALL_ERROR(OutOfMemory);
1284 return -1;
1285 }
1286 const size_t copied = Log::instance().copyText(snapshot, capacity);
1287 const bool valid = PosixSubsystem::copyToUser(buf, snapshot, copied);
1288 delete[] snapshot;
1289 if (!valid) {
1290 SYSCALL_ERROR(BadAddress);
1291 return -1;
1292 }
1293 return static_cast<int>(copied);
1294}
1295
1296int posix_syslog(const char* msg, int prio) {
1297 String msgCopy;
1298 if (!copyUserString(msg, msgCopy)) {
1299 SC_NOTICE("klog -> invalid address");
1300 return -1;
1301 }
1302
1303 uint64_t id = Processor::information().getCurrentThread()->getParent()->getId();
1304 if (id <= 1) {
1305 if (prio <= LOG_CRIT)
1306 FATAL("[" << Dec << id << Hex << "]\tklog: " << msgCopy);
1307 }
1308
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);
1315#if DEBUGGER
1316 else
1317 NOTICE("[" << Dec << id << Hex << "]\tklog: " << msgCopy);
1318#endif
1319 return 0;
1320}
1321
1322int posix_reboot(uint32_t magic1, uint32_t magic2, uint32_t command) {
1323 if (Processor::information().getCurrentThread()->getParent()->getEffectiveUserId() != 0) {
1324 SYSCALL_ERROR(NotEnoughPermissions);
1325 return -1;
1326 }
1327 if (magic1 != 0xfee1dead ||
1328 (magic2 != 672274793 && magic2 != 85072278 && magic2 != 369367448 && magic2 != 537993216)) {
1329 SYSCALL_ERROR(InvalidArgument);
1330 return -1;
1331 }
1332
1333 Machine::ShutdownType type;
1334 switch (command) {
1335 case 0x00000000: // CAD_OFF
1336 case 0x89abcdef: // CAD_ON
1337 // There is no kernel Ctrl-Alt-Del policy to change.
1338 return 0;
1339 case 0x01234567:
1340 type = Machine::ShutdownType::Restart;
1341 break;
1342 case 0xcdef0123:
1343 type = Machine::ShutdownType::Halt;
1344 break;
1345 case 0x4321fedc:
1346 type = Machine::ShutdownType::PowerOff;
1347 break;
1348 default:
1349 // RESTART2, suspend and kexec require contracts we do not implement.
1350 SYSCALL_ERROR(InvalidArgument);
1351 return -1;
1352 }
1353
1354 // Catch known writeback failures before committing to terminal teardown.
1355 // Module shutdown closes writers and performs the final cache drains.
1356 const auto status = VFS::instance().syncAll();
1357 if (status == Filesystem::SyncStatus::IoError || status == Filesystem::SyncStatus::NoMemory) {
1358 syscallError(status == Filesystem::SyncStatus::IoError ? Error::IoError : Error::OutOfMemory);
1359 return -1;
1360 }
1361 if (!SyscallManager::instance().requestReboot(type)) {
1362 SYSCALL_ERROR(DeviceBusy);
1363 return -1;
1364 }
1365 return 0;
1366}
1367
1368EXPORTED_PUBLIC int pedigree_reboot() {
1369 return posix_reboot(0xfee1dead, 672274793, 0x01234567);
1370}
1371
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
1374 << ")");
1375
1376 Thread* thread = Processor::information().getCurrentThread();
1377 if (option == 3 || option == 4) {
1378 PosixProcess* process = getPosixProcess();
1379 if (!process) {
1380 SYSCALL_ERROR(InvalidArgument);
1381 return -1;
1382 }
1383 if (option == 3) {
1384 thread->setErrno(0);
1385 return process->snapshotCredentials().dumpable ? 1 : 0;
1386 }
1387 if (arg2 > 1) {
1388 SYSCALL_ERROR(InvalidArgument);
1389 return -1;
1390 }
1391 process->setDumpable(arg2 != 0);
1392 thread->setErrno(0);
1393 return 0;
1394 }
1395
1396 if (option == LINUX_PR_SET_NAME) {
1397 String requested;
1398 const PosixSubsystem::UserStringResult result = PosixSubsystem::copyUserString(
1399 reinterpret_cast<const char*>(arg2), requested, LINUX_TASK_NAME_LENGTH);
1400 if (result == PosixSubsystem::UserStringBadAddress) {
1401 SYSCALL_ERROR(BadAddress);
1402 return -1;
1403 }
1404
1405 // Linux task names are a 16-byte field including the terminator. Direct
1406 // prctl callers are truncated; pthread_setname_np applies its own ERANGE.
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));
1411 return 0;
1412 }
1413
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)
1418 ? current.length()
1419 : (LINUX_TASK_NAME_LENGTH - 1);
1420 MemoryCopy(name, current.cstr(), length);
1421 if (!PosixSubsystem::copyToUser(reinterpret_cast<void*>(arg2), name, sizeof(name))) {
1422 SYSCALL_ERROR(BadAddress);
1423 return -1;
1424 }
1425 return 0;
1426 }
1427
1428 SYSCALL_ERROR(InvalidArgument);
1429 return -1;
1430}
1431
1432int posix_arch_prctl(int code, unsigned long addr) {
1433 Thread* current = Processor::information().getCurrentThread();
1434 switch (code) {
1435#if X64 && !HOSTED
1436 case ARCH_SET_GS:
1437 // Paranoid entry distinguishes kernel and user GS by the address half.
1438 // FSGSBASE stays disabled, so userspace cannot bypass this restriction.
1439 if (addr >= current->getParent()->getAddressSpace()->getKernelStart() ||
1440 addr >= 0x0000800000000000ULL) {
1441 SYSCALL_ERROR(NotEnoughPermissions);
1442 return -1;
1443 }
1444 current->setUserGsBase(addr);
1445 break;
1446
1447 case ARCH_GET_GS: {
1448 const unsigned long base = Processor::getUserGsBase();
1449 if (!PosixSubsystem::copyToUser(reinterpret_cast<void*>(addr), &base, sizeof(base))) {
1450 SYSCALL_ERROR(BadAddress);
1451 return -1;
1452 }
1453 break;
1454 }
1455#endif
1456 case ARCH_SET_FS:
1457 if (addr >= current->getParent()->getAddressSpace()->getKernelStart()
1458#if X64
1459 || addr >= 0x0000800000000000ULL
1460#endif
1461 ) {
1462 SYSCALL_ERROR(NotEnoughPermissions);
1463 return -1;
1464 }
1465 current->setTlsBase(addr);
1466 break;
1467
1468 case ARCH_GET_FS: {
1469 const unsigned long base = current->getTlsBase();
1470 if (!PosixSubsystem::copyToUser(reinterpret_cast<void*>(addr), &base, sizeof(base))) {
1471 SYSCALL_ERROR(BadAddress);
1472 return -1;
1473 }
1474 break;
1475 }
1476
1477 default:
1478 SYSCALL_ERROR(InvalidArgument);
1479 return -1;
1480 }
1481 return 0;
1482}
1483
1484int posix_pause() {
1485 SC_NOTICE("pause");
1486
1487 Processor::information().getCurrentThread()->waitForEvent();
1488
1489 SYSCALL_ERROR(Interrupted);
1490 return -1;
1491}
1492
1493int posix_membarrier(int command, unsigned int flags, int cpuId) {
1494 SC_NOTICE("membarrier(" << Dec << command << ", " << flags << ", " << cpuId << ")");
1495
1496 // A zero query result truthfully advertises that no membarrier commands are
1497 // available. Callers can then select their ordinary synchronization path.
1498 if (command == 0 && flags == 0) {
1499 return 0;
1500 }
1501
1502 SYSCALL_ERROR(InvalidArgument);
1503 return -1;
1504}
1505
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);
1510 return -1;
1511 }
1512 if (who < 0) {
1513 SYSCALL_ERROR(NoSuchProcess);
1514 return -1;
1515 }
1516
1517 PosixProcess* caller = getPosixProcess();
1518 if (!caller) {
1519 SYSCALL_ERROR(NoSuchProcess);
1520 return -1;
1521 }
1522
1523 // POSIX nice values are not mutable yet. Linux returns 20 minus nice,
1524 // while the native POSIX service exposes the public value directly.
1525 const int priority = linuxAbi ? 20 : 0;
1526 if (which == PRIO_PROCESS) {
1527 if (!who || static_cast<size_t>(who) == caller->getUserspaceId()) {
1528 return priority;
1529 }
1530 Scheduler::ProcessLease candidate;
1531 if (Scheduler::instance().acquireProcessByUserspaceId(candidate, static_cast<size_t>(who)) &&
1532 candidate->getType() == Process::Posix && candidate->getState() != Process::Reaped) {
1533 return priority;
1534 }
1535 SYSCALL_ERROR(NoSuchProcess);
1536 return -1;
1537 }
1538
1539 if (which == PRIO_USER) {
1540 if (!who || static_cast<int64_t>(who) == caller->getUserId()) {
1541 return priority;
1542 }
1543 // The scheduler has no stable process snapshot for another user's set.
1544 // Index-based scans can miss a live match when an earlier process exits.
1545 SYSCALL_ERROR(Unimplemented);
1546 return -1;
1547 }
1548
1549 size_t callerGroup = 0;
1550 const bool hasCallerGroup = caller->getProcessGroupId(callerGroup);
1551 if (hasCallerGroup && (!who || static_cast<size_t>(who) == callerGroup)) {
1552 return priority;
1553 }
1554 if (who) {
1555 SYSCALL_ERROR(Unimplemented);
1556 return -1;
1557 }
1558
1559 SYSCALL_ERROR(NoSuchProcess);
1560 return -1;
1561}
1562
1563int posix_setpriority(int which, int who, int prio) {
1565 SC_NOTICE("setpriority(" << which << ", " << Dec << who << ", " << prio << ")");
1566 return 0;
1567}
1568
1569int posix_get_robust_list(int pid, struct robust_list_head** head_ptr, size_t* len_ptr,
1570 bool linuxAbi) {
1571 SC_NOTICE("get_robust_list");
1572 Thread* current = Processor::information().getCurrentThread();
1573 Thread* target = current;
1574 Process::ThreadLease targetLease;
1575 const size_t currentId = linuxAbi ? current->getTaskId() : current->getId();
1576 if (pid < 0 || (pid && static_cast<size_t>(pid) != currentId &&
1577 !(linuxAbi ? Scheduler::instance().acquireThreadByTaskId(targetLease, pid)
1578 : current->getParent()->acquireThreadById(targetLease, pid)))) {
1579 SYSCALL_ERROR(NoSuchProcess);
1580 return -1;
1581 }
1582 if (targetLease) {
1583 target = targetLease.get();
1584 }
1585 if (target->getParent() != current->getParent()) {
1586 // Cross-process inspection needs a ptrace access policy which the
1587 // subsystem does not yet implement.
1588 SYSCALL_ERROR(NotEnoughPermissions);
1589 return -1;
1590 }
1591
1592 auto* head = reinterpret_cast<struct robust_list_head*>(target->getRobustList());
1593 const size_t length = 3 * sizeof(uintptr_t);
1594 if (!PosixSubsystem::copyToUser(head_ptr, &head, sizeof(head)) ||
1595 !PosixSubsystem::copyToUser(len_ptr, &length, sizeof(length))) {
1596 SYSCALL_ERROR(BadAddress);
1597 return -1;
1598 }
1599 return 0;
1600}
1601
1602int posix_set_robust_list(struct robust_list_head* head, size_t len, bool linuxAbi) {
1603 SC_NOTICE("set_robust_list");
1604
1605 if (len != 3 * sizeof(uintptr_t)) {
1606 SYSCALL_ERROR(InvalidArgument);
1607 return -1;
1608 }
1609
1610 // The list is mutable userspace state. Linux registers its address without
1611 // touching it; exit processing must bound and validate each later access.
1612 Thread* current = Processor::information().getCurrentThread();
1613 current->setRobustList(reinterpret_cast<uintptr_t>(head),
1614 linuxAbi ? current->getTaskId() : current->getId());
1615
1616 return 0;
1617}
1618
1619int posix_ioperm(unsigned long from, unsigned long num, int turn_on) {
1620 SC_NOTICE("ioperm(" << from << ", " << num << ", " << turn_on << ")");
1621
1624 return 0;
1625}
1626
1627int posix_iopl(int level) {
1628 SC_NOTICE("iopl(" << level << ")");
1629 return 0;
1630}
1631
1632#undef SC_NOTICE
1633#define SC_NOTICE(x)
1634
1635namespace {
1636constexpr Time::Timestamp MaximumLinuxTimerNanoseconds = 0x7FFFFFFFFFFFFFFFULL;
1637
1638IntervalTimer* selectIntervalTimer(PosixProcess* process, int which) {
1639 switch (which) {
1640 case ITIMER_REAL:
1641 return &process->getRealIntervalTimer();
1642 case ITIMER_VIRTUAL:
1643 return &process->getVirtualIntervalTimer();
1644 case ITIMER_PROF:
1645 return &process->getProfileIntervalTimer();
1646 default:
1647 return nullptr;
1648 }
1649}
1650
1651bool validIntervalTimeval(const struct timeval& value) {
1652 return value.tv_sec >= 0 && value.tv_usec >= 0 && value.tv_usec < 1000000;
1653}
1654
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;
1661 }
1662 return seconds * Time::Multiplier::Second + microseconds;
1663}
1664
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;
1672 return result;
1673}
1674} // namespace
1675
1676int posix_getitimer(int which, struct itimerval* curr_value) {
1677 SC_NOTICE("posix_getitimer(" << which << ", " << curr_value << ")");
1678
1679 Thread* currentThread = Processor::information().getCurrentThread();
1680 PosixProcess* pProcess = static_cast<PosixProcess*>(currentThread->getParent());
1681
1682 Time::Timestamp interval = 0;
1683 Time::Timestamp value = 0;
1684
1685 IntervalTimer* itimer = selectIntervalTimer(pProcess, which);
1686 if (!itimer) {
1687 SYSCALL_ERROR(InvalidArgument);
1688 return -1;
1689 }
1690
1691 if (which != ITIMER_REAL) {
1692 currentThread->trackTime(CpuTimeMode::Kernel);
1693 }
1694 itimer->getIntervalAndValue(interval, value);
1695
1696 const struct itimerval result = intervalTimerToUser(interval, value);
1697 if (!PosixSubsystem::copyToUser(curr_value, &result, sizeof(result))) {
1698 SYSCALL_ERROR(BadAddress);
1699 return -1;
1700 }
1701
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
1705 << "us");
1706
1707 return 0;
1708}
1709
1710int posix_setitimer(int which, const struct itimerval* new_value, struct itimerval* old_value) {
1711 SC_NOTICE("posix_setitimer(" << which << ", " << new_value << ", " << old_value << ")");
1712
1713 struct itimerval requested = {};
1714 if (new_value && !PosixSubsystem::copyFromUser(&requested, new_value, sizeof(requested))) {
1715 SYSCALL_ERROR(BadAddress);
1716 return -1;
1717 }
1718 if (!validIntervalTimeval(requested.it_interval) || !validIntervalTimeval(requested.it_value)) {
1719 SYSCALL_ERROR(InvalidArgument);
1720 return -1;
1721 }
1722
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
1726 << "us");
1727
1728 Thread* currentThread = Processor::information().getCurrentThread();
1729 PosixProcess* pProcess = static_cast<PosixProcess*>(currentThread->getParent());
1730
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;
1735
1736 IntervalTimer* itimer = selectIntervalTimer(pProcess, which);
1737 if (!itimer) {
1738 SYSCALL_ERROR(InvalidArgument);
1739 return -1;
1740 }
1741
1742 if (which != ITIMER_REAL) {
1743 currentThread->trackTime(CpuTimeMode::Kernel);
1744 }
1745 itimer->setIntervalAndValue(interval, value, &prevInterval, &prevValue);
1746
1747 if (old_value) {
1748 const struct itimerval previous = intervalTimerToUser(prevInterval, prevValue);
1749 if (!PosixSubsystem::copyToUser(old_value, &previous, sizeof(previous))) {
1750 SYSCALL_ERROR(BadAddress);
1751 return -1;
1752 }
1753 }
1754
1755 return 0;
1756}
1757
1758int posix_capget(void* hdrp, void* datap) {
1759 if (!getPosixProcess()) {
1760 return -1;
1761 }
1762 cap_header header = {};
1763 if (!PosixSubsystem::copyFromUser(&header, hdrp, sizeof(header))) {
1764 SYSCALL_ERROR(BadAddress);
1765 return -1;
1766 }
1767 if (header.version != _LINUX_CAPABILITY_VERSION_1) {
1768 const uint32_t version = _LINUX_CAPABILITY_VERSION_1;
1769 if (!PosixSubsystem::copyToUser(hdrp, &version, sizeof(version))) {
1770 SYSCALL_ERROR(BadAddress);
1771 return -1;
1772 }
1773 SYSCALL_ERROR(InvalidArgument);
1774 return -1;
1775 }
1776 if (datap) {
1777 const cap_data data = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF};
1778 if (!PosixSubsystem::copyToUser(datap, &data, sizeof(data))) {
1779 SYSCALL_ERROR(BadAddress);
1780 return -1;
1781 }
1782 }
1783 return 0;
1784}
1785
1786int posix_capset(void* hdrp, const void* datap) {
1787 cap_header header = {};
1788 if (!PosixSubsystem::copyFromUser(&header, hdrp, sizeof(header))) {
1789 SYSCALL_ERROR(BadAddress);
1790 return -1;
1791 }
1792 if (header.version != _LINUX_CAPABILITY_VERSION_1) {
1793 const uint32_t version = _LINUX_CAPABILITY_VERSION_1;
1794 if (!PosixSubsystem::copyToUser(hdrp, &version, sizeof(version))) {
1795 SYSCALL_ERROR(BadAddress);
1796 return -1;
1797 }
1798 SYSCALL_ERROR(InvalidArgument);
1799 return -1;
1800 }
1801 cap_data data = {};
1802 if (!PosixSubsystem::copyFromUser(&data, datap, sizeof(data))) {
1803 SYSCALL_ERROR(BadAddress);
1804 return -1;
1805 }
1806 // Capability policy remains the existing all-granted no-op contract.
1807 return 0;
1808}
Memory-mapped file interface.
Definition Group.h:32
const String & getName() const
Definition Group.h:54
size_t getId() const
Definition Group.h:50
void setIntervalAndValue(Time::Timestamp interval, Time::Timestamp value, Time::Timestamp *prevInterval=nullptr, Time::Timestamp *prevValue=nullptr)
Set both interval and value atomically.
the kernel's log
Definition Log.h:155
static EXPORTED_PUBLIC Log & instance()
Definition Log.cc:117
EXPORTED_PUBLIC size_t copyText(char *buffer, size_t capacity)
Definition Log.cc:444
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 &copy, 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
Definition Process.h:467
@ Reaped
Terminal wait status is visible; the owner may still be on-stack.
Definition Process.h:273
MUST_USE_RESULT bool installFilesystemContext(FilesystemContextOwner &&context)
Definition Process.cc:651
Process * getParent()
Definition Process.h:567
VirtualAddressSpace * getAddressSpace()
Definition Process.h:477
size_t getNumThreads()
Definition Process.cc:1271
Time::Timestamp getUserTime() const
Definition Process.h:774
static ProcessorInformation & information()
static void switchAddressSpace(VirtualAddressSpace &AddressSpace)
static void setInterrupts(bool bEnable)
static Scheduler & instance()
Definition Scheduler.h:96
static SharedPointer< T > tryAdopt(T *ptr)
static EXPORTED_PUBLIC SyscallManager & instance()
void setErrno(size_t err)
Definition Thread.h:465
void setTlsBase(uintptr_t base)
Definition Thread.cc:2674
void setUnwindState(UnwindType ut)
Definition Thread.cc:3550
@ TerminateThread
Exit only this thread during Process exit.
Definition Thread.h:502
Time::Timestamp getUserTime() const
Definition Thread.h:397
UnwindType getUnwindState()
Definition Thread.h:518
bool detach()
Definition Thread.cc:2939
void setClearChildTid(uintptr_t address)
Definition Thread.cc:627
void trackTime(CpuTimeMode mode)
Definition Thread.cc:373
bool startDetached()
Definition Thread.cc:743
Process * getParent() const
Definition Thread.h:325
size_t getId()
Definition Thread.h:450
bool start()
Definition Thread.cc:725
uintptr_t getTlsBase()
Definition Thread.cc:2596
size_t getTaskId() const
Definition Thread.h:455
User * getUser(size_t id)
static UserManager & instance()
Definition UserManager.h:32
Definition User.h:32
size_t getId() const
Definition User.h:60
const String & getFullName() const
Definition User.h:68
const String & getUsername() const
Definition User.h:64
bool login()
Definition User.cc:65
Group * getDefaultGroup()
Definition User.h:72
const String & getHome() const
Definition User.h:76
const String & getShell() const
Definition User.h:80
Filesystem::SyncStatus syncAll()
Definition VFS.cc:857
static VFS & instance()
Definition VFS.cc:310
A vector / dynamic array.
Definition Vector.h:33
virtual uintptr_t getKernelStart() const =0
@ Oct
Definition Log.h:128
@ Dec
Definition Log.h:126
@ Hex
Definition Log.h:124