8#include "pedigree/kernel/Atomic.h"
9#include "pedigree/kernel/Log.h"
10#include "pedigree/kernel/errors.h"
11#include "pedigree/kernel/process/Process.h"
12#include "pedigree/kernel/process/Thread.h"
13#include "pedigree/kernel/processor/Processor.h"
17#include "modules/subsys/posix/FileDescriptor.h"
18#include "modules/subsys/posix/PosixSubsystem.h"
19#include "modules/subsys/posix/file-syscalls.h"
20#include "modules/system/vfs/File.h"
24constexpr size_t LockDescriptor = 96;
25constexpr size_t FcntlCommandCount = 3;
26constexpr size_t ValidFlockOperationCount = 6;
27constexpr size_t InvalidFlockOperationCount = 5;
29const int FcntlCommands[FcntlCommandCount] = {F_GETLK, F_SETLK, F_SETLKW};
30const int ValidFlockOperations[ValidFlockOperationCount] = {
31 LOCK_SH, LOCK_EX, LOCK_UN, LOCK_SH | LOCK_NB, LOCK_EX | LOCK_NB, LOCK_UN | LOCK_NB};
32const int InvalidFlockOperations[InvalidFlockOperationCount] = {
33 0, LOCK_NB, LOCK_SH | LOCK_EX, LOCK_SH | LOCK_UN, LOCK_EX | 0x1000};
35struct AdvisoryLockContext {
37 : fcntlResults{-2, -2, -2},
39 badFcntlResults{-2, -2, -2},
40 badFcntlErrors{0, 0, 0},
41 validFlockResults{-2, -2, -2, -2, -2, -2},
42 validFlockErrors{0, 0, 0, 0, 0, 0},
43 invalidFlockResults{-2, -2, -2, -2, -2},
44 invalidFlockErrors{0, 0, 0, 0, 0},
47 invalidBadFlockResult(-2),
48 invalidBadFlockError(0),
49 queryUnchanged(false),
52 int fcntlResults[FcntlCommandCount];
53 int fcntlErrors[FcntlCommandCount];
54 int badFcntlResults[FcntlCommandCount];
55 int badFcntlErrors[FcntlCommandCount];
56 int validFlockResults[ValidFlockOperationCount];
57 int validFlockErrors[ValidFlockOperationCount];
58 int invalidFlockResults[InvalidFlockOperationCount];
59 int invalidFlockErrors[InvalidFlockOperationCount];
62 int invalidBadFlockResult;
63 int invalidBadFlockError;
74int advisoryLockWorker(
void* parameter) {
75 AdvisoryLockContext* context =
reinterpret_cast<AdvisoryLockContext*
>(parameter);
78 struct flock request = {};
79 request.l_type = F_WRLCK;
80 request.l_whence = SEEK_SET;
84 const struct flock original = request;
86 for (
size_t i = 0; i < FcntlCommandCount; ++i) {
88 context->fcntlResults[i] =
89 posix_fcntl(
static_cast<int>(LockDescriptor), FcntlCommands[i], &request);
90 context->fcntlErrors[i] = thread->
getErrno();
93 context->badFcntlResults[i] = posix_fcntl(-1, FcntlCommands[i], &request);
94 context->badFcntlErrors[i] = thread->
getErrno();
96 context->queryUnchanged = request.l_type == original.l_type &&
97 request.l_whence == original.l_whence &&
98 request.l_start == original.l_start &&
99 request.l_len == original.l_len && request.l_pid == original.l_pid;
101 for (
size_t i = 0; i < ValidFlockOperationCount; ++i) {
103 context->validFlockResults[i] =
104 posix_flock(
static_cast<int>(LockDescriptor), ValidFlockOperations[i]);
105 context->validFlockErrors[i] = thread->
getErrno();
107 for (
size_t i = 0; i < InvalidFlockOperationCount; ++i) {
109 context->invalidFlockResults[i] =
110 posix_flock(
static_cast<int>(LockDescriptor), InvalidFlockOperations[i]);
111 context->invalidFlockErrors[i] = thread->
getErrno();
115 context->badFlockResult = posix_flock(-1, LOCK_EX | LOCK_NB);
116 context->badFlockError = thread->
getErrno();
118 context->invalidBadFlockResult = posix_flock(-1, 0);
119 context->invalidBadFlockError = thread->
getErrno();
121 context->returned += 1;
125bool advisoryLocksFailClosed(
Process* kernelProcess) {
128 process->setSubsystem(subsystem);
130 File file(
String(
"advisory-lock-probe"), 0, 0, 0, 1,
nullptr, 0,
nullptr);
134 AdvisoryLockContext context;
135 Thread*
worker =
new Thread(process, advisoryLockWorker, &context,
nullptr,
false,
true,
true);
136 worker->setName(
"hosted advisory lock fail-closed");
137 const bool started =
worker->start();
138 const bool joined = started &&
worker->joinForCompletion();
143 bool passed = started && joined && context.returned == 1 && context.queryUnchanged;
144 for (
size_t i = 0; i < FcntlCommandCount; ++i) {
145 passed = context.fcntlResults[i] == -1 && context.fcntlErrors[i] == Error::Unimplemented &&
146 context.badFcntlResults[i] == -1 &&
147 context.badFcntlErrors[i] == Error::BadFileDescriptor && passed;
149 for (
size_t i = 0; i < ValidFlockOperationCount; ++i) {
150 passed = context.validFlockResults[i] == -1 &&
151 context.validFlockErrors[i] == Error::Unimplemented && passed;
153 for (
size_t i = 0; i < InvalidFlockOperationCount; ++i) {
154 passed = context.invalidFlockResults[i] == -1 &&
155 context.invalidFlockErrors[i] == Error::InvalidArgument && passed;
157 passed = context.badFlockResult == -1 && context.badFlockError == Error::BadFileDescriptor &&
158 context.invalidBadFlockResult == -1 &&
159 context.invalidBadFlockError == Error::InvalidArgument && passed;
161 passed = closeDescriptor(subsystem, LockDescriptor) && passed;
166 "HOSTED-SYSCALL-TEST: FAIL advisory-lock-fail-closed: "
167 "unsupported locks succeeded or validation returned the wrong error");
171 NOTICE(
"HOSTED-SYSCALL-TEST: PASS advisory-lock-fail-closed");
176bool runHostedAdvisoryLockRegressions(
Process* process) {
177 return advisoryLocksFailClosed(process);
bool acquireFileDescriptor(size_t fd, DescriptorLease &descriptor)
bool closeFileDescriptor(size_t fd, const DescriptorLease &descriptor)
void addFileDescriptor(size_t fd, FileDescriptor *pFd)
static ProcessorInformation & information()
void setErrno(size_t err)