1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 15:07: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

@ -68,19 +68,19 @@ int Process::sys$unveil(Userspace<const Syscall::SC_unveil_params*> user_params)
for (const char permission : permissions) {
switch (permission) {
case 'r':
new_permissions |= UnveiledPath::Access::Read;
new_permissions |= UnveilAccess::Read;
break;
case 'w':
new_permissions |= UnveiledPath::Access::Write;
new_permissions |= UnveilAccess::Write;
break;
case 'x':
new_permissions |= UnveiledPath::Access::Execute;
new_permissions |= UnveilAccess::Execute;
break;
case 'c':
new_permissions |= UnveiledPath::Access::CreateOrRemove;
new_permissions |= UnveilAccess::CreateOrRemove;
break;
case 'b':
new_permissions |= UnveiledPath::Access::Browse;
new_permissions |= UnveilAccess::Browse;
break;
default:
return -EINVAL;
@ -97,7 +97,7 @@ int Process::sys$unveil(Userspace<const Syscall::SC_unveil_params*> user_params)
auto custody_or_error = VFS::the().resolve_path_without_veil(path.value(), root_directory(), &parent_custody);
if (!custody_or_error.is_error()) {
new_unveiled_path = custody_or_error.value()->absolute_path();
} else if (custody_or_error.error() == -ENOENT && parent_custody && (new_permissions & UnveiledPath::Access::CreateOrRemove)) {
} else if (custody_or_error.error() == -ENOENT && parent_custody && (new_permissions & UnveilAccess::CreateOrRemove)) {
String basename = LexicalPath(path.value()).basename();
new_unveiled_path = String::formatted("{}/{}", parent_custody->absolute_path(), basename);
} else {
@ -105,16 +105,21 @@ int Process::sys$unveil(Userspace<const Syscall::SC_unveil_params*> user_params)
return custody_or_error.error();
}
for (auto& unveiled_path : m_unveiled_paths) {
if (unveiled_path.path == new_unveiled_path) {
if (new_permissions & ~unveiled_path.permissions)
return -EPERM;
unveiled_path.permissions = new_permissions;
return 0;
}
LexicalPath lexical_path(new_unveiled_path);
auto it = lexical_path.parts().begin();
auto& matching_node = m_unveiled_paths.traverse_until_last_accessible_node(it, lexical_path.parts().end());
if (it.is_end()) {
if (new_permissions & ~matching_node.permissions())
return -EPERM;
matching_node.set_metadata({ matching_node.path(), (UnveilAccess)new_permissions, true });
return 0;
}
m_unveiled_paths.append({ new_unveiled_path, new_permissions });
matching_node.insert(
it,
lexical_path.parts().end(),
{ new_unveiled_path, (UnveilAccess)new_permissions, true },
[](auto& parent, auto& it) -> Optional<UnveilMetadata> { return UnveilMetadata { String::formatted("{}/{}", parent.path(), *it), parent.permissions(), false }; });
ASSERT(m_veil_state != VeilState::Locked);
m_veil_state = VeilState::Dropped;
return 0;