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 "system-syscalls.h"
21 #include "file-syscalls.h"
22 #include "modules/system/linker/DynamicLinker.h"
23 #include "modules/system/vfs/File.h"
24 #include "modules/system/vfs/Symlink.h"
25 #include "modules/system/vfs/VFS.h"
26 #include "pedigree/kernel/Log.h"
27 #include "pedigree/kernel/Version.h"
28 #include "pedigree/kernel/compiler.h"
29 #include "pedigree/kernel/linker/Elf.h"
30 #include "pedigree/kernel/linker/KernelElf.h"
31 #include "pedigree/kernel/panic.h"
32 #include "pedigree/kernel/process/PerProcessorScheduler.h"
33 #include "pedigree/kernel/process/Process.h"
34 #include "pedigree/kernel/process/Scheduler.h"
35 #include "pedigree/kernel/process/Thread.h"
36 #include "pedigree/kernel/processor/PhysicalMemoryManager.h"
37 #include "pedigree/kernel/processor/Processor.h"
38 #include "pedigree/kernel/processor/StackFrame.h"
39 #include "pedigree/kernel/processor/VirtualAddressSpace.h"
40 #include "pedigree/kernel/processor/state.h"
41 #include "pedigree/kernel/processor/types.h"
42 #include "pedigree/kernel/syscallError.h"
43 #include "pedigree/kernel/utilities/String.h"
44 #include "pedigree/kernel/utilities/Vector.h"
45 #include "pipe-syscalls.h"
46 #include "posixSyscallNumbers.h"
47 #include "pthread-syscalls.h"
48 #include "signal-syscalls.h"
49 
50 #define MACHINE_FORWARD_DECL_ONLY
51 #include "pedigree/kernel/machine/Machine.h"
52 #include "pedigree/kernel/machine/Timer.h"
53 
54 #include "pedigree/kernel/Subsystem.h"
55 #include <PosixProcess.h>
56 #include <PosixSubsystem.h>
57 
58 #include "modules/system/console/Console.h"
59 #include "modules/system/users/Group.h"
60 #include "modules/system/users/User.h"
61 #include "modules/system/users/UserManager.h"
63 
64 #include <grp.h>
65 #include <limits.h>
66 #include <pwd.h>
67 #include <sched.h>
68 #include <sys/resource.h>
69 #include <sys/times.h>
70 #include <sys/utsname.h>
71 #include <sys/wait.h>
72 #include <syslog.h>
73 
74 // arch_prctl
75 #define ARCH_SET_FS 0x1002
76 #define ARCH_GET_FS 0x1003
77 
78 // capget/capset
79 #define _LINUX_CAPABILITY_VERSION_1 0x19980330
80 
81 struct cap_header
82 {
83  uint32_t version;
84  int pid;
85 };
86 
87 struct cap_data
88 {
89  uint32_t effective;
90  uint32_t permitted;
91  uint32_t inheritable;
92 };
93 
94 //
95 // Syscalls pertaining to system operations.
96 //
97 
98 #define GET_CWD() \
99  (Processor::information().getCurrentThread()->getParent()->getCwd())
100 
101 static PosixProcess *getPosixProcess()
102 {
103  // Not a POSIX process
104  Process *pStockProcess =
105  Processor::information().getCurrentThread()->getParent();
106  if (pStockProcess->getType() != Process::Posix)
107  {
108  return nullptr;
109  }
110 
111  return static_cast<PosixProcess *>(pStockProcess);
112 }
113 
115 static size_t
116 save_string_array(const char **array, Vector<SharedPointer<String>> &rArray)
117 {
118  size_t result = 0;
119  while (*array)
120  {
121  String *pStr = new String(*array);
122  rArray.pushBack(SharedPointer<String>(pStr));
123  array++;
124 
125  result += pStr->length() + 1;
126  }
127 
128  return result;
129 }
130 
134 static char **load_string_array(
135  Vector<SharedPointer<String>> &rArray, uintptr_t arrayLoc,
136  uintptr_t &arrayEndLoc)
137 {
138  char **pMasterArray = reinterpret_cast<char **>(arrayLoc);
139 
140  char *pPtr = reinterpret_cast<char *>(
141  arrayLoc + sizeof(char *) * (rArray.count() + 1));
142  int i = 0;
143  for (auto it = rArray.begin(); it != rArray.end(); it++)
144  {
145  SharedPointer<String> pStr = *it;
146 
147  StringCopy(pPtr, *pStr);
148  pPtr[pStr->length()] = '\0'; // Ensure NULL-termination.
149 
150  pMasterArray[i] = pPtr;
151 
152  pPtr += pStr->length() + 1;
153  i++;
154  }
155 
156  pMasterArray[i] = 0; // Null terminate.
157  arrayEndLoc = reinterpret_cast<uintptr_t>(pPtr);
158 
159  return pMasterArray;
160 }
161 
162 long posix_sbrk(int delta)
163 {
164  SC_NOTICE("sbrk(" << delta << ")");
165 
166  long ret = reinterpret_cast<long>(
167  Processor::information().getVirtualAddressSpace().expandHeap(
169  SC_NOTICE(" -> " << ret);
170  if (ret == 0)
171  {
172  SYSCALL_ERROR(OutOfMemory);
173  return -1;
174  }
175  else
176  return ret;
177 }
178 
179 uintptr_t posix_brk(uintptr_t theBreak)
180 {
181  SC_NOTICE("brk(" << theBreak << ")");
182 
183  void *newBreak = reinterpret_cast<void *>(theBreak);
184 
185  void *currentBreak =
186  Processor::information().getVirtualAddressSpace().getEndOfHeap();
187  if (newBreak < currentBreak)
188  {
189  SC_NOTICE(" -> " << currentBreak);
190  return reinterpret_cast<uintptr_t>(currentBreak);
191  }
192 
193  intptr_t difference = pointer_diff(currentBreak, newBreak);
194  if (!difference)
195  {
196  SC_NOTICE(" -> " << currentBreak);
197  return reinterpret_cast<uintptr_t>(currentBreak);
198  }
199 
200  // OK, good to go.
201  void *result = Processor::information().getVirtualAddressSpace().expandHeap(
202  difference, VirtualAddressSpace::Write);
203  if (!result)
204  {
205  SYSCALL_ERROR(OutOfMemory);
206  SC_NOTICE(" -> ENOMEM");
207  return -1;
208  }
209 
210  // Return new end of heap.
211  currentBreak =
212  Processor::information().getVirtualAddressSpace().getEndOfHeap();
213 
214  SC_NOTICE(" -> " << currentBreak);
215  return reinterpret_cast<uintptr_t>(currentBreak);
216 }
217 
218 long posix_clone(
219  SyscallState &state, unsigned long flags, void *child_stack, int *ptid,
220  int *ctid, unsigned long newtls)
221 {
222  SC_NOTICE(
223  "clone(" << Hex << flags << ", " << child_stack << ", " << ptid << ", "
224  << ctid << ", " << newtls << ")");
225 
227 
228  // Must clone state as we make modifications for the new thread here.
229  SyscallState clonedState = state;
230 
231  // Basic warnings to start with.
232  if (flags & CLONE_CHILD_CLEARTID)
233  {
234  SC_NOTICE(" -> CLONE_CHILD_CLEARTID is not yet supported!");
235  }
236  if (flags & CLONE_PARENT)
237  {
238  SC_NOTICE(" -> CLONE_PARENT is not yet supported!");
239  }
240  if (flags & CLONE_VFORK)
241  {
242  // Halts parent until child ruins execve() or exit(), just like vfork.
243  // We should support this properly.
244  SC_NOTICE(" -> CLONE_VFORK is not yet supported!");
245  }
246 
247 #if 0
248  if (flags & CLONE_VM) SC_NOTICE("\t\t-> CLONE_VM");
249  if (flags & CLONE_FS) SC_NOTICE("\t\t-> CLONE_FS");
250  if (flags & CLONE_FILES) SC_NOTICE("\t\t-> CLONE_FILES");
251  if (flags & CLONE_SIGHAND) SC_NOTICE("\t\t-> CLONE_SIGHAND");
252  if (flags & CLONE_PTRACE) SC_NOTICE("\t\t-> CLONE_PTRACE");
253  if (flags & CLONE_VFORK) SC_NOTICE("\t\t-> CLONE_VFORK");
254  if (flags & CLONE_PARENT) SC_NOTICE("\t\t-> CLONE_PARENT");
255  if (flags & CLONE_THREAD) SC_NOTICE("\t\t-> CLONE_THREAD");
256  if (flags & CLONE_NEWNS) SC_NOTICE("\t\t-> CLONE_NEWNS");
257  if (flags & CLONE_SYSVSEM) SC_NOTICE("\t\t-> CLONE_SYSVSEM");
258  if (flags & CLONE_SETTLS) SC_NOTICE("\t\t-> CLONE_SETTLS");
259  if (flags & CLONE_PARENT_SETTID) SC_NOTICE("\t\t-> CLONE_PARENT_SETTID");
260  if (flags & CLONE_CHILD_CLEARTID) SC_NOTICE("\t\t-> CLONE_CHILD_CLEARTID");
261  if (flags & CLONE_DETACHED) SC_NOTICE("\t\t-> CLONE_DETACHED");
262  if (flags & CLONE_UNTRACED) SC_NOTICE("\t\t-> CLONE_UNTRACED");
263  if (flags & CLONE_CHILD_SETTID) SC_NOTICE("\t\t-> CLONE_CHILD_SETTID");
264  if (flags & CLONE_NEWUTS) SC_NOTICE("\t\t-> CLONE_NEWUTS");
265  if (flags & CLONE_NEWIPC) SC_NOTICE("\t\t-> CLONE_NEWIPC");
266  if (flags & CLONE_NEWUSER) SC_NOTICE("\t\t-> CLONE_NEWUSER");
267  if (flags & CLONE_NEWPID) SC_NOTICE("\t\t-> CLONE_NEWPID");
268  if (flags & CLONE_NEWNET) SC_NOTICE("\t\t-> CLONE_NEWNET");
269  if (flags & CLONE_IO) SC_NOTICE("\t\t-> CLONE_IO");
270 #endif
271 
272  if ((flags & CLONE_VM) == CLONE_VM)
273  {
274  // clone vm doesn't actually copy the address space, it shares it
275 
276  // New child's stack. Must be valid as we're sharing the address space.
277  if (!child_stack)
278  {
279  SYSCALL_ERROR(InvalidArgument);
280  return -1;
281  }
282 
283  // Set up stack for new thread.
284  clonedState.setStackPointer(reinterpret_cast<uintptr_t>(child_stack));
285 
286  // Child returns 0 -- parent returns the new thread ID.
287  clonedState.setSyscallReturnValue(0);
288 
289  // pretty much just a thread
290  Process *pParentProcess =
291  Processor::information().getCurrentThread()->getParent();
292 
293  // Create a new thread for the new process. Make sure it's
294  // delayed-start so we can ensure the new thread ID gets written to the
295  // right places in memory.
296  Thread *pThread = new Thread(pParentProcess, clonedState, true);
297  pThread->setTlsBase(newtls);
298  pThread->detach();
299 
300  // Update the child ID before letting the child run
301  if (flags & CLONE_CHILD_SETTID)
302  {
303  *ctid = pThread->getId();
304  }
305  if (flags & CLONE_PARENT_SETTID)
306  {
307  *ptid = pThread->getId();
308  }
309 
310  pThread->setStatus(Thread::Ready); // good to go now.
311 
312  // Parent gets the new thread ID.
313  SC_NOTICE(" -> " << pThread->getId() << " [new thread]");
314  return pThread->getId();
315  }
316 
317  // No child stack means CoW the existing one, but if one is specified we
318  // should use it instead!
319  if (child_stack)
320  {
321  clonedState.setStackPointer(reinterpret_cast<uintptr_t>(child_stack));
322  }
323 
324  // Inhibit signals to the parent
325  for (int sig = 0; sig < 32; sig++)
326  Processor::information().getCurrentThread()->inhibitEvent(sig, true);
327 
328  // Create a new process.
329  Process *pParentProcess =
330  Processor::information().getCurrentThread()->getParent();
331  PosixProcess *pProcess = new PosixProcess(pParentProcess);
332  if (!pProcess)
333  {
334  SYSCALL_ERROR(OutOfMemory);
335  SC_NOTICE(" -> ENOMEM");
336  return -1;
337  }
338 
339  PosixSubsystem *pParentSubsystem =
340  reinterpret_cast<PosixSubsystem *>(pParentProcess->getSubsystem());
341  PosixSubsystem *pSubsystem = new PosixSubsystem(*pParentSubsystem);
342  if (!pSubsystem || !pParentSubsystem)
343  {
344  ERROR("No subsystem for one or both of the processes!");
345 
346  if (pSubsystem)
347  delete pSubsystem;
348  if (pParentSubsystem)
349  delete pParentSubsystem;
350  delete pProcess;
351 
352  SYSCALL_ERROR(OutOfMemory);
353 
354  // Allow signals again, something went wrong
355  for (int sig = 0; sig < 32; sig++)
356  Processor::information().getCurrentThread()->inhibitEvent(
357  sig, false);
358  SC_NOTICE(" -> ENOMEM");
359  return -1;
360  }
361  pProcess->setSubsystem(pSubsystem);
362  pSubsystem->setProcess(pProcess);
363 
364  // Copy POSIX Process Group information if needed
365  if (pParentProcess->getType() == Process::Posix)
366  {
367  PosixProcess *p = static_cast<PosixProcess *>(pParentProcess);
368  pProcess->setProcessGroup(p->getProcessGroup());
369 
370  // default to being a member of the group
371  pProcess->setGroupMembership(PosixProcess::Member);
372 
373  // Do not adopt leadership status.
374  if (p->getGroupMembership() == PosixProcess::Leader)
375  {
376  SC_NOTICE("fork parent was a group leader.");
377  }
378  else
379  {
380  SC_NOTICE(
381  "fork parent had status "
382  << static_cast<int>(p->getGroupMembership()) << "...");
383  pProcess->setGroupMembership(p->getGroupMembership());
384  }
385  }
386 
387  // Register with the dynamic linker.
388  DynamicLinker *oldLinker = pProcess->getLinker();
389  if (oldLinker)
390  {
391  DynamicLinker *newLinker = new DynamicLinker(*oldLinker);
392  pProcess->setLinker(newLinker);
393  }
394 
395  MemoryMapManager::instance().clone(pProcess);
396 
397  // Copy the file descriptors from the parent
398  pSubsystem->copyDescriptors(pParentSubsystem);
399 
400  // Child returns 0.
401  clonedState.setSyscallReturnValue(0);
402 
403  // Allow signals to the parent again
404  for (int sig = 0; sig < 32; sig++)
405  Processor::information().getCurrentThread()->inhibitEvent(sig, false);
406 
407  // Set ctid in the new address space if we are required to.
408  if (flags & CLONE_CHILD_SETTID)
409  {
410  VirtualAddressSpace &curr =
411  Processor::information().getVirtualAddressSpace();
412  VirtualAddressSpace *va = pProcess->getAddressSpace();
414  *ctid = pProcess->getId();
416  }
417 
418  // Create a new thread for the new process.
419  Thread *pThread = new Thread(pProcess, clonedState);
420  pThread->detach();
421 
422  // Fix up the main thread in the child.
426  pedigree_copy_posix_thread(
427  Processor::information().getCurrentThread(), pParentSubsystem, pThread,
428  pSubsystem);
429 
430  // Parent returns child ID.
431  SC_NOTICE(" -> " << pProcess->getId() << " [new process]");
432  return pProcess->getId();
433 }
434 
435 int posix_fork(SyscallState &state)
436 {
437  SC_NOTICE("fork");
438 
439  return posix_clone(state, 0, 0, 0, 0, 0);
440 }
441 
442 int posix_execve(
443  const char *name, const char **argv, const char **env, SyscallState &state)
444 {
447  reinterpret_cast<uintptr_t>(name), PATH_MAX,
448  PosixSubsystem::SafeRead))
449  {
450  SC_NOTICE("execve -> invalid address");
451  SYSCALL_ERROR(InvalidArgument);
452  return -1;
453  }
454 
455  SC_NOTICE("execve(\"" << name << "\")");
456 
457  // Bad arguments?
458  if (argv == 0 || env == 0)
459  {
460  SYSCALL_ERROR(ExecFormatError);
461  return -1;
462  }
463 
464  Process *pProcess =
465  Processor::information().getCurrentThread()->getParent();
466  PosixSubsystem *pSubsystem =
467  reinterpret_cast<PosixSubsystem *>(pProcess->getSubsystem());
468  if (!pSubsystem)
469  {
470  ERROR("No subsystem for this process!");
471  return -1;
472  }
473 
474  // Build argv and env lists.
475  Vector<String> listArgv, listEnv;
476  for (const char **arg = argv; *arg != 0; ++arg)
477  {
478  listArgv.pushBack(String(*arg));
479  }
480  for (const char **e = env; *e != 0; ++e)
481  {
482  listEnv.pushBack(String(*e));
483  }
484 
485  // Normalise path to ensure we have the correct path to invoke.
486  String invokePath;
487  normalisePath(invokePath, name);
488 
489  if (!pSubsystem->invoke(invokePath, listArgv, listEnv, state))
490  {
491  SC_NOTICE(" -> execve failed in invoke");
492  return -1;
493  }
494 
495  // Technically, we never get here.
496  return 0;
497 }
498 
503 {
504  public:
505  WaitCleanup(List<Process *> *cleanupList, Semaphore *lock)
506  : m_List(cleanupList), m_Lock(lock), m_pTerminated(0)
507  {
508  }
509 
515  void terminated(Process *pProcess)
516  {
517  m_pTerminated = pProcess;
518  pProcess->removeWaiter(m_Lock);
519  }
520 
521  ~WaitCleanup()
522  {
523  for (List<Process *>::Iterator it = m_List->begin();
524  it != m_List->end(); ++it)
525  {
526  if ((*it) == m_pTerminated)
527  continue;
528 
529  (*it)->removeWaiter(m_Lock);
530  }
531  }
532 
533  private:
534  List<Process *> *m_List;
535  Semaphore *m_Lock;
536  Process *m_pTerminated;
537 };
538 
539 int posix_waitpid(const int pid, int *status, int options)
540 {
541  if (status && !PosixSubsystem::checkAddress(
542  reinterpret_cast<uintptr_t>(status), sizeof(int),
543  PosixSubsystem::SafeWrite))
544  {
545  SC_NOTICE("waitpid -> invalid address");
546  SYSCALL_ERROR(InvalidArgument);
547  return -1;
548  }
549 
550  SC_NOTICE(
551  "waitpid(" << pid << " [" << Dec << pid << Hex << "], " << options
552  << ")");
553 
554  // Find the set of processes to check.
555  List<Process *> processList;
556 
557  // Our lock, which we will assign to each process (assuming WNOHANG is not
558  // set).
559  Semaphore waitLock(0);
560 
561  // RAII object to clean up when we return (instead of goto or other
562  // ugliness).
563  WaitCleanup cleanup(&processList, &waitLock);
564 
565  // Metadata about the calling process.
566  PosixProcess *pThisProcess = static_cast<PosixProcess *>(
567  Processor::information().getCurrentThread()->getParent());
568  ProcessGroup *pThisGroup = pThisProcess->getProcessGroup();
569 
570  // Check for the process(es) we need to check for.
571  bool bBlock = (options & WNOHANG) != WNOHANG;
572  if (bBlock)
573  {
574  SC_NOTICE(" -> blocking until a process reports status");
575  }
576  else
577  {
578  SC_NOTICE(" -> WNOHANG");
579  }
580 
581  size_t i = 0;
582  for (; i < Scheduler::instance().getNumProcesses(); ++i)
583  {
584  Process *pProcess = Scheduler::instance().getProcess(i);
585  if (pProcess == pThisProcess)
586  continue; // Don't wait for ourselves.
587 
588  if (pProcess->getState() == Process::Reaped)
589  continue; // Reaped but not yet destroyed.
590 
591  if ((pid <= 0) && (pProcess->getType() == Process::Posix))
592  {
593  PosixProcess *pPosixProcess = static_cast<PosixProcess *>(pProcess);
594  ProcessGroup *pGroup = pPosixProcess->getProcessGroup();
595  if (pid == 0)
596  {
597  // Any process in the same process group as the caller.
598  if (!(pGroup && pThisGroup))
599  continue;
600  if (pGroup->processGroupId != pThisGroup->processGroupId)
601  continue;
602  }
603  else if (pid == -1)
604  {
605  // Wait for any child.
606  if (pProcess->getParent() != pThisProcess)
607  continue;
608  }
609  else if (pGroup && (pGroup->processGroupId != (pid * -1)))
610  {
611  // Absolute group ID reference
612  continue;
613  }
614  }
615  else if ((pid > 0) && (static_cast<int>(pProcess->getId()) != pid))
616  continue;
617  else if (pProcess->getType() != Process::Posix)
618  continue;
619 
620  // Okay, the process is good.
621  processList.pushBack(pProcess);
622 
623  // If not WNOHANG, subscribe our lock to this process' state changes.
624  // If the process is in the process of terminating, we can add our
625  // lock and hope for the best.
626  if (bBlock || (pProcess->getState() == Process::Terminating))
627  {
628  SC_NOTICE(
629  " -> adding our wait lock to process " << Dec
630  << pProcess->getId());
631  pProcess->addWaiter(&waitLock);
632  bBlock = true;
633  }
634  }
635 
636  // No children?
637  if (processList.count() == 0)
638  {
639  SYSCALL_ERROR(NoChildren);
640  SC_NOTICE(" -> no children");
641  return -1;
642  }
643 
644  // Main wait loop.
645  while (1)
646  {
647  // Check each process for state.
648  for (List<Process *>::Iterator it = processList.begin();
649  it != processList.end(); ++it)
650  {
651  Process *pProcess = *it;
652  int this_pid = pProcess->getId();
653 
654  // Does this process even exist anymore?
655 
656  // Zombie or reaped?
657  // Because processes don't get actually destroyed until no more
658  // waiters exist on them, we can safely do this and it makes sure
659  // multiple waitpid() calls on the same process do the right thing
660  if (pProcess->getState() == Process::Terminated ||
661  pProcess->getState() == Process::Reaped)
662  {
663  if (status)
664  *status = pProcess->getExitStatus();
665 
666  // Delete the process; it's been reaped good and proper.
667  SC_NOTICE(
668  "waitpid: " << Dec << this_pid << " reaped ["
669  << pProcess->getExitStatus() << "]");
670  cleanup.terminated(pProcess);
671  if (pProcess->waiterCount() < 1)
672  {
673  SC_NOTICE("waitpid: destroying reaped process");
674  delete pProcess;
675  }
676  else
677  {
678  SC_NOTICE("waitpid: marking process reaped");
679  pProcess->reap();
680  }
681  return this_pid;
682  }
683  // Suspended (and WUNTRACED)?
684  else if ((options & 2) && pProcess->hasSuspended())
685  {
686  if (status)
687  *status = pProcess->getExitStatus();
688 
689  SC_NOTICE("waitpid: " << Dec << this_pid << " suspended.");
690  return this_pid;
691  }
692  // Continued (and WCONTINUED)?
693  else if ((options & 4) && pProcess->hasResumed())
694  {
695  if (status)
696  *status = pProcess->getExitStatus();
697 
698  SC_NOTICE("waitpid: " << Dec << this_pid << " resumed.");
699  return this_pid;
700  }
701  else
702  {
703  SC_NOTICE(
704  "waitpid: " << Dec << this_pid << " has no status change");
705  }
706  }
707 
708  // Don't wait for any processes to report status if we are not meant
709  // to be blocking.
710  if (!bBlock)
711  {
712  SC_NOTICE("waitpid: not blocking, no status to report");
713  return 0;
714  }
715 
716  // Wait for processes to report in.
717  waitLock.acquire();
718 
719  // We can get woken up by our process dying. Handle that here.
720  if (Processor::information().getCurrentThread()->getUnwindState() ==
721  Thread::Exit)
722  {
723  SC_NOTICE("waitpid: unwind state means exit");
724  return -1;
725  }
726 
727  // We get notified by processes just before they change state.
728  // Make sure they are scheduled into that state by yielding.
730  }
731 }
732 
733 int posix_exit(int code, bool allthreads)
734 {
735  SC_NOTICE("exit(" << Dec << (code & 0xFF) << Hex << ")");
736 
737  Process *pProcess =
738  Processor::information().getCurrentThread()->getParent();
739  PosixSubsystem *pSubsystem =
740  reinterpret_cast<PosixSubsystem *>(pProcess->getSubsystem());
741 
742  if (allthreads)
743  {
744  SC_NOTICE(" -> thread group");
745  pSubsystem->exit(code);
746  }
747  else
748  {
749  // Not all threads - only kill current thread!
750  SC_NOTICE(" -> current thread");
751  Processor::information().getScheduler().killCurrentThread();
752  }
753 
754  // Should NEVER get here.
755  FATAL("exit method returned in posix_exit");
756 }
757 
758 int posix_getpid()
759 {
760  SC_NOTICE("getpid");
761 
762  Process *pProcess =
763  Processor::information().getCurrentThread()->getParent();
764  return pProcess->getId();
765 }
766 
767 int posix_getppid()
768 {
769  SC_NOTICE("getppid");
770 
771  Process *pProcess =
772  Processor::information().getCurrentThread()->getParent();
773  if (!pProcess->getParent())
774  return 0;
775  return pProcess->getParent()->getId();
776 }
777 
778 int posix_gettimeofday(timeval *tv, struct timezone *tz)
779 {
781  reinterpret_cast<uintptr_t>(tv), sizeof(timeval),
782  PosixSubsystem::SafeWrite))
783  {
784  SC_NOTICE("gettimeofday -> invalid address");
785  SYSCALL_ERROR(InvalidArgument);
786  return -1;
787  }
788 
789  SC_NOTICE("gettimeofday");
790 
791  Timer *pTimer = Machine::instance().getTimer();
792 
793  // UNIX timestamp + remaining time portion, in microseconds.
794  tv->tv_sec = pTimer->getUnixTimestamp();
795  tv->tv_usec = pTimer->getNanosecond() / 1000U;
796 
797  return 0;
798 }
799 
800 int posix_settimeofday(const timeval *tv, const struct timezone *tz)
801 {
802  SC_NOTICE("settimeofday");
803 
805  reinterpret_cast<uintptr_t>(tv), sizeof(timeval),
806  PosixSubsystem::SafeRead))
807  {
808  SC_NOTICE(" -> invalid address");
809  SYSCALL_ERROR(BadAddress);
810  return -1;
811  }
812 
814 
815  return 0;
816 }
817 
818 time_t posix_time(time_t *tval)
819 {
820  SC_NOTICE("time");
821 
822  if (tval && !PosixSubsystem::checkAddress(
823  reinterpret_cast<uintptr_t>(tval), sizeof(time_t),
824  PosixSubsystem::SafeWrite))
825  {
826  SC_NOTICE(" -> invalid address");
827  SYSCALL_ERROR(BadAddress);
828  return -1;
829  }
830 
831  time_t result = Time::getTime();
832  if (tval)
833  {
834  *tval = result;
835  }
836 
837  return result;
838 }
839 
840 clock_t posix_times(struct tms *tm)
841 {
843  reinterpret_cast<uintptr_t>(tm), sizeof(struct tms),
844  PosixSubsystem::SafeWrite))
845  {
846  SC_NOTICE("posix_times -> invalid address");
847  SYSCALL_ERROR(InvalidArgument);
848  return -1;
849  }
850 
851  SC_NOTICE("times");
852 
853  Process *pProcess =
854  Processor::information().getCurrentThread()->getParent();
855 
856  ByteSet(tm, 0, sizeof(struct tms));
857  tm->tms_utime = pProcess->getUserTime();
858  tm->tms_stime = pProcess->getKernelTime();
859 
860  SC_NOTICE(
861  "times: u=" << pProcess->getUserTime()
862  << ", s=" << pProcess->getKernelTime());
863 
864  return Time::getTimeNanoseconds() - pProcess->getStartTime();
865 }
866 
867 int posix_getrusage(int who, struct rusage *r)
868 {
869  SC_NOTICE("getrusage who=" << who);
870 
872  reinterpret_cast<uintptr_t>(r), sizeof(struct rusage),
873  PosixSubsystem::SafeWrite))
874  {
875  SC_NOTICE("posix_getrusage -> invalid address");
876  SYSCALL_ERROR(BadAddress);
877  return -1;
878  }
879 
880  if (who != RUSAGE_SELF)
881  {
882  SC_NOTICE("posix_getrusage -> non-RUSAGE_SELF not supported");
883  SYSCALL_ERROR(InvalidArgument);
884  ByteSet(r, 0, sizeof(struct rusage));
885  return -1;
886  }
887 
888  Process *pProcess =
889  Processor::information().getCurrentThread()->getParent();
890 
891  Time::Timestamp user = pProcess->getUserTime();
892  Time::Timestamp kernel = pProcess->getKernelTime();
893 
894  ByteSet(r, 0, sizeof(struct rusage));
895  r->ru_utime.tv_sec = user / Time::Multiplier::Second;
896  r->ru_utime.tv_usec =
897  (user % Time::Multiplier::Second) / Time::Multiplier::Microsecond;
898  r->ru_stime.tv_sec = kernel / Time::Multiplier::Second;
899  r->ru_stime.tv_usec =
900  (kernel % Time::Multiplier::Second) / Time::Multiplier::Microsecond;
901 
902  return 0;
903 }
904 
905 static char *store_str_to(char *str, char *strend, String s)
906 {
907  int i = 0;
908  while (s[i] && str != strend)
909  *str++ = s[i++];
910  *str++ = '\0';
911 
912  return str;
913 }
914 
915 int posix_getpwent(passwd *pw, int n, char *str)
916 {
919  reinterpret_cast<uintptr_t>(pw), sizeof(passwd),
920  PosixSubsystem::SafeWrite))
921  {
922  SC_NOTICE("getpwent -> invalid address");
923  SYSCALL_ERROR(InvalidArgument);
924  return -1;
925  }
926 
927  SC_NOTICE("getpwent(" << Dec << n << Hex << ")");
928 
929  // Grab the given user.
930  User *pUser = UserManager::instance().getUser(n);
931  if (!pUser)
932  return -1;
933 
934  char *strend = str + 256; // If we get here, we've gone off the end of str.
935 
936  pw->pw_name = str;
937  str = store_str_to(str, strend, pUser->getUsername());
938 
939  pw->pw_passwd = str;
940  *str++ = '\0';
941 
942  pw->pw_uid = pUser->getId();
943  pw->pw_gid = pUser->getDefaultGroup()->getId();
944  str = store_str_to(str, strend, pUser->getFullName());
945 
946  pw->pw_gecos = str;
947  *str++ = '\0';
948  pw->pw_dir = str;
949  str = store_str_to(str, strend, pUser->getHome());
950 
951  pw->pw_shell = str;
952  store_str_to(str, strend, pUser->getShell());
953 
954  return 0;
955 }
956 
957 int posix_getpwnam(passwd *pw, const char *name, char *str)
958 {
961  reinterpret_cast<uintptr_t>(pw), sizeof(passwd),
962  PosixSubsystem::SafeWrite) &&
964  reinterpret_cast<uintptr_t>(name), PATH_MAX,
965  PosixSubsystem::SafeRead)))
966  {
967  SC_NOTICE("getpwname -> invalid address");
968  SYSCALL_ERROR(InvalidArgument);
969  return -1;
970  }
971 
972  SC_NOTICE("getpwname(" << name << ")");
973 
974  // Grab the given user.
975  User *pUser = UserManager::instance().getUser(String(name));
976  if (!pUser)
977  return -1;
978 
979  char *strend = str + 256; // If we get here, we've gone off the end of str.
980 
981  pw->pw_name = str;
982  str = store_str_to(str, strend, pUser->getUsername());
983 
984  pw->pw_passwd = str;
985  *str++ = '\0';
986 
987  pw->pw_uid = pUser->getId();
988  pw->pw_gid = pUser->getDefaultGroup()->getId();
989  str = store_str_to(str, strend, pUser->getFullName());
990 
991  pw->pw_gecos = str;
992  *str++ = '\0';
993 
994  pw->pw_dir = str;
995  str = store_str_to(str, strend, pUser->getHome());
996 
997  pw->pw_shell = str;
998  store_str_to(str, strend, pUser->getShell());
999 
1000  return 0;
1001 }
1002 
1003 int posix_getgrnam(const char *name, struct group *out)
1004 {
1006  reinterpret_cast<uintptr_t>(name), PATH_MAX,
1007  PosixSubsystem::SafeRead) &&
1009  reinterpret_cast<uintptr_t>(out), sizeof(struct group),
1010  PosixSubsystem::SafeWrite)))
1011  {
1012  SC_NOTICE("getgrnam -> invalid address");
1013  SYSCALL_ERROR(InvalidArgument);
1014  return -1;
1015  }
1016 
1017  SC_NOTICE("getgrnam(" << name << ")");
1018 
1019  Group *pGroup = UserManager::instance().getGroup(String(name));
1020  if (!pGroup)
1021  {
1022  // No error needs to be set if not found.
1023  return -1;
1024  }
1025 
1027  StringCopy(out->gr_name, static_cast<const char *>(pGroup->getName()));
1028  out->gr_gid = pGroup->getId();
1029 
1030  return 0;
1031 }
1032 
1033 int posix_getgrgid(gid_t id, struct group *out)
1034 {
1036  reinterpret_cast<uintptr_t>(out), sizeof(struct group),
1037  PosixSubsystem::SafeWrite)))
1038  {
1039  SC_NOTICE("getgrgid( -> invalid address");
1040  SYSCALL_ERROR(InvalidArgument);
1041  return -1;
1042  }
1043 
1044  SC_NOTICE("getgrgid(" << id << ")");
1045 
1046  Group *pGroup = UserManager::instance().getGroup(id);
1047  if (!pGroup)
1048  {
1049  // No error needs to be set if not found.
1050  return -1;
1051  }
1052 
1054  StringCopy(out->gr_name, static_cast<const char *>(pGroup->getName()));
1055  out->gr_gid = pGroup->getId();
1056 
1057  return 0;
1058 }
1059 
1060 uid_t posix_getuid()
1061 {
1062  SC_NOTICE("getuid");
1063 
1064  uid_t uid = -1;
1065  posix_getresuid(&uid, nullptr, nullptr);
1066  return uid;
1067 }
1068 
1069 gid_t posix_getgid()
1070 {
1071  SC_NOTICE("getgid");
1072 
1073  gid_t gid = -1;
1074  posix_getresgid(&gid, nullptr, nullptr);
1075  return gid;
1076 }
1077 
1078 uid_t posix_geteuid()
1079 {
1080  SC_NOTICE("geteuid");
1081 
1082  uid_t euid = -1;
1083  posix_getresuid(nullptr, &euid, nullptr);
1084  return euid;
1085 }
1086 
1087 gid_t posix_getegid()
1088 {
1089  SC_NOTICE("getegid");
1090 
1091  uid_t egid = -1;
1092  posix_getresgid(nullptr, &egid, nullptr);
1093  return egid;
1094 }
1095 
1096 int posix_setuid(uid_t uid)
1097 {
1098  SC_NOTICE("setuid(" << uid << ")");
1099  return posix_setresuid(uid, uid, -1);
1100 }
1101 
1102 int posix_setgid(gid_t gid)
1103 {
1104  SC_NOTICE("setgid(" << gid << ")");
1105  return posix_setresgid(gid, gid, -1);
1106 }
1107 
1108 int posix_seteuid(uid_t euid)
1109 {
1110  SC_NOTICE("seteuid(" << euid << ")");
1111  return posix_setresuid(-1, euid, -1);
1112 }
1113 
1114 int posix_setegid(gid_t egid)
1115 {
1116  SC_NOTICE("setegid(" << egid << ")");
1117  return posix_setresgid(-1, egid, -1);
1118 }
1119 
1120 EXPORTED_PUBLIC int pedigree_login(int uid, const char *password)
1121 {
1123  reinterpret_cast<uintptr_t>(password), PATH_MAX,
1124  PosixSubsystem::SafeRead))
1125  {
1126  SC_NOTICE("pedigree_login -> invalid address");
1127  SYSCALL_ERROR(InvalidArgument);
1128  return -1;
1129  }
1130 
1131  // Grab the given user.
1132  User *pUser = UserManager::instance().getUser(uid);
1133  if (!pUser)
1134  return -1;
1135 
1136  if (pUser->login(String(password)))
1137  return 0;
1138  else
1139  return -1;
1140 }
1141 
1142 int posix_setsid()
1143 {
1144  SC_NOTICE("setsid");
1145 
1146  // Not a POSIX process
1147  Process *pStockProcess =
1148  Processor::information().getCurrentThread()->getParent();
1149  if (pStockProcess->getType() != Process::Posix)
1150  {
1151  ERROR("setsid called on something not a POSIX process");
1152  return -1;
1153  }
1154 
1155  PosixProcess *pProcess = static_cast<PosixProcess *>(pStockProcess);
1156 
1157  // Already in a group?
1158  PosixProcess::Membership myMembership = pProcess->getGroupMembership();
1159  if (myMembership != PosixProcess::NoGroup)
1160  {
1161  // If we don't actually have a group, something's gone wrong
1162  if (!pProcess->getProcessGroup())
1163  FATAL("Process' is apparently a member of a group, but its group "
1164  "pointer is invalid.");
1165 
1166  // Are we the group leader of that other group?
1167  if (myMembership == PosixProcess::Leader)
1168  {
1169  SC_NOTICE("setsid() called while the leader of another group");
1170  SYSCALL_ERROR(PermissionDenied);
1171  return -1;
1172  }
1173  else
1174  {
1175  SC_NOTICE(
1176  "setsid() called while a member of another group ["
1177  << pProcess->getProcessGroup()->processGroupId << "]");
1178  }
1179  }
1180 
1181  // Delete the old group, if any
1182  ProcessGroup *pGroup = pProcess->getProcessGroup();
1183  if (pGroup)
1184  {
1185  pProcess->setProcessGroup(0);
1186 
1189  if (pGroup->Members.count() <= 1) // Us or nothing
1190  delete pGroup;
1191  }
1192 
1193  // Create the new session.
1194  PosixSession *pNewSession = new PosixSession();
1195  pNewSession->Leader = pProcess;
1196  pProcess->setSession(pNewSession);
1197 
1198  // Create a new process group and join it.
1199  ProcessGroup *pNewGroup = new ProcessGroup;
1200  pNewGroup->processGroupId = pProcess->getId();
1201  pNewGroup->Leader = pProcess;
1202  pNewGroup->Members.clear();
1203 
1204  // We're now a group leader - we got promoted!
1205  pProcess->setProcessGroup(pNewGroup);
1206  pProcess->setGroupMembership(PosixProcess::Leader);
1207 
1208  // Remove controlling terminal.
1209  pProcess->setCtty(0);
1210 
1211  SC_NOTICE(
1212  "setsid: now part of a group [id=" << pNewGroup->processGroupId
1213  << "]!");
1214 
1215  // Success!
1216  return pNewGroup->processGroupId;
1217 }
1218 
1219 int posix_setpgid(int pid_, int pgid)
1220 {
1221  size_t pid = pid_;
1222  SC_NOTICE("setpgid(" << pid << ", " << pgid << ")");
1223 
1224  // Handle invalid group ID
1225  if (pgid < 0)
1226  {
1227  SYSCALL_ERROR(InvalidArgument);
1228  SC_NOTICE(" -> EINVAL");
1229  return -1;
1230  }
1231 
1232  Process *pBaseProcess =
1233  Processor::information().getCurrentThread()->getParent();
1234  if (pBaseProcess->getType() != Process::Posix)
1235  {
1236  SC_NOTICE(" -> not a posix process");
1237  return -1;
1238  }
1239 
1240  // Are we already a leader of a session?
1241  PosixProcess *pProcess = static_cast<PosixProcess *>(pBaseProcess);
1242 
1243  // Handle zero PID and PGID.
1244  if (!pid)
1245  {
1246  pid = pProcess->getId();
1247  }
1248  if (!pgid)
1249  {
1250  pgid = pid;
1251  }
1252 
1253  ProcessGroup *pGroup = pProcess->getProcessGroup();
1254  PosixSession *pSession = pProcess->getSession();
1255 
1256  // Is this us or a child of us?
1258  if (pid != pProcess->getId())
1259  {
1260  // Find the target process - it's not us
1261  Process *pTargetProcess = nullptr;
1262  for (size_t i = 0; i < Scheduler::instance().getNumProcesses(); ++i)
1263  {
1264  Process *check = Scheduler::instance().getProcess(i);
1265  if (check->getType() != Process::Posix)
1266  continue;
1267 
1268  if (check->getId() == pid)
1269  {
1270  pTargetProcess = check;
1271  break;
1272  }
1273  }
1274 
1275  if (!pTargetProcess)
1276  {
1277  SC_NOTICE(" -> process doesn't exist");
1278  SYSCALL_ERROR(NoSuchProcess);
1279  return -1;
1280  }
1281 
1282  // Is this process a child of us?
1283  Process *parent = pTargetProcess->getParent();
1284  while (parent != nullptr)
1285  {
1286  if (parent == pProcess)
1287  {
1288  // ok!
1289  break;
1290  }
1291  }
1292 
1293  if (parent != pProcess)
1294  {
1295  // Not a child!
1296  SC_NOTICE(" -> target process is not a descendant of the current "
1297  "process");
1298  SYSCALL_ERROR(NoSuchProcess);
1299  return -1;
1300  }
1301 
1302  if (static_cast<PosixProcess *>(pTargetProcess)->getSession() !=
1303  pSession)
1304  {
1305  SC_NOTICE(" -> target process is in a different session");
1306  SYSCALL_ERROR(NotEnoughPermissions);
1307  return -1;
1308  }
1309 
1310  pBaseProcess = pTargetProcess;
1311  pProcess = static_cast<PosixProcess *>(pTargetProcess);
1312  pGroup = pProcess->getProcessGroup();
1313  pSession = pProcess->getSession();
1314  }
1315 
1316  if (pGroup && (pGroup->processGroupId == pgid))
1317  {
1318  // Already a member.
1319  SC_NOTICE(" -> OK, already a member!");
1320  return 0;
1321  }
1322 
1323  if (pSession && (pSession->Leader == pProcess))
1324  {
1325  // Already a session leader.
1326  SYSCALL_ERROR(PermissionDenied);
1327  SC_NOTICE(" -> EPERM (already leader)");
1328  return 0;
1329  }
1330 
1331  // Does the process group exist?
1332  Process *check = 0;
1333  for (size_t i = 0; i < Scheduler::instance().getNumProcesses(); ++i)
1334  {
1335  check = Scheduler::instance().getProcess(i);
1336  if (check->getType() != Process::Posix)
1337  continue;
1338 
1339  PosixProcess *posixCheck = static_cast<PosixProcess *>(check);
1340  ProcessGroup *pGroupCheck = posixCheck->getProcessGroup();
1341  if (pGroupCheck)
1342  {
1343  if (pGroupCheck->processGroupId == pgid)
1344  {
1345  // Join this group.
1346  pProcess->setProcessGroup(pGroupCheck);
1347  pProcess->setGroupMembership(PosixProcess::Member);
1348  SC_NOTICE(" -> OK, joined!");
1349  return 0;
1350  }
1351  }
1352  }
1353 
1354  // No, the process group does not exist. Create it.
1355  ProcessGroup *pNewGroup = new ProcessGroup;
1356  pNewGroup->processGroupId = pProcess->getId();
1357  pNewGroup->Leader = pProcess;
1358  pNewGroup->Members.clear();
1359 
1360  // We're now a group leader - we got promoted!
1361  pProcess->setProcessGroup(pNewGroup);
1362  pProcess->setGroupMembership(PosixProcess::Leader);
1363 
1364  SC_NOTICE(" -> OK, created!");
1365  return 0;
1366 }
1367 
1368 int posix_getpgid(int pid)
1369 {
1370  if (!pid)
1371  {
1372  return posix_getpgrp();
1373  }
1374 
1375  size_t pid_ = pid;
1376 
1377  SC_NOTICE("getpgid(" << pid << ")");
1378 
1379  // Find the target process - it's not us
1380  Process *pTargetProcess = nullptr;
1381  for (size_t i = 0; i < Scheduler::instance().getNumProcesses(); ++i)
1382  {
1383  Process *check = Scheduler::instance().getProcess(i);
1384  if (check->getType() != Process::Posix)
1385  continue;
1386 
1387  if (check->getId() == pid_)
1388  {
1389  pTargetProcess = check;
1390  break;
1391  }
1392  }
1393 
1394  if (!pTargetProcess)
1395  {
1396  SC_NOTICE(" -> target process not found");
1397  SYSCALL_ERROR(NoSuchProcess);
1398  return -1;
1399  }
1400 
1401  PosixProcess *pProcess = static_cast<PosixProcess *>(pTargetProcess);
1402  ProcessGroup *pGroup = pProcess->getProcessGroup();
1403 
1404  if (pGroup)
1405  {
1406  SC_NOTICE(" -> " << pGroup->processGroupId);
1407  return pGroup->processGroupId;
1408  }
1409 
1410  SC_NOTICE(" -> target process did not have a group");
1411  SYSCALL_ERROR(NoSuchProcess);
1412  return -1;
1413 }
1414 
1415 int posix_getpgrp()
1416 {
1417  SC_NOTICE("getpgrp");
1418 
1419  PosixProcess *pProcess = static_cast<PosixProcess *>(
1420  Processor::information().getCurrentThread()->getParent());
1421  ProcessGroup *pGroup = pProcess->getProcessGroup();
1422 
1423  int result = 0;
1424  if (pGroup)
1425  {
1426  SC_NOTICE(" -> using existing group id");
1427  result = pGroup->processGroupId;
1428  }
1429  else
1430  {
1431  SC_NOTICE(" -> using pid only");
1432  result = pProcess->getId(); // Fallback if no ProcessGroup pointer yet
1433  }
1434 
1435  SC_NOTICE(" -> " << result);
1436  return result;
1437 }
1438 
1439 mode_t posix_umask(mode_t mask)
1440 {
1441  SC_NOTICE("umask(" << Oct << mask << ")");
1442 
1443  // Not a POSIX process
1444  Process *pStockProcess =
1445  Processor::information().getCurrentThread()->getParent();
1446  if (pStockProcess->getType() != Process::Posix)
1447  {
1448  SC_NOTICE("umask -> called on something not a POSIX process");
1449  SYSCALL_ERROR(InvalidArgument);
1450  return -1;
1451  }
1452 
1453  PosixProcess *pProcess = static_cast<PosixProcess *>(pStockProcess);
1454 
1455  uint32_t previous = pProcess->getMask();
1456  pProcess->setMask(mask);
1457 
1458  return previous;
1459 }
1460 
1461 int posix_linux_syslog(int type, char *buf, int len)
1462 {
1464  reinterpret_cast<uintptr_t>(buf), len, PosixSubsystem::SafeRead))
1465  {
1466  SC_NOTICE("linux_syslog -> invalid address");
1467  SYSCALL_ERROR(InvalidArgument);
1468  return -1;
1469  }
1470 
1471  SC_NOTICE("linux_syslog");
1472 
1473  if (len > 512)
1474  len = 512;
1475 
1476  switch (type)
1477  {
1478  case 0:
1479  SC_NOTICE(" -> close log");
1480  return 0;
1481 
1482  case 1:
1483  SC_NOTICE(" -> open log");
1484  return 0;
1485 
1486  case 2:
1488  // NOTE: blocking call...
1489  SC_NOTICE(" -> read log");
1490  Processor::information().getScheduler().sleep(nullptr);
1491  return 0;
1492 
1493  case 3:
1495  SC_NOTICE(" -> read up to last 4k");
1496  return 0;
1497 
1498  case 4:
1500  SC_NOTICE(" -> read and clear last 4k");
1501  return 0;
1502 
1503  case 5:
1504  SC_NOTICE(" -> clear");
1505  return 0;
1506 
1507  case 6:
1508  SC_NOTICE(" -> disable write to console");
1509  return 0;
1510 
1511  case 7:
1512  SC_NOTICE(" -> enable write to console");
1513  return 0;
1514 
1515  case 8:
1516  SC_NOTICE(" -> set console write level");
1517  return 0;
1518 
1519  default:
1520  SC_NOTICE(" -> unknown!");
1521  SYSCALL_ERROR(InvalidArgument);
1522  return -1;
1523  }
1524 }
1525 
1526 int posix_syslog(const char *msg, int prio)
1527 {
1529  reinterpret_cast<uintptr_t>(msg), PATH_MAX,
1530  PosixSubsystem::SafeRead))
1531  {
1532  SC_NOTICE("klog -> invalid address");
1533  SYSCALL_ERROR(InvalidArgument);
1534  return -1;
1535  }
1536 
1537  uint64_t id =
1538  Processor::information().getCurrentThread()->getParent()->getId();
1539  if (id <= 1)
1540  {
1541  if (prio <= LOG_CRIT)
1542  FATAL("[" << Dec << id << Hex << "]\tklog: " << msg);
1543  }
1544 
1545  if (prio <= LOG_ERR)
1546  ERROR("[" << Dec << id << Hex << "]\tklog: " << msg);
1547  else if (prio == LOG_WARNING)
1548  WARNING("[" << Dec << id << Hex << "]\tklog: " << msg);
1549  else if (prio == LOG_NOTICE || prio == LOG_INFO)
1550  NOTICE("[" << Dec << id << Hex << "]\tklog: " << msg);
1551 #ifdef DEBUGGER
1552  else
1553  NOTICE("[" << Dec << id << Hex << "]\tklog: " << msg);
1554 #endif
1555  return 0;
1556 }
1557 
1558 extern void system_reset();
1559 
1560 EXPORTED_PUBLIC int pedigree_reboot()
1561 {
1562  // Are we superuser?
1563  User *pUser =
1564  Processor::information().getCurrentThread()->getParent()->getUser();
1565  if (pUser->getId())
1566  {
1567  SYSCALL_ERROR(NotEnoughPermissions);
1568  return -1;
1569  }
1570 
1571  WARNING("System shutting down...");
1572  for (int i = Scheduler::instance().getNumProcesses() - 1; i >= 0; i--)
1573  {
1574  Process *proc = Scheduler::instance().getProcess(i);
1575  Subsystem *subsys = proc->getSubsystem();
1576 
1577  if (proc == Processor::information().getCurrentThread()->getParent())
1578  continue;
1579 
1580  if (subsys)
1581  {
1582  // If there's a subsystem, kill it that way.
1584  subsys->kill(Subsystem::Terminated, proc->getThread(0));
1585  }
1586  else
1587  {
1588  // If no subsystem, outright kill the process without sending a
1589  // signal
1591 
1596  // proc->kill();
1597  }
1598  }
1599 
1600  // Wait for remaining processes to terminate.
1601  while (true)
1602  {
1603  Processor::setInterrupts(false);
1604  if (Scheduler::instance().getNumProcesses() <= 1)
1605  {
1606  break;
1607  }
1608  bool allZombie = true;
1609  for (size_t i = 0; i < Scheduler::instance().getNumProcesses(); i++)
1610  {
1611  if (Scheduler::instance().getProcess(i) ==
1612  Processor::information().getCurrentThread()->getParent())
1613  {
1614  continue;
1615  }
1616  if (Scheduler::instance()
1617  .getProcess(i)
1618  ->getThread(0)
1619  ->getStatus() != Thread::Zombie)
1620  {
1621  allZombie = false;
1622  }
1623  }
1624 
1625  if (allZombie)
1626  {
1627  break;
1628  }
1630 
1632  }
1633 
1634  // All dead, reap them all.
1635  while (Scheduler::instance().getNumProcesses() > 1)
1636  {
1637  if (Scheduler::instance().getProcess(0) ==
1638  Processor::information().getCurrentThread()->getParent())
1639  {
1640  continue;
1641  }
1642  delete Scheduler::instance().getProcess(0);
1643  }
1644 
1645  // Reset the system
1646  system_reset();
1647  return 0;
1648 }
1649 
1650 int posix_uname(struct utsname *n)
1651 {
1652  if (!n)
1653  {
1654  SYSCALL_ERROR(InvalidArgument);
1655  return -1;
1656  }
1657 
1658  Process *pProcess =
1659  Processor::information().getCurrentThread()->getParent();
1660  PosixSubsystem *pSubsystem =
1661  reinterpret_cast<PosixSubsystem *>(pProcess->getSubsystem());
1662 
1663  StringCopy(n->sysname, "Pedigree");
1664 
1665  if (pSubsystem->getAbi() == PosixSubsystem::LinuxAbi)
1666  {
1667  // Lie a bit to Linux ABI callers.
1668  StringCopy(n->release, "2.6.32-generic");
1669  StringCopy(n->version, g_pBuildRevision);
1670  }
1671  else
1672  {
1673  StringCopy(n->release, g_pBuildRevision);
1674  StringCopy(n->version, "Foster");
1675  }
1676 
1677  StringCopy(n->machine, g_pBuildTarget);
1678 
1680  StringCopy(n->nodename, "pedigree");
1681  return 0;
1682 }
1683 
1684 int posix_prctl(
1685  int option, uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5)
1686 {
1687  NOTICE(
1688  "prctl(" << Hex << option << ", " << arg2 << ", " << arg3 << ", "
1689  << arg4 << ", " << arg5 << ")");
1690  return 0;
1691 }
1692 
1693 int posix_arch_prctl(int code, unsigned long addr)
1694 {
1695  unsigned long *pAddr = reinterpret_cast<unsigned long *>(addr);
1696 
1697  switch (code)
1698  {
1699  case ARCH_SET_FS:
1700  Processor::information().getCurrentThread()->setTlsBase(addr);
1701  break;
1702 
1703  case ARCH_GET_FS:
1704  *pAddr = Processor::information().getCurrentThread()->getTlsBase();
1705  break;
1706 
1707  default:
1708  SYSCALL_ERROR(InvalidArgument);
1709  return -1;
1710  }
1711 
1712  return 0;
1713 }
1714 
1715 int posix_pause()
1716 {
1717  SC_NOTICE("pause");
1718 
1719  Processor::information().getScheduler().sleep();
1720 
1721  SYSCALL_ERROR(Interrupted);
1722  return -1;
1723 }
1724 
1725 int posix_setgroups(size_t size, const gid_t *list)
1726 {
1727  SC_NOTICE("setgroups(" << size << ", " << list << ")");
1728 
1730 
1732  reinterpret_cast<uintptr_t>(list), size * sizeof(gid_t),
1733  PosixSubsystem::SafeRead))
1734  {
1735  SC_NOTICE(" -> invalid address");
1736  SYSCALL_ERROR(BadAddress);
1737  return -1;
1738  }
1739 
1740  PosixProcess *pProcess = getPosixProcess();
1741  if (!pProcess)
1742  {
1744  return -1;
1745  }
1746 
1747  Vector<int64_t> newGroups;
1748  for (size_t i = 0; i < size; ++i)
1749  {
1750  newGroups.pushBack(list[i]);
1751  }
1752 
1753  pProcess->setSupplementalGroupIds(newGroups);
1754 
1755  return 0;
1756 }
1757 
1758 int posix_getgroups(size_t size, gid_t *list)
1759 {
1760  SC_NOTICE("getgroups(" << size << ", " << list << ")");
1761 
1762  if (size && !PosixSubsystem::checkAddress(
1763  reinterpret_cast<uintptr_t>(list), size * sizeof(gid_t),
1764  PosixSubsystem::SafeWrite))
1765  {
1766  SC_NOTICE("getgroups -> invalid address");
1767  SYSCALL_ERROR(BadAddress);
1768  return -1;
1769  }
1770 
1771  PosixProcess *pProcess = getPosixProcess();
1772  if (!pProcess)
1773  {
1775  return -1;
1776  }
1777 
1778  Vector<int64_t> groups;
1779  pProcess->getSupplementalGroupIds(groups);
1780 
1781  for (size_t i = 0; i < size && i < groups.count(); ++i)
1782  {
1783  list[i] = groups[i];
1784  }
1785 
1786  SC_NOTICE(" -> " << groups.count());
1787  return groups.count();
1788 }
1789 
1790 int posix_getrlimit(int resource, struct rlimit *rlim)
1791 {
1793  SC_NOTICE("getrlimit(" << Dec << resource << ")");
1794 
1795  switch (resource)
1796  {
1797  case RLIMIT_CPU:
1798  break;
1799  case RLIMIT_FSIZE:
1800  rlim->rlim_cur = rlim->rlim_max = RLIM_INFINITY;
1801  break;
1802  case RLIMIT_DATA:
1803  rlim->rlim_cur = rlim->rlim_max = RLIM_INFINITY;
1804  break;
1805  case RLIMIT_STACK:
1806  rlim->rlim_cur = rlim->rlim_max = RLIM_INFINITY;
1807  break;
1808  case RLIMIT_CORE:
1809  rlim->rlim_cur = 0;
1810  rlim->rlim_max = RLIM_INFINITY;
1811  break;
1812  case RLIMIT_RSS:
1813  rlim->rlim_cur = rlim->rlim_max = 1ULL << 48ULL;
1814  break;
1815  case RLIMIT_NPROC:
1816  rlim->rlim_cur = rlim->rlim_max = RLIM_INFINITY;
1817  break;
1818  case RLIMIT_NOFILE:
1819  rlim->rlim_cur = rlim->rlim_max = 16384;
1820  break;
1821  case RLIMIT_MEMLOCK:
1822  rlim->rlim_cur = rlim->rlim_max = 1ULL << 24ULL;
1823  break;
1824  case RLIMIT_AS:
1825  rlim->rlim_cur = rlim->rlim_max = 1ULL << 48ULL;
1826  break;
1827  case RLIMIT_LOCKS:
1828  rlim->rlim_cur = rlim->rlim_max = 1024;
1829  break;
1830  case RLIMIT_SIGPENDING:
1831  rlim->rlim_cur = rlim->rlim_max = 16;
1832  break;
1833  case RLIMIT_MSGQUEUE:
1834  rlim->rlim_cur = rlim->rlim_max = 0x100000;
1835  break;
1836  case RLIMIT_NICE:
1837  rlim->rlim_cur = rlim->rlim_max = 1;
1838  break;
1839  case RLIMIT_RTPRIO:
1840  SYSCALL_ERROR(InvalidArgument);
1841  SC_NOTICE(" -> RTPRIO not supported");
1842  return -1;
1843  default:
1844  SYSCALL_ERROR(InvalidArgument);
1845  SC_NOTICE(" -> unknown resource!");
1846  return -1;
1847  }
1848 
1849  SC_NOTICE(" -> cur = " << rlim->rlim_cur);
1850  SC_NOTICE(" -> max = " << rlim->rlim_max);
1851  return 0;
1852 }
1853 
1854 int posix_setrlimit(int resource, const struct rlimit *rlim)
1855 {
1857  SC_NOTICE("setrlimit(" << Dec << resource << ")");
1858 
1860 
1861  return 0;
1862 }
1863 
1864 int posix_getpriority(int which, int who)
1865 {
1867  SC_NOTICE("getpriority(" << which << ", " << Dec << who << ")");
1868  SYSCALL_ERROR(NoError); // clear errno if not already
1869  return 0;
1870 }
1871 
1872 int posix_setpriority(int which, int who, int prio)
1873 {
1875  SC_NOTICE(
1876  "setpriority(" << which << ", " << Dec << who << ", " << prio << ")");
1877  return 0;
1878 }
1879 
1880 int posix_setreuid(uid_t ruid, uid_t euid)
1881 {
1882  SC_NOTICE("setreuid(" << ruid << ", " << euid << ")");
1883  return posix_setresuid(ruid, euid, -1);
1884 }
1885 
1886 int posix_setregid(gid_t rgid, gid_t egid)
1887 {
1888  SC_NOTICE("setregid(" << rgid << ", " << egid << ")");
1889  return posix_setresgid(rgid, egid, -1);
1890 }
1891 
1892 int posix_setresuid(uid_t ruid, uid_t euid, uid_t suid)
1893 {
1894  SC_NOTICE("setresuid(" << ruid << ", " << euid << ", " << suid << ")");
1895 
1896  PosixProcess *pProcess = getPosixProcess();
1897  if (!pProcess)
1898  {
1900  return -1;
1901  }
1902 
1903  if (ruid != static_cast<uid_t>(-1))
1904  {
1905  pProcess->setUserId(ruid);
1906  }
1907  if (euid != static_cast<uid_t>(-1))
1908  {
1909  pProcess->setEffectiveUserId(euid);
1910  }
1911  if (suid != static_cast<uid_t>(-1))
1912  {
1913  pProcess->setSavedUserId(suid);
1914  }
1915 
1916  return 0;
1917 }
1918 
1919 int posix_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
1920 {
1921  SC_NOTICE("setresgid(" << rgid << ", " << egid << ", " << sgid << ")");
1922 
1923  PosixProcess *pProcess = getPosixProcess();
1924  if (!pProcess)
1925  {
1927  return -1;
1928  }
1929 
1930  if (rgid != static_cast<gid_t>(-1))
1931  {
1932  pProcess->setGroupId(rgid);
1933  }
1934  if (egid != static_cast<gid_t>(-1))
1935  {
1936  pProcess->setEffectiveGroupId(egid);
1937  }
1938  if (sgid != static_cast<gid_t>(-1))
1939  {
1940  pProcess->setSavedGroupId(sgid);
1941  }
1942 
1943  return 0;
1944 }
1945 
1946 int posix_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid)
1947 {
1948  SC_NOTICE("getresuid");
1949 
1950  Process *pStockProcess =
1951  Processor::information().getCurrentThread()->getParent();
1952 
1953  if (ruid)
1954  {
1955  *ruid = pStockProcess->getUserId();
1956  SC_NOTICE(" -> uid=" << *ruid);
1957  }
1958 
1959  if (euid)
1960  {
1961  *euid = pStockProcess->getEffectiveUserId();
1962  SC_NOTICE(" -> euid=" << *euid);
1963  }
1964 
1965  if (suid)
1966  {
1967  PosixProcess *pProcess = getPosixProcess();
1968  if (pProcess)
1969  {
1970  *suid = pProcess->getSavedUserId();
1971  SC_NOTICE(" -> suid=" << *suid);
1972  }
1973  }
1974 
1975  return 0;
1976 }
1977 
1978 int posix_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid)
1979 {
1980  SC_NOTICE("getresgid");
1981 
1982  Process *pStockProcess =
1983  Processor::information().getCurrentThread()->getParent();
1984 
1985  if (rgid)
1986  {
1987  *rgid = pStockProcess->getGroupId();
1988  SC_NOTICE(" -> gid=" << *rgid);
1989  }
1990 
1991  if (egid)
1992  {
1993  *egid = pStockProcess->getEffectiveGroupId();
1994  SC_NOTICE(" -> egid=" << *egid);
1995  }
1996 
1997  if (sgid)
1998  {
1999  PosixProcess *pProcess = getPosixProcess();
2000  if (pProcess)
2001  {
2002  *sgid = pProcess->getSavedGroupId();
2003  SC_NOTICE(" -> sgid=" << *sgid);
2004  }
2005  }
2006 
2007  return 0;
2008 }
2009 
2010 int posix_get_robust_list(
2011  int pid, struct robust_list_head **head_ptr, size_t *len_ptr)
2012 {
2013  SC_NOTICE("get_robust_list");
2014 
2016  reinterpret_cast<uintptr_t>(head_ptr), sizeof(void *),
2017  PosixSubsystem::SafeWrite) &&
2019  reinterpret_cast<uintptr_t>(len_ptr), sizeof(size_t),
2020  PosixSubsystem::SafeWrite)))
2021  {
2022  SC_NOTICE(" -> invalid address");
2023  SYSCALL_ERROR(InvalidArgument);
2024  return -1;
2025  }
2026 
2027  PosixProcess *pProcess = static_cast<PosixProcess *>(
2028  Processor::information().getCurrentThread()->getParent());
2029 
2030  auto data = pProcess->getRobustList();
2031  *head_ptr = reinterpret_cast<struct robust_list_head *>(data.head);
2032  *len_ptr = data.head_len;
2033 
2034  return 0;
2035 }
2036 
2037 int posix_set_robust_list(struct robust_list_head *head, size_t len)
2038 {
2039  SC_NOTICE("set_robust_list");
2040 
2041  PosixProcess *pProcess = static_cast<PosixProcess *>(
2042  Processor::information().getCurrentThread()->getParent());
2043 
2045  data.head = head;
2046  data.head_len = len;
2047 
2048  pProcess->setRobustList(data);
2049 
2050  return 0;
2051 }
2052 
2053 int posix_ioperm(unsigned long from, unsigned long num, int turn_on)
2054 {
2055  SC_NOTICE("ioperm(" << from << ", " << num << ", " << turn_on << ")");
2056 
2059  return 0;
2060 }
2061 
2062 int posix_iopl(int level)
2063 {
2064  SC_NOTICE("iopl(" << level << ")");
2065  return 0;
2066 }
2067 
2068 #undef SC_NOTICE
2069 #define SC_NOTICE(x)
2070 
2071 int posix_getitimer(int which, struct itimerval *curr_value)
2072 {
2073  SC_NOTICE("posix_getitimer(" << which << ", " << curr_value << ")");
2074 
2075  PosixProcess *pProcess = static_cast<PosixProcess *>(
2076  Processor::information().getCurrentThread()->getParent());
2077 
2079 
2080  Time::Timestamp interval = 0;
2081  Time::Timestamp value = 0;
2082 
2083  IntervalTimer *itimer = &pProcess->getRealIntervalTimer();
2084  if (which == ITIMER_REAL)
2085  {
2086  SC_NOTICE(" -> ITIMER_REAL");
2087  }
2088  else if (which == ITIMER_VIRTUAL)
2089  {
2090  SC_NOTICE(" -> ITIMER_VIRTUAL");
2091 
2092  itimer = &pProcess->getVirtualIntervalTimer();
2093  }
2094  else if (which == ITIMER_PROF)
2095  {
2096  SC_NOTICE(" -> ITIMER_VIRTUAL");
2097 
2098  itimer = &pProcess->getProfileIntervalTimer();
2099  }
2100  else
2101  {
2102  SYSCALL_ERROR(InvalidArgument);
2103  return -1;
2104  }
2105 
2106  itimer->getIntervalAndValue(interval, value);
2107 
2108  curr_value->it_interval.tv_sec = interval / Time::Multiplier::Second;
2109  curr_value->it_interval.tv_usec =
2110  (interval % Time::Multiplier::Second) / Time::Multiplier::Microsecond;
2111 
2112  curr_value->it_value.tv_sec = value / Time::Multiplier::Second;
2113  curr_value->it_value.tv_usec =
2114  (value % Time::Multiplier::Second) / Time::Multiplier::Microsecond;
2115 
2116  SC_NOTICE(
2117  " -> period = " << Dec << curr_value->it_interval.tv_sec << "s "
2118  << curr_value->it_interval.tv_usec << "us");
2119  SC_NOTICE(
2120  " -> value = " << Dec << curr_value->it_value.tv_sec << "s "
2121  << curr_value->it_value.tv_usec << "us");
2122 
2123  return 0;
2124 }
2125 
2126 int posix_setitimer(
2127  int which, const struct itimerval *new_value, struct itimerval *old_value)
2128 {
2129  SC_NOTICE(
2130  "posix_setitimer(" << which << ", " << new_value << ", " << old_value
2131  << ")");
2132  SC_NOTICE(
2133  " -> period = " << Dec << new_value->it_interval.tv_sec << "s "
2134  << new_value->it_interval.tv_usec << "us");
2135  SC_NOTICE(
2136  " -> value = " << Dec << new_value->it_value.tv_sec << "s "
2137  << new_value->it_value.tv_usec << "us");
2138 
2140 
2141  PosixProcess *pProcess = static_cast<PosixProcess *>(
2142  Processor::information().getCurrentThread()->getParent());
2143 
2144  Time::Timestamp interval = 0;
2145  Time::Timestamp value = 0;
2146 
2147  Time::Timestamp prevInterval = 0;
2148  Time::Timestamp prevValue = 0;
2149 
2150  interval = (new_value->it_interval.tv_sec * Time::Multiplier::Second) +
2151  (new_value->it_interval.tv_usec * Time::Multiplier::Microsecond);
2152  value = (new_value->it_value.tv_sec * Time::Multiplier::Second) +
2153  (new_value->it_value.tv_usec * Time::Multiplier::Microsecond);
2154 
2155  IntervalTimer *itimer = &pProcess->getRealIntervalTimer();
2156  if (which == ITIMER_REAL)
2157  {
2158  SC_NOTICE(" -> ITIMER_REAL");
2159  }
2160  else if (which == ITIMER_VIRTUAL)
2161  {
2162  SC_NOTICE(" -> ITIMER_VIRTUAL");
2163 
2164  itimer = &pProcess->getVirtualIntervalTimer();
2165  }
2166  else if (which == ITIMER_PROF)
2167  {
2168  SC_NOTICE(" -> ITIMER_VIRTUAL");
2169 
2170  itimer = &pProcess->getProfileIntervalTimer();
2171  }
2172  else
2173  {
2174  SYSCALL_ERROR(InvalidArgument);
2175  return -1;
2176  }
2177 
2178  itimer->setIntervalAndValue(interval, value, &prevInterval, &prevValue);
2179 
2180  if (old_value)
2181  {
2182  old_value->it_interval.tv_sec = prevInterval / Time::Multiplier::Second;
2183  old_value->it_interval.tv_usec =
2184  (prevInterval % Time::Multiplier::Second) /
2185  Time::Multiplier::Microsecond;
2186 
2187  old_value->it_value.tv_sec = prevValue / Time::Multiplier::Second;
2188  old_value->it_value.tv_usec = (prevValue % Time::Multiplier::Second) /
2189  Time::Multiplier::Microsecond;
2190  }
2191 
2192  return 0;
2193 }
2194 
2195 int posix_capget(void *hdrp, void *datap)
2196 {
2197  PosixProcess *pProcess = getPosixProcess();
2198  if (!pProcess)
2199  {
2201  return -1;
2202  }
2203 
2204  struct cap_header *header = reinterpret_cast<struct cap_header *>(hdrp);
2205  struct cap_data *data = reinterpret_cast<struct cap_data *>(datap);
2206 
2207  if (!header)
2208  {
2209  SYSCALL_ERROR(BadAddress);
2210  return -1;
2211  }
2212 
2213  if (header->version != _LINUX_CAPABILITY_VERSION_1)
2214  {
2215  // require capability version 1
2216  header->version = _LINUX_CAPABILITY_VERSION_1;
2217  SYSCALL_ERROR(InvalidArgument);
2218  return -1;
2219  }
2220 
2221  if (data)
2222  {
2224  data->effective = 0xFFFFFFFF;
2225  data->permitted = 0xFFFFFFFF;
2226  data->inheritable = 0xFFFFFFFF;
2227  }
2228 
2229  return 0;
2230 }
2231 
2232 int posix_capset(void *hdrp, const void *datap)
2233 {
2234  struct cap_header *header = reinterpret_cast<struct cap_header *>(hdrp);
2235  const struct cap_data *data =
2236  reinterpret_cast<const struct cap_data *>(datap);
2237 
2238  if (!header)
2239  {
2240  SYSCALL_ERROR(BadAddress);
2241  return -1;
2242  }
2243 
2244  if (header->version != _LINUX_CAPABILITY_VERSION_1)
2245  {
2246  header->version = _LINUX_CAPABILITY_VERSION_1;
2247  SYSCALL_ERROR(InvalidArgument);
2248  return -1;
2249  }
2250 
2251  // no-op - capget says all capabilities are given, and the posix subsystem
2252  // doesn't use them yet
2253  return 0;
2254 }
void terminated(Process *pProcess)
void clear()
Definition: List.h:386
void pushBack(const T &value)
Definition: Vector.h:270
void pushBack(const T &value)
Definition: List.h:232
String getUsername()
Definition: User.h:71
Abi getAbi() const
size_t count() const
Definition: Vector.h:264
size_t getId()
Definition: User.h:66
bool acquire(size_t n=1, size_t timeoutSecs=0, size_t timeoutUsecs=0)
Definition: Semaphore.h:62
size_t getId()
Definition: Process.h:108
int getExitStatus()
Definition: Process.h:131
A vector / dynamic array.
virtual bool invoke(const char *name, Vector< String > &argv, Vector< String > &env)
virtual Timer * getTimer()=0
bool copyDescriptors(PosixSubsystem *pSubsystem)
void setTlsBase(uintptr_t base)
Definition: Thread.cc:818
virtual int64_t getUserId() const
Definition: Process.cc:320
User * getUser(size_t id)
Definition: UserManager.cc:88
Definition: String.h:49
static ProcessorInformation & information()
Definition: Processor.cc:45
static void switchAddressSpace(VirtualAddressSpace &AddressSpace)
Definition: User.h:32
virtual Time::Timestamp getUnixTimestamp()
Definition: Timer.cc:23
String getShell()
Definition: User.h:91
PosixProcess * Leader
Definition: PosixProcess.h:44
String getHome()
Definition: User.h:86
Group * getGroup(size_t id)
Definition: UserManager.cc:105
void setCtty(File *f)
Definition: Process.h:172
String getFullName()
Definition: User.h:76
void removeProcess(Process *pProcess)
Definition: Scheduler.cc:119
static bool checkAddress(uintptr_t addr, size_t extent, size_t flags)
#define WARNING(text)
Definition: Log.h:78
void exit(int code) NORETURN
Memory-mapped file interface.
Process * getParent()
Definition: Process.h:150
Time::Timestamp getUserTime() const
Definition: Process.h:358
Group * getDefaultGroup()
Definition: User.h:81
#define NOTICE(text)
Definition: Log.h:74
void reap()
Definition: Process.h:137
Definition: Log.h:136
size_t getNumProcesses()
Definition: Scheduler.cc:140
static MemoryMapManager & instance()
Iterator begin()
Definition: List.h:123
static Scheduler & instance()
Definition: Scheduler.h:48
Process * getProcess(size_t n)
Definition: Scheduler.cc:149
virtual uint64_t getNanosecond()=0
static void setInterrupts(bool bEnable)
void setStatus(Status s)
Definition: Thread.cc:364
Definition: Log.h:140
int processGroupId
Definition: PosixProcess.h:58
Thread * getThread(size_t n)
Definition: Process.cc:225
Status getStatus() const
Definition: Thread.h:192
List< PosixProcess * > Members
Definition: PosixProcess.h:67
Definition: Thread.h:54
void setIntervalAndValue(Time::Timestamp interval, Time::Timestamp value, Time::Timestamp *prevInterval=nullptr, Time::Timestamp *prevValue=nullptr)
Set both interval and value atomically.
void clone(Process *pTarget)
VirtualAddressSpace * getAddressSpace()
Definition: Process.h:120
virtual ProcessType getType()
Definition: Process.h:259
#define ERROR(text)
Definition: Log.h:82
static UserManager & instance()
Definition: UserManager.h:34
bool login(String password)
Definition: User.cc:72
String getName()
Definition: Group.h:56
void yield()
Definition: Scheduler.cc:135
bool detach()
Definition: Thread.cc:885
Definition: Log.h:138
size_t getId()
Definition: Thread.h:210
(b) below.
Definition: Thread.h:245
size_t getId()
Definition: Group.h:51
#define FATAL(text)
Definition: Log.h:89
virtual bool kill(KillReason killReason, Thread *pThread=0)=0
Iterator end()
Definition: List.h:135
PosixProcess * Leader
Definition: PosixProcess.h:61
virtual void setProcess(Process *p)
Definition: Subsystem.h:137
Definition: Group.h:32
size_t count() const
Definition: List.h:227