diff options
author | AnotherTest <ali.mpfard@gmail.com> | 2020-12-26 13:54:34 +0330 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-12-26 11:54:54 +0100 |
commit | a9184fcb76d01304bdf3b206d52d315ce52e28ac (patch) | |
tree | b5534842a9cbc1654ad0cf9d9dab2ccc197d02e3 /Kernel/Syscalls/unveil.cpp | |
parent | cb3348191b1672afbfc99939cce4bc6f2b63eb4a (diff) | |
download | serenity-a9184fcb76d01304bdf3b206d52d315ce52e28ac.zip |
Kernel: Implement unveil() as a prefix-tree
Fixes #4530.
Diffstat (limited to 'Kernel/Syscalls/unveil.cpp')
-rw-r--r-- | Kernel/Syscalls/unveil.cpp | 33 |
1 files changed, 19 insertions, 14 deletions
diff --git a/Kernel/Syscalls/unveil.cpp b/Kernel/Syscalls/unveil.cpp index 57807cd8e9..74f75252c5 100644 --- a/Kernel/Syscalls/unveil.cpp +++ b/Kernel/Syscalls/unveil.cpp @@ -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; |