为什么我不能硬链接到我不拥有的文件,即使我可以移动它?

PSk*_*cik 3 linux permissions hard-link files move

示例脚本:

#!/bin/sh -e 
sudo useradd -m user_a
sudo useradd -m user_b -g user_a
sudo chmod g+w /home/user_a

set +e
sudo su user_a <<EOF
cd
umask 027
>> file_a 
>> file_b
>> file_c
ls -l file_*
EOF

sudo su user_b <<EOF
cd
umask 000
rm -f file_*
ls -l ~user_a/
set -x
mv ~user_a/file_a .
cp ~user_a/file_b .
ln ~user_a/file_c .
set +x
ls -l ~/
EOF
sudo userdel  -r user_b
sudo userdel  -r user_a
Run Code Online (Sandbox Code Playgroud)

输出:

-rw-r----- 1 user_a user_a 0 Jul 11 12:26 file_a
-rw-r----- 1 user_a user_a 0 Jul 11 12:26 file_b
-rw-r----- 1 user_a user_a 0 Jul 11 12:26 file_c
total 0
-rw-r----- 1 user_a user_a 0 Jul 11 12:26 file_a
-rw-r----- 1 user_a user_a 0 Jul 11 12:26 file_b
-rw-r----- 1 user_a user_a 0 Jul 11 12:26 file_c
+ mv /home/user_a/file_a .
+ cp /home/user_a/file_b .
+ ln /home/user_a/file_c .
ln: failed to create hard link ‘./file_c’ => ‘/home/user_a/file_c’: Operation not permitted
+ set +x
total 0
-rw-r----- 1 user_a user_a 0 Jul 11 12:26 file_a
-rw-r----- 1 user_b user_a 0 Jul 11 12:26 file_b
userdel: user_b mail spool (/var/mail/user_b) not found
userdel: user_a mail spool (/var/mail/user_a) not found
Run Code Online (Sandbox Code Playgroud)

ilk*_*chu 6

你运行的是哪个系统?在 Linux 上,这种行为是可配置的,通过/proc/sys/fs/protected_hardlinks(或sysctl fs.protected_hardlinks)。

该行为描述于proc(5)

/proc/sys/fs/protected_hardlinks(Linux 3.6 起)
当该文件中的值为0 时,对硬链接的创建没有限制(即这是Linux 3.6 之前的历史行为)。当此文件中的值为 1 时,仅当以下条件之一为真时,才能创建到目标文件的硬链接:

  • 调用进程具有 CAP_FOWNER 能力...
  • 创建链接的进程的文件系统 UID 与目标文件的所有者 (UID) 匹配...
  • 以下所有条件都为真:
    • 目标是一个普通文件;
    • 目标文件没有启用它的设置用户 ID 模式位;
    • 目标文件没有同时启用它的 set-group-ID 和 group-executable 模式位;和
    • 调用者有权读取和写入目标文件(通过文件的权限掩码或因为它具有合适的功能)。

这样做的理由应该很清楚:

此文件中的默认值为 0。将值设置为 1 可防止由基于硬链接的检查时间、使用时间竞争引起的长期安全问题,最常见于世界可写目录中,例如作为 /tmp.

在 Debian 系统protected_hardlinks和类似的protected_symlinks默认系统上,因此在没有对文件的写访问权限的情况下创建链接不起作用:

$ ls -ld . ./foo
drwxrwxr-x 2 root itvirta 4096 Jul 11 16:43 ./
-rw-r--r-- 1 root root       4 Jul 11 16:43 ./foo
$ mv foo bar
$ ln bar bar2
ln: failed to create hard link 'bar2' => 'bar': Operation not permitted
Run Code Online (Sandbox Code Playgroud)

设置protected_hardlinks为零可解除限制:

# echo 0 >  /proc/sys/fs/protected_hardlinks 
$ ln bar bar2
$ ls -l bar bar2
-rw-r--r-- 2 root root 4 Jul 11 16:43 bar
-rw-r--r-- 2 root root 4 Jul 11 16:43 bar2
Run Code Online (Sandbox Code Playgroud)