1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 04:27:45 +00:00

Kernel: Implement unveil() as a prefix-tree

Fixes #4530.
This commit is contained in:
AnotherTest 2020-12-26 13:54:34 +03:30 committed by Andreas Kling
parent cb3348191b
commit a9184fcb76
8 changed files with 192 additions and 58 deletions

View file

@ -634,18 +634,20 @@ static OwnPtr<KBuffer> procfs$pid_unveil(InodeIdentifier identifier)
KBufferBuilder builder;
JsonArraySerializer array { builder };
for (auto& unveiled_path : process->unveiled_paths()) {
if (!unveiled_path.was_explicitly_unveiled())
continue;
auto obj = array.add_object();
obj.add("path", unveiled_path.path);
obj.add("path", unveiled_path.path());
StringBuilder permissions_builder;
if (unveiled_path.permissions & UnveiledPath::Access::Read)
if (unveiled_path.permissions() & UnveilAccess::Read)
permissions_builder.append('r');
if (unveiled_path.permissions & UnveiledPath::Access::Write)
if (unveiled_path.permissions() & UnveilAccess::Write)
permissions_builder.append('w');
if (unveiled_path.permissions & UnveiledPath::Access::Execute)
if (unveiled_path.permissions() & UnveilAccess::Execute)
permissions_builder.append('x');
if (unveiled_path.permissions & UnveiledPath::Access::CreateOrRemove)
if (unveiled_path.permissions() & UnveilAccess::CreateOrRemove)
permissions_builder.append('c');
if (unveiled_path.permissions & UnveiledPath::Access::Browse)
if (unveiled_path.permissions() & UnveilAccess::Browse)
permissions_builder.append('b');
obj.add("permissions", permissions_builder.to_string());
}

View file

@ -820,21 +820,16 @@ Custody& VFS::root_custody()
return *m_root_custody;
}
const UnveiledPath* VFS::find_matching_unveiled_path(StringView path)
const UnveilNode* VFS::find_matching_unveiled_path(StringView path)
{
for (auto& unveiled_path : Process::current()->unveiled_paths()) {
if (path == unveiled_path.path)
return &unveiled_path;
if (!path.starts_with(unveiled_path.path))
continue;
// /foo/ and /foo/bar
if (unveiled_path.path.ends_with('/'))
return &unveiled_path;
// /foo and /foo/bar
if (path.length() > unveiled_path.path.length() && path[unveiled_path.path.length()] == '/')
return &unveiled_path;
}
return nullptr;
auto& unveil_root = Process::current()->unveiled_paths();
if (unveil_root.is_empty())
return nullptr;
LexicalPath lexical_path { path };
auto& path_parts = lexical_path.parts();
auto& last_matching_node = unveil_root.traverse_until_last_accessible_node(path_parts.begin(), path_parts.end());
return &last_matching_node;
}
KResult VFS::validate_path_against_process_veil(StringView path, int options)
@ -856,14 +851,14 @@ KResult VFS::validate_path_against_process_veil(StringView path, int options)
}
if (options & O_CREAT) {
if (!(unveiled_path->permissions & UnveiledPath::Access::CreateOrRemove)) {
if (!(unveiled_path->permissions() & UnveilAccess::CreateOrRemove)) {
dbg() << "Rejecting path '" << path << "' since it hasn't been unveiled with 'c' permission.";
dump_backtrace();
return KResult(-EACCES);
}
}
if (options & O_UNLINK_INTERNAL) {
if (!(unveiled_path->permissions & UnveiledPath::Access::CreateOrRemove)) {
if (!(unveiled_path->permissions() & UnveilAccess::CreateOrRemove)) {
dbg() << "Rejecting path '" << path << "' for unlink since it hasn't been unveiled with 'c' permission.";
dump_backtrace();
return KResult(-EACCES);
@ -872,13 +867,13 @@ KResult VFS::validate_path_against_process_veil(StringView path, int options)
}
if (options & O_RDONLY) {
if (options & O_DIRECTORY) {
if (!(unveiled_path->permissions & (UnveiledPath::Access::Read | UnveiledPath::Access::Browse))) {
if (!(unveiled_path->permissions() & (UnveilAccess::Read | UnveilAccess::Browse))) {
dbg() << "Rejecting path '" << path << "' since it hasn't been unveiled with 'r' or 'b' permissions.";
dump_backtrace();
return KResult(-EACCES);
}
} else {
if (!(unveiled_path->permissions & UnveiledPath::Access::Read)) {
if (!(unveiled_path->permissions() & UnveilAccess::Read)) {
dbg() << "Rejecting path '" << path << "' since it hasn't been unveiled with 'r' permission.";
dump_backtrace();
return KResult(-EACCES);
@ -886,14 +881,14 @@ KResult VFS::validate_path_against_process_veil(StringView path, int options)
}
}
if (options & O_WRONLY) {
if (!(unveiled_path->permissions & UnveiledPath::Access::Write)) {
if (!(unveiled_path->permissions() & UnveilAccess::Write)) {
dbg() << "Rejecting path '" << path << "' since it hasn't been unveiled with 'w' permission.";
dump_backtrace();
return KResult(-EACCES);
}
}
if (options & O_EXEC) {
if (!(unveiled_path->permissions & UnveiledPath::Access::Execute)) {
if (!(unveiled_path->permissions() & UnveilAccess::Execute)) {
dbg() << "Rejecting path '" << path << "' since it hasn't been unveiled with 'x' permission.";
dump_backtrace();
return KResult(-EACCES);

View file

@ -37,13 +37,13 @@
#include <Kernel/FileSystem/InodeIdentifier.h>
#include <Kernel/FileSystem/InodeMetadata.h>
#include <Kernel/KResult.h>
#include <Kernel/UnveilNode.h>
namespace Kernel {
class Custody;
class Device;
class FileDescription;
struct UnveiledPath;
struct UidAndGid {
uid_t uid;
@ -122,7 +122,7 @@ public:
private:
friend class FileDescription;
const UnveiledPath* find_matching_unveiled_path(StringView path);
const UnveilNode* find_matching_unveiled_path(StringView path);
KResult validate_path_against_process_veil(StringView path, int options);
bool is_vfs_root(InodeIdentifier) const;