2#include "pedigree/kernel/process/FilesystemAccess.h"
3#include "pedigree/kernel/syscallError.h"
5#include "MountView-internal.h"
7#include "pedigree/kernel/Subsystem.h"
8#include "pedigree/kernel/process/Process.h"
9#include "pedigree/kernel/process/Thread.h"
10#include "pedigree/kernel/processor/Processor.h"
11#include "pedigree/kernel/processor/ProcessorInformation.h"
18 auto* process = thread ? thread->
getParent() :
nullptr;
19 auto* subsystem = process ? process->getSubsystem() :
nullptr;
20 return subsystem && subsystem->filesystemConstrained() ? subsystem :
nullptr;
23uint64_t creationAccess(
File* node) {
24 if (node->isDirectory()) {
25 return FilesystemAccess::MakeDir;
27 if (node->isSymlink()) {
28 return FilesystemAccess::MakeSym;
30 if (node->isSocket()) {
31 return FilesystemAccess::MakeSock;
33 if (node->isPipe() || node->isFifo()) {
34 return FilesystemAccess::MakeFifo;
36 if (node->isBlockDevice()) {
37 return FilesystemAccess::MakeBlock;
39 if (!node->supportsRegularFileOperations()) {
40 return FilesystemAccess::MakeChar;
42 return FilesystemAccess::MakeReg;
49 for (
size_t depth = 0; depth < 4096; ++depth) {
50 auto* item = path(current);
51 if (!item || !result.tryReserve(result.
count() + 1)) {
55 if (!item->node()->isDirectory() && item->lookupParent && item->lookupName.length()) {
61 if (found != Directory::LookupStatus::Found || selectedName.get() != item->node()) {
66 if (item->node() == item->attachment->root) {
71 auto* row = find(item->attachment->id);
73 parentAttachment = row->parent;
74 covered = row->covered;
77 if (!parentAttachment) {
80 if (!covered || !makePath(parentAttachment, covered->
get(), next)) {
83 }
else if (!parent(current, next)) {
86 if (view.samePath(current, next)) {
89 current = pedigree_std::move(next);
96 auto* owner = fromPath(path);
97 if (owner && owner !=
this) {
98 return owner->filesystemAccess(path, writer);
100#ifndef VFS_STANDALONE
101 auto* policy = currentPolicy();
107 return filesystemAccess(path, &admission);
109 if (!writer->protects(m_Vfs) || !m_State || !m_State->nodePath(path)) {
113 if (!m_State->path(path)) {
114 return policy->filesystemAccess(&path, 1);
117 if (!m_State->ancestors(path, ancestry)) {
120 return policy->filesystemAccess(ancestry.
begin(), ancestry.
count());
126bool VfsMountView::checkFilesystemAccess(
const FilesystemPathRef& path, uint64_t access,
128 auto* owner = fromPath(path);
129 if (owner && owner !=
this) {
130 return owner->checkFilesystemAccess(path, access, writer);
132 constexpr uint64_t mutations =
133 FilesystemAccess::WriteFile | FilesystemAccess::RemoveDir | FilesystemAccess::RemoveFile |
134 FilesystemAccess::MakeChar | FilesystemAccess::MakeDir | FilesystemAccess::MakeReg |
135 FilesystemAccess::MakeSock | FilesystemAccess::MakeFifo | FilesystemAccess::MakeBlock |
136 FilesystemAccess::MakeSym | FilesystemAccess::Truncate;
137 if ((access & mutations) && !writable(path)) {
140 if ((access & FilesystemAccess::Execute) && (mountFlags(path) & NoExec)) {
141 SYSCALL_ERROR(PermissionDenied);
144 if ((filesystemAccess(path, writer) & access) == access) {
147 SYSCALL_ERROR(PermissionDenied);
153 return checkFilesystemAccess(
154 parent, node->isDirectory() ? FilesystemAccess::RemoveDir : FilesystemAccess::RemoveFile,
160#ifndef VFS_STANDALONE
161 if (currentPolicy()) {
162 auto* source = m_State->path(target);
164 if (!source || !source->lookupParent || !source->lookupName.length() ||
167 Directory::LookupStatus::Found ||
168 selected.get() != source->node()) {
169 SYSCALL_ERROR(PermissionDenied);
175 return m_State->parent(target, oldParent) &&
176 authorizeRename(oldParent, target->node(), parent,
nullptr, writer,
false);
182 if ((removeSource && !authorizeRemove(oldParent, source, writer)) ||
183 !checkFilesystemAccess(newParent, creationAccess(source), &writer) ||
184 (replaced && !authorizeRemove(newParent, replaced, writer))) {
187#ifndef VFS_STANDALONE
188 auto* policy = currentPolicy();
189 if (!policy || samePath(oldParent, newParent)) {
193 if (!m_State->makePath(m_State->path(oldParent)->attachment, source, selected)) {
196 static_cast<VfsPath*
>(selected.
get())->lookupParent = oldParent;
198 if (!m_State->ancestors(selected, from) || !to.tryReserve(1)) {
199 SYSCALL_ERROR(OutOfMemory);
203 if (!m_State->ancestors(newParent, to)) {
204 SYSCALL_ERROR(OutOfMemory);
207 if (!checkFilesystemAccess(oldParent, FilesystemAccess::Refer, &writer) ||
208 !checkFilesystemAccess(newParent, FilesystemAccess::Refer, &writer) ||
210 SYSCALL_ERROR(CrossDeviceLink);
static Directory * fromFile(File *pF)
MUST_USE_RESULT LookupStatus lookupChild(const HashedStringView &s, ChildLease &child) const
static ProcessorInformation & information()
A vector / dynamic array.
void pushBack(const T &value)