Kaynağa Gözat

Kernel: Implement the same hard link protection as Linux

sys$link() will now fail to create hard links in some cases where you
don't own or have write access to the link target.

Work towards #4934
Andreas Kling 4 yıl önce
ebeveyn
işleme
9681e3eca0
1 değiştirilmiş dosya ile 20 ekleme ve 0 silme
  1. 20 0
      Kernel/FileSystem/VirtualFileSystem.cpp

+ 20 - 0
Kernel/FileSystem/VirtualFileSystem.cpp

@@ -634,6 +634,23 @@ KResult VFS::chown(StringView path, uid_t a_uid, gid_t a_gid, Custody& base)
     return chown(custody, a_uid, a_gid);
 }
 
+static bool hard_link_allowed(const Inode& inode)
+{
+    auto metadata = inode.metadata();
+
+    if (Process::current()->euid() == metadata.uid)
+        return true;
+
+    if (metadata.is_regular_file()
+        && !metadata.is_setuid()
+        && !(metadata.is_setgid() && metadata.mode & S_IXGRP)
+        && metadata.may_write(*Process::current())) {
+        return true;
+    }
+
+    return false;
+}
+
 KResult VFS::link(StringView old_path, StringView new_path, Custody& base)
 {
     auto old_custody_or_error = resolve_path(old_path, base);
@@ -664,6 +681,9 @@ KResult VFS::link(StringView old_path, StringView new_path, Custody& base)
     if (parent_custody->is_readonly())
         return KResult(-EROFS);
 
+    if (!hard_link_allowed(old_inode))
+        return KResult(-EPERM);
+
     return parent_inode.add_child(old_inode, LexicalPath(new_path).basename(), old_inode.mode());
 }