8#include "pedigree/kernel/Log.h"
9#include "pedigree/kernel/errors.h"
10#include "pedigree/kernel/process/Process.h"
11#include "pedigree/kernel/process/Thread.h"
12#include "pedigree/kernel/processor/PhysicalMemoryManager.h"
13#include "pedigree/kernel/processor/Processor.h"
14#include "pedigree/kernel/processor/VirtualAddressSpace.h"
15#include "pedigree/kernel/utilities/utility.h"
19#include "modules/subsys/posix/PosixSubsystem.h"
20#include "modules/subsys/posix/signal-syscalls.h"
23bool runHostedUsercopyRegressions(
Process* process) {
25 const size_t maximum = ~static_cast<size_t>(0);
26 const bool overflowRejected =
33 const size_t mappingLength = pageSize * 2;
34 uintptr_t address = 0;
35 if (!process->allocateUserRange(Process::UserRegion::Normal, mappingLength, address)) {
36 ERROR(
"HOSTED-SYSCALL-TEST: FAIL usercopy: could not reserve userspace range");
40 uintptr_t mappedAddress = address;
42 mappedAddress, mappingLength,
43 MemoryMappedObject::Read | MemoryMappedObject::Write | MemoryMappedObject::Exec);
44 if (!mapping || mappedAddress != address) {
46 process->freeUserRange(Process::UserRegion::Normal, address, mappingLength);
47 ERROR(
"HOSTED-SYSCALL-TEST: FAIL usercopy: could not map userspace range");
51 const uint8_t source[] = {0x31, 0x42, 0x53, 0x64, 0x75, 0x86};
52 uint8_t result[
sizeof(source)] = {};
53 void* userBuffer =
reinterpret_cast<void*
>(address + pageSize - 3);
57 !MemoryCompare(source, result,
sizeof(source));
58 const char sourceString[] = {
'u',
's',
'e',
'r', 0};
60 const bool stringSnapshot =
63 sizeof(sourceString)) == PosixSubsystem::UserStringSuccess &&
64 copiedString ==
String(
"user");
66 reinterpret_cast<uintptr_t
>(userBuffer), 1, PosixSubsystem::SafeExecute);
68 const bool kernelPointerRejected =
77 bool mappingCoverage = manager.allows(address, mappingLength,
78 MemoryMappedObject::Read | MemoryMappedObject::Write |
79 MemoryMappedObject::Exec) &&
80 manager.allows(
reinterpret_cast<uintptr_t
>(userBuffer),
sizeof(source),
81 MemoryMappedObject::Read | MemoryMappedObject::Write);
83 manager.setPermissions(address + pageSize, pageSize, MemoryMappedObject::Read) == 1 &&
84 manager.allows(address, mappingLength, MemoryMappedObject::Read) &&
85 !manager.allows(address, mappingLength, MemoryMappedObject::Write) &&
86 manager.allows(address, pageSize, MemoryMappedObject::Write) &&
87 manager.allows(address + pageSize, pageSize, MemoryMappedObject::Read) &&
88 !manager.allows(address + pageSize, pageSize, MemoryMappedObject::Write) && mappingCoverage;
90 manager.setPermissions(address + pageSize, pageSize, MemoryMappedObject::None) == 1 &&
91 !manager.allows(address + pageSize, pageSize, MemoryMappedObject::Read) &&
92 manager.allows(address + pageSize, pageSize, MemoryMappedObject::None) && mappingCoverage;
93 mappingCoverage = manager.setPermissions(address, mappingLength,
94 MemoryMappedObject::Read | MemoryMappedObject::Write |
95 MemoryMappedObject::Exec) == 2 &&
100 const uint64_t requestedMask = (
static_cast<uint64_t
>(1) << (SIGUSR1 - 1)) |
101 (
static_cast<uint64_t
>(1) << (SIGKILL - 1)) |
102 (
static_cast<uint64_t
>(1) << (SIGSTOP - 1));
103 void* userMask =
reinterpret_cast<void*
>(address + 64);
104 void* userOldMask =
reinterpret_cast<void*
>(address + 128);
105 uint64_t returnedMask = 0;
106 const bool signalMaskSnapshots =
108 posix_sigprocmask(SIG_SETMASK, userMask, userOldMask,
sizeof(uint64_t),
true) == 0 &&
110 returnedMask == originalMask &&
112 (requestedMask & ~((
static_cast<uint64_t
>(1) << (SIGKILL - 1)) |
113 (
static_cast<uint64_t
>(1) << (SIGSTOP - 1))));
117 stack_t disableStack = {};
118 disableStack.ss_flags = SS_DISABLE;
119 void* userStack =
reinterpret_cast<void*
>(address + 256);
120 void* userOldStack =
reinterpret_cast<void*
>(address + 384);
121 stack_t returnedStack = {};
122 const int expectedOldStackFlags =
123 originalStack.enabled ? (originalStack.inUse ? SS_ONSTACK : 0) : SS_DISABLE;
124 const bool alternateStackSnapshots =
126 posix_sigaltstack(
reinterpret_cast<const stack_t*
>(userStack),
127 reinterpret_cast<stack_t*
>(userOldStack)) == 0 &&
129 returnedStack.ss_flags == expectedOldStackFlags &&
130 (!originalStack.enabled ||
131 (returnedStack.ss_sp ==
reinterpret_cast<void*
>(originalStack.base) &&
132 returnedStack.ss_size == originalStack.size)) &&
133 !currentThread->getAlternateSignalStack().enabled;
134 currentThread->getAlternateSignalStack() = originalStack;
136 size_t checkedExtent = 99;
138 reinterpret_cast<uintptr_t
>(userBuffer), 2, 3, PosixSubsystem::SafeRead, &checkedExtent);
139 const bool overflowRangeRejected =
143 const size_t reducedPermissionObjects =
144 manager.setPermissions(address, mappingLength, MemoryMappedObject::Read);
145 const bool reducedPermissionsRejected =
149 PosixSubsystem::SafeExecute);
151 const uint64_t maskBeforeRejectedOutput = currentThread->
getSignalMask();
152 const bool signalMaskReadOnlyOutputRejected =
153 posix_sigprocmask(SIG_SETMASK, userMask, userOldMask,
sizeof(uint64_t),
true) == -1 &&
154 currentThread->
getErrno() == Error::BadAddress &&
158 const bool alternateStackReadOnlyOutputRejected =
159 posix_sigaltstack(
reinterpret_cast<const stack_t*
>(userStack),
160 reinterpret_cast<stack_t*
>(userOldStack)) == -1 &&
161 currentThread->
getErrno() == Error::BadAddress &&
162 currentThread->getAlternateSignalStack().base == originalStack.base &&
163 currentThread->getAlternateSignalStack().size == originalStack.size &&
164 currentThread->getAlternateSignalStack().enabled == originalStack.enabled &&
165 currentThread->getAlternateSignalStack().inUse == originalStack.inUse;
166 currentThread->getAlternateSignalStack() = originalStack;
169 const bool holeCoverage = !manager.allows(address, mappingLength, MemoryMappedObject::Read) &&
170 manager.allows(address, pageSize, MemoryMappedObject::Read) &&
171 !manager.allows(address + pageSize, pageSize, MemoryMappedObject::Read);
172 const bool incompleteRangeRejected =
175 const uint64_t maskBeforeRejectedCopy = currentThread->
getSignalMask();
176 const bool signalMaskIncompleteRangeRejected =
177 posix_sigprocmask(SIG_SETMASK, userBuffer,
nullptr,
sizeof(uint64_t),
true) == -1 &&
178 currentThread->
getErrno() == Error::BadAddress &&
181 const bool alternateStackIncompleteRangeRejected =
182 posix_sigaltstack(
reinterpret_cast<const stack_t*
>(userBuffer),
nullptr) == -1 &&
183 currentThread->
getErrno() == Error::BadAddress &&
184 currentThread->getAlternateSignalStack().base == originalStack.base &&
185 currentThread->getAlternateSignalStack().size == originalStack.size &&
186 currentThread->getAlternateSignalStack().enabled == originalStack.enabled &&
187 currentThread->getAlternateSignalStack().inUse == originalStack.inUse;
191 process->freeUserRange(Process::UserRegion::Normal, address, mappingLength);
194 overflowRejected && zeroExtentAccepted && roundTrip && stringSnapshot &&
195 executableUserAccepted && kernelPointerRejected && nullPointersRejected && mappingCoverage &&
196 signalMaskSnapshots && alternateStackSnapshots && arrayRangeAccepted && checkedExtent == 0 &&
197 overflowRangeRejected && reducedPermissionsRejected && signalMaskReadOnlyOutputRejected &&
198 alternateStackReadOnlyOutputRejected && holeCoverage && incompleteRangeRejected &&
199 signalMaskIncompleteRangeRejected && alternateStackIncompleteRangeRejected;
202 "HOSTED-SYSCALL-TEST: FAIL usercopy: overflow, range, permission, or copy contract "
207 NOTICE(
"HOSTED-SYSCALL-TEST: PASS usercopy");
Memory-mapped file interface.
MemoryMappedObject * mapAnon(uintptr_t &address, size_t length, MemoryMappedObject::Permissions perms)
size_t remove(uintptr_t base, size_t length)
static MemoryMapManager & instance()
static constexpr size_t getPageSize() PURE
static bool copyFromUser(void *destination, const void *source, size_t count, size_t elementSize=1)
static bool checkedUserBufferSize(size_t count, size_t elementSize, size_t &extent)
static UserStringResult copyUserString(const char *userString, String ©, size_t maxLength)
static bool checkUserBuffer(uintptr_t addr, size_t count, size_t elementSize, size_t flags, size_t *extent=nullptr)
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)
static ProcessorInformation & information()
void setErrno(size_t err)
void setSignalMask(uint64_t mask)