2#include "clone3-syscalls.h"
3#include "pedigree/kernel/processor/Processor.h"
4#include "pedigree/kernel/processor/ProcessorInformation.h"
5#include "pedigree/kernel/processor/VirtualAddressSpace.h"
6#include "pedigree/kernel/syscallError.h"
11#include "PosixSubsystem.h"
12#include "linux-clone-abi.h"
13#include "system-syscalls.h"
16bool linuxUserRange(uint64_t address, uint64_t length) {
18 uint64_t limit = space.getKernelStart();
19 if (limit > 0x0000800000000000ULL)
20 limit = 0x0000800000000000ULL;
21 return address >= space.getUserStart() && address < limit && length <= limit - address;
25long posix_clone3(SyscallState& state,
const LinuxCloneArgs* userArgs,
size_t size) {
26 if (size > LinuxCloneAbi::MaximumSize) {
27 SYSCALL_ERROR(TooBig);
30 if (size < LinuxCloneAbi::Version0Size) {
31 SYSCALL_ERROR(InvalidArgument);
34 const uintptr_t userAddress =
reinterpret_cast<uintptr_t
>(userArgs);
35 if (!linuxUserRange(userAddress, size)) {
36 SYSCALL_ERROR(BadAddress);
43 uint8_t extension[64];
44 size_t count = size - offset;
45 if (count >
sizeof(extension))
46 count =
sizeof(extension);
48 reinterpret_cast<const void*
>(userAddress + offset), count)) {
49 SYSCALL_ERROR(BadAddress);
52 for (
size_t n = 0; n < count; ++n) {
54 SYSCALL_ERROR(TooBig);
62 const size_t knownSize = size <
sizeof(args) ? size : sizeof(args);
64 SYSCALL_ERROR(BadAddress);
68 constexpr uint64_t AllowedFlags =
69 CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_VFORK | CLONE_THREAD |
70 CLONE_SYSVSEM | CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID |
71 CLONE_CHILD_SETTID | CLONE_NEWUTS | CLONE_NEWNS | CLONE_NEWUSER | CLONE_NEWPID |
72 CLONE_NEWIPC | CLONE_NEWNET | LinuxCloneAbi::ClearSighand;
73 const bool clearSignalHandlers = args.flags & LinuxCloneAbi::ClearSighand;
74 const bool thread = args.flags & CLONE_THREAD;
75 if ((args.flags & ~AllowedFlags) || args.pidfd || args.set_tid || args.set_tid_size ||
76 args.cgroup || (clearSignalHandlers && (args.flags & (CLONE_SIGHAND | CLONE_THREAD))) ||
77 args.exit_signal !=
static_cast<uint64_t
>(thread ? 0 : SIGCHLD)) {
78 SYSCALL_ERROR(InvalidArgument);
82 const uint64_t maximumPointer = ~uintptr_t(0);
83 if (((args.flags & CLONE_PARENT_SETTID) && args.parent_tid > maximumPointer) ||
84 ((args.flags & (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)) &&
85 args.child_tid > maximumPointer)) {
86 SYSCALL_ERROR(BadAddress);
89 if ((args.flags & CLONE_SETTLS) && args.tls > maximumPointer) {
90 SYSCALL_ERROR(NotEnoughPermissions);
94 uintptr_t stackTop = 0;
95 if (args.stack || args.stack_size) {
97 if (!args.stack || !args.stack_size || !linuxUserRange(args.stack, args.stack_size)) {
98 SYSCALL_ERROR(InvalidArgument);
101 stackTop =
static_cast<uintptr_t
>(args.stack + args.stack_size);
104 const unsigned long flags =
105 static_cast<unsigned long>((args.flags & ~LinuxCloneAbi::ClearSighand) | args.exit_signal);
106 return posix_clone(state, flags,
reinterpret_cast<void*
>(stackTop),
107 reinterpret_cast<int*
>(
static_cast<uintptr_t
>(args.parent_tid)),
108 reinterpret_cast<int*
>(
static_cast<uintptr_t
>(args.child_tid)),
109 static_cast<unsigned long>(args.tls),
true, clearSignalHandlers);
static bool copyFromUser(void *destination, const void *source, size_t count, size_t elementSize=1)
static ProcessorInformation & information()