diff options
author | Sergey Bugaev <bugaevc@serenityos.org> | 2020-11-21 22:55:20 +0300 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-11-23 18:37:40 +0100 |
commit | 098070b767db2d74595829040d8ef55bb3b81bd5 (patch) | |
tree | 3b1bbda527a0afa75401f850adcef403a17f250b /Kernel/FileSystem | |
parent | 23dc3ff0c2dc703f2d0649177cf30ab2b8b1e57d (diff) | |
download | serenity-098070b767db2d74595829040d8ef55bb3b81bd5.zip |
Kernel: Add unveil('b')
This is a new "browse" permission that lets you open (and subsequently list
contents of) directories underneath the path, but not regular files or any other
types of files.
Diffstat (limited to 'Kernel/FileSystem')
-rw-r--r-- | Kernel/FileSystem/ProcFS.cpp | 2 | ||||
-rw-r--r-- | Kernel/FileSystem/VirtualFileSystem.cpp | 24 |
2 files changed, 21 insertions, 5 deletions
diff --git a/Kernel/FileSystem/ProcFS.cpp b/Kernel/FileSystem/ProcFS.cpp index 6e5996a23b..4acf07ab14 100644 --- a/Kernel/FileSystem/ProcFS.cpp +++ b/Kernel/FileSystem/ProcFS.cpp @@ -644,6 +644,8 @@ static Optional<KBuffer> procfs$pid_unveil(InodeIdentifier identifier) permissions_builder.append('x'); if (unveiled_path.permissions & UnveiledPath::Access::CreateOrRemove) permissions_builder.append('c'); + if (unveiled_path.permissions & UnveiledPath::Access::Browse) + permissions_builder.append('b'); obj.add("permissions", permissions_builder.to_string()); } array.finish(); diff --git a/Kernel/FileSystem/VirtualFileSystem.cpp b/Kernel/FileSystem/VirtualFileSystem.cpp index 54092e91c2..2ba9589dcd 100644 --- a/Kernel/FileSystem/VirtualFileSystem.cpp +++ b/Kernel/FileSystem/VirtualFileSystem.cpp @@ -825,7 +825,13 @@ const UnveiledPath* 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) && path.length() > unveiled_path.path.length() && path[unveiled_path.path.length()] == '/') + 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; @@ -863,10 +869,18 @@ KResult VFS::validate_path_against_process_veil(StringView path, int options) return KSuccess; } if (options & O_RDONLY) { - if (!(unveiled_path->permissions & UnveiledPath::Access::Read)) { - dbg() << "Rejecting path '" << path << "' since it hasn't been unveiled with 'r' permission."; - dump_backtrace(); - return KResult(-EACCES); + if (options & O_DIRECTORY) { + if (!(unveiled_path->permissions & (UnveiledPath::Access::Read | UnveiledPath::Access::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)) { + dbg() << "Rejecting path '" << path << "' since it hasn't been unveiled with 'r' permission."; + dump_backtrace(); + return KResult(-EACCES); + } } } if (options & O_WRONLY) { |