mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 18:07:34 +00:00
Kernel: Implement the same symlink protection as Linux
Path resolution will now refuse to follow symlinks in some cases where you don't own the symlink, or when it's in a sticky world-writable directory and the link has a different owner than the directory. The point of all this is to prevent classic TOCTOU bugs in /tmp etc. Fixes #4934
This commit is contained in:
parent
9681e3eca0
commit
8601108e21
1 changed files with 19 additions and 0 deletions
|
@ -952,6 +952,21 @@ KResultOr<NonnullRefPtr<Custody>> VFS::resolve_path(StringView path, Custody& ba
|
||||||
return custody;
|
return custody;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool safe_to_follow_symlink(const Inode& inode, const InodeMetadata& parent_metadata)
|
||||||
|
{
|
||||||
|
auto metadata = inode.metadata();
|
||||||
|
if (Process::current()->euid() == metadata.uid)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (!(parent_metadata.is_sticky() && parent_metadata.mode & S_IWOTH))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (metadata.uid == parent_metadata.uid)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
KResultOr<NonnullRefPtr<Custody>> VFS::resolve_path_without_veil(StringView path, Custody& base, RefPtr<Custody>* out_parent, int options, int symlink_recursion_level)
|
KResultOr<NonnullRefPtr<Custody>> VFS::resolve_path_without_veil(StringView path, Custody& base, RefPtr<Custody>* out_parent, int options, int symlink_recursion_level)
|
||||||
{
|
{
|
||||||
if (symlink_recursion_level >= symlink_recursion_limit)
|
if (symlink_recursion_level >= symlink_recursion_limit)
|
||||||
|
@ -1017,6 +1032,10 @@ KResultOr<NonnullRefPtr<Custody>> VFS::resolve_path_without_veil(StringView path
|
||||||
if (options & O_NOFOLLOW_NOERROR)
|
if (options & O_NOFOLLOW_NOERROR)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!safe_to_follow_symlink(*child_inode, parent_metadata))
|
||||||
|
return KResult(-EACCES);
|
||||||
|
|
||||||
auto symlink_target = child_inode->resolve_as_link(parent, out_parent, options, symlink_recursion_level + 1);
|
auto symlink_target = child_inode->resolve_as_link(parent, out_parent, options, symlink_recursion_level + 1);
|
||||||
if (symlink_target.is_error() || !have_more_parts)
|
if (symlink_target.is_error() || !have_more_parts)
|
||||||
return symlink_target;
|
return symlink_target;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue