2#include "pedigree/kernel/process/Scheduler.h"
3#include "pedigree/kernel/process/TerminationDeferral.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/Pointers.h"
9#include "pedigree/kernel/utilities/utility.h"
12#include "modules/system/vfs/VFS.h"
13#include "user-namespace.h"
16enum class Kind { Uid, Gid, Setgroups };
17const char* name(Kind kind) {
18 return kind == Kind::Uid ?
"uid_map" : kind == Kind::Gid ?
"gid_map" :
"setgroups";
21class UserMapFile final :
public File {
24 uint32_t uid, uint32_t gid)
25 :
File(
String(name(kind)), 0, 0, 0, filesystem.getNextInode(), &filesystem, 0, parent),
28 m_Viewer(posix_user_namespace(*
Processor::information().getCurrentThread())) {
34 SYSCALL_ERROR(NoSuchDevice);
42 bool allowResize(
size_t,
size_t)
override {
43 SYSCALL_ERROR(InvalidArgument);
46 uint64_t
readBytewise(uint64_t offset, uint64_t size, uintptr_t buffer,
bool)
override {
49 SYSCALL_ERROR(OutOfMemory);
53 if (m_Kind == Kind::Setgroups) {
54 const bool allow = !m_Space || m_Space->groupsAllowed();
55 length = allow ? 6 : 5;
56 MemoryCopy(bytes.get(), allow ?
"allow\n" :
"deny\n", length);
57 }
else if (!m_Space) {
58 static const char initial[] =
"0 0 4294967295\n";
59 length =
sizeof(initial) - 1;
60 MemoryCopy(bytes.get(), initial, length);
62 length = m_Space->readMap(m_Kind == Kind::Gid, m_Viewer, bytes.get(), 4096);
64 if (offset >= length) {
67 if (size > length - offset) {
68 size = length - offset;
70 MemoryCopy(
reinterpret_cast<void*
>(buffer), bytes.get() + offset, size);
73 uint64_t
writeBytewise(uint64_t offset, uint64_t size, uintptr_t buffer,
bool)
override {
75 SYSCALL_ERROR(NotEnoughPermissions);
78 if (offset || size >= 4096) {
79 SYSCALL_ERROR(InvalidArgument);
82 const char* bytes =
reinterpret_cast<const char*
>(buffer);
83 const int result = m_Kind == Kind::Setgroups
84 ? m_Space->writeSetgroups(bytes, size)
85 : m_Space->writeMap(m_Kind == Kind::Gid, bytes, size);
86 return result < 0 ? 0 : result;
94class UserMapNode final :
public File {
97 :
File(
String(name(kind)), 0, 0, 0, filesystem.getNextInode(), &filesystem, 0, parent),
99 m_ProcessId(process.getId()),
100 m_Identity(process.pidIdentity()) {
110 process->pidIdentity() != m_Identity ||
111 !process->acquireThreadByUserspaceId(task, process->
getUserspaceId(),
nullptr)) {
112 SYSCALL_ERROR(NoSuchProcess);
117 auto* file =
new UserMapFile(*
static_cast<ProcFs*
>(getFilesystem()), getParent(), m_Kind,
118 posix_user_namespace(*task.get()), process->getEffectiveUserId(),
119 process->getEffectiveGroupId());
122 SYSCALL_ERROR(OutOfMemory);
131 const size_t m_ProcessId;
137 constexpr Kind kinds[] = {Kind::Uid, Kind::Gid, Kind::Setgroups};
138 for (Kind kind : kinds) {
139 auto* file =
new UserMapNode(filesystem, &directory, process, kind);
143 directory.addEntry(file->getName(), file);
virtual uint64_t readBytewise(uint64_t location, uint64_t size, uintptr_t buffer, bool bCanBlock=true)
virtual bool isBytewise() const
void setGidOnly(size_t gid)
void setPermissionsOnly(uint32_t perms)
void setUidOnly(size_t uid)
virtual bool allowMapping(bool shared, bool writeRequested, bool &mayWrite)
virtual uint64_t writeBytewise(uint64_t location, uint64_t size, uintptr_t buffer, bool bCanBlock=true)
virtual File * openForDescriptor(RetainedFile &owner)
size_t getUserspaceId() const
static Scheduler & instance()