The Pedigree Project 0.1
memfd-syscalls.cc
1/* Copyright (c) 2026, Pedigree Developers. */
2#include "memfd-syscalls.h"
3#include "pedigree/kernel/process/Process.h"
4#include "pedigree/kernel/process/TerminationDeferral.h"
5#include "pedigree/kernel/process/Thread.h"
6#include "pedigree/kernel/processor/Processor.h"
7#include "pedigree/kernel/processor/ProcessorInformation.h"
8#include "pedigree/kernel/syscallError.h"
9
10#include <fcntl.h>
11
12#include "FileDescriptor.h"
13#include "PosixSubsystem.h"
14#include "memfd-file.h"
15#include "modules/system/vfs/VFS.h"
16
17int posix_memfd_create(const char* name, unsigned int flags) {
18 if (flags & ~(LinuxMemFd::CloseOnExec | LinuxMemFd::AllowSealing)) {
19 SYSCALL_ERROR(InvalidArgument);
20 return -1;
21 }
22 TerminationDeferral lifetime;
23 String label;
24 const auto copied =
25 PosixSubsystem::copyUserString(name, label, LinuxMemFd::MaximumNameLength + 1);
26 if (copied != PosixSubsystem::UserStringSuccess) {
27 syscallError(copied == PosixSubsystem::UserStringTooLong ? Error::InvalidArgument
28 : Error::BadAddress);
29 return -1;
30 }
31 Process* process = Processor::information().getCurrentThread()->getParent();
32 auto* subsystem = static_cast<PosixSubsystem*>(process->getSubsystem());
33 if (!subsystem) {
34 SYSCALL_ERROR(InvalidArgument);
35 return -1;
36 }
37 FilesystemCredentials credentials;
38 if (!Process::currentFilesystemCredentials(credentials)) {
39 SYSCALL_ERROR(PermissionDenied);
40 return -1;
41 }
42 String filename("memfd:");
43 filename += label;
44 auto* file =
45 new MemFdFile(filename, flags & LinuxMemFd::AllowSealing, credentials.uid, credentials.gid);
46 if (!file) {
47 SYSCALL_ERROR(OutOfMemory);
48 return -1;
49 }
50 // The OFD acquires its VFS lease only from an already tracked file.
52 auto* descriptor = new FileDescriptor(file, 0, 0xFFFFFFFF,
53 flags & LinuxMemFd::CloseOnExec ? FD_CLOEXEC : 0, O_RDWR);
54 if (!descriptor || !descriptor->acquireOpenFileDescription()) {
55 delete descriptor;
57 SYSCALL_ERROR(OutOfMemory);
58 return -1;
59 }
60 DescriptorLease published;
61 const size_t fd = subsystem->installFileDescriptor(descriptor, published);
63 return static_cast<int>(fd);
64}
65
66int posix_memfd_fcntl(const DescriptorLease& descriptor, int command, uintptr_t argument) {
67 TerminationDeferral lifetime;
68 if (!descriptor) {
69 SYSCALL_ERROR(BadFileDescriptor);
70 return -1;
71 }
72 auto description = descriptor->acquireOpenFileDescription();
73 if (!description) {
74 SYSCALL_ERROR(BadFileDescriptor);
75 return -1;
76 }
77 MemFdFile* file = MemFdFile::fromFile(description->getFile());
78 if (!file || (command != F_GET_SEALS && command != F_ADD_SEALS)) {
79 SYSCALL_ERROR(InvalidArgument);
80 return -1;
81 }
82 const int statusFlags = descriptor->getStatusFlags();
83 if (statusFlags & O_PATH) {
84 SYSCALL_ERROR(BadFileDescriptor);
85 return -1;
86 }
87 if (command == F_GET_SEALS)
88 return file->getSeals();
89 const int access = statusFlags & O_ACCMODE;
90 if (access != O_WRONLY && access != O_RDWR) {
91 SYSCALL_ERROR(NotEnoughPermissions);
92 return -1;
93 }
94 // Linux's memfd fcntl entry accepts an unsigned int seal mask.
95 return file->addSeals(static_cast<unsigned int>(argument));
96}
OpenFileDescriptionLease acquireOpenFileDescription() const
int getStatusFlags() const
Get current status flags.
static UserStringResult copyUserString(const char *userString, String &copy, size_t maxLength)
Process * getParent()
Definition Process.h:620
static ProcessorInformation & information()
bool untrackFile(File *pFile, bool destroy=true)
Definition VFS.cc:1670
static VFS & instance()
Definition VFS.cc:311
void trackFile(File *pFile)
Track a File object that exists. It is necessary to keep track of File objects, or at least those tha...
Definition VFS.cc:1625