2#include "execveat-syscalls.h"
3#include "pedigree/kernel/process/Process.h"
4#include "pedigree/kernel/process/Thread.h"
5#include "pedigree/kernel/processor/Processor.h"
6#include "pedigree/kernel/processor/ProcessorInformation.h"
7#include "pedigree/kernel/syscallError.h"
8#include "pedigree/kernel/utilities/StaticString.h"
13#include "PosixSubsystem.h"
14#include "file-syscalls.h"
19 ExecResult(
int result)
21 error(result < 0 ?
Processor::information().getCurrentThread()->getErrno() : 0) {}
26bool snapshotArguments(
const char** pointers,
Vector<String>& output,
size_t& remaining) {
27 uintptr_t cursor =
reinterpret_cast<uintptr_t
>(pointers);
29 const char* argument =
nullptr;
32 SYSCALL_ERROR(BadAddress);
37 if (remaining <=
sizeof(uintptr_t)) {
38 SYSCALL_ERROR(TooBig);
41 remaining -=
sizeof(uintptr_t);
44 if (result != PosixSubsystem::UserStringSuccess) {
45 syscallError(result == PosixSubsystem::UserStringBadAddress ? Error::BadAddress
49 remaining -= value.length() + 1;
50 output.pushBack(value);
51 if (cursor > ~uintptr_t(0) -
sizeof(uintptr_t)) {
52 SYSCALL_ERROR(BadAddress);
55 cursor +=
sizeof(uintptr_t);
60ExecResult execveat(
int dirfd,
const char* path,
const char** argv,
const char** env,
int flags,
61 SyscallState& state) {
62 if (flags & ~(AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW)) {
63 SYSCALL_ERROR(InvalidArgument);
68 if (copied != PosixSubsystem::UserStringSuccess) {
69 syscallError(copied == PosixSubsystem::UserStringBadAddress ? Error::BadAddress
70 : Error::NameTooLong);
73 if (!pathname.length() && !(flags & AT_EMPTY_PATH)) {
74 SYSCALL_ERROR(DoesNotExist);
79 auto* subsystem =
static_cast<PosixSubsystem*
>(process->getSubsystem());
83 File* target =
nullptr;
84 const bool absolute = pathname.length() && pathname[0] ==
'/';
85 const bool descriptorPath = !absolute && dirfd != AT_FDCWD;
87 if (dirfd < 0 || !subsystem->acquireFileDescriptor(dirfd, descriptor)) {
88 SYSCALL_ERROR(BadFileDescriptor);
91 target = descriptor->getFile();
92 start = descriptor->openingPath();
93 if (!target || (pathname.length() && (!target->
isDirectory() || !start))) {
94 syscallError(pathname.length() ? Error::NotADirectory : Error::PermissionDenied);
97 targetLease.retain(start);
98 }
else if (!pathname.length()) {
99 auto context = process->acquireFilesystemContext();
101 if (!context || !context->snapshot(snapshot) || !snapshot.cwd) {
102 SYSCALL_ERROR(DoesNotExist);
105 targetLease.retain(snapshot.cwd);
106 target = targetLease.get();
109 if (pathname.length()) {
111 normalisePath(resolvedPath, pathname.cstr());
112 target = subsystem->findFileRetained(resolvedPath, targetLease, start);
116 SYSCALL_ERROR(DoesNotExist);
119 if ((flags & AT_SYMLINK_NOFOLLOW) && target->
isSymlink()) {
120 SYSCALL_ERROR(LoopExists);
124 target = subsystem->followFile(targetLease);
129 SYSCALL_ERROR(PermissionDenied);
133 String originalName(pathname);
134 if (descriptorPath) {
136 prefix.append(
static_cast<size_t>(dirfd));
137 originalName.assign(prefix, prefix.length());
138 if (pathname.length()) {
140 originalName += pathname;
146 size_t remaining = PosixSubsystem::MaximumExecArgumentBytes - 2 *
sizeof(uintptr_t);
147 if (originalName.length() >= remaining) {
148 SYSCALL_ERROR(TooBig);
151 remaining -= originalName.length() + 1;
152 if (!snapshotArguments(argv, arguments, remaining) ||
153 !snapshotArguments(env, environment, remaining))
156 const bool inaccessible = descriptorPath && (descriptor->
fdflags & FD_CLOEXEC);
157 const auto opening = targetLease.path()
162 ? subsystem->invoke(opening, originalName, arguments, environment, state, inaccessible)
163 : subsystem->invoke(target, originalName, arguments, environment, state, inaccessible);
164 return invoked ? 0 : -1;
169int posix_execveat(
int dirfd,
const char* path,
const char** argv,
const char** env,
int flags,
170 SyscallState& state) {
171 const ExecResult result = execveat(dirfd, path, argv, env, flags, state);
172 syscallError(result.error);
Memory-mapped file interface.
int fdflags
File descriptor flags (fcntl)
virtual bool isSocket() const
virtual bool isDirectory()
virtual bool isFifo() const
virtual bool isPipe() const
static MemoryMapManager & instance()
static bool copyFromUser(void *destination, const void *source, size_t count, size_t elementSize=1)
static UserStringResult copyUserString(const char *userString, String ©, size_t maxLength)
static ProcessorInformation & information()
A vector / dynamic array.