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

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

示例脚本:

#!/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

输出:

-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

答案1

您运行的是哪个系统?在 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 模式位;
    • 目标文件没有同时启用其设置组 ID 和组可执行模式位;和
    • 调用者有权读取和写入目标文件(通过文件的权限掩码或因为它具有合适的功能)。

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

该文件中的默认值为 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

设置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

答案2

通常,每个文件都有一个目录项(也有例外,但无需赘述)。

目录项本质上是一个姓名+号码一对;文件的名称和一个称为 i 编号的数字。这是一个名为“我的列表,其中包含每个文件的所有真实详细信息,结构称为i节点

i 节点包含文件所有者的详细信息等。它实际上由文件所有者“拥有”。其中的字段之一是使用次数,通常设置为 1。

当建立硬链接时,它只是另一个名称+数字对,与第一个没有区别。此时使用计数增加 1;当硬链接(或原始目录项,因为它们具有相同的地位)被删除时,使用计数减1。当它变为零时,文件消失。您可以从中看到,创建硬链接意味着您必须能够在不是其所有者时更改 i 节点。

这是 UNIX 上多年来的一个问题,也是符号链接(或符号链接,有时称为软链接) 被引入。这是一个姓名+姓名对,基本上只是为原始文件提供一个别名。 i 节点中没有任何变化;这只是一个重定向。缺点是可以删除原始文件而符号链接不会消失,并且最终指向一个不存在的文件。

答案3

man 2 link:“...两个名称都引用同一个文件(因此具有相同的权限和所有权)”

即使您有权读取/复制/移动文件,也不能使用不同的权限创建指向同一文件的两个链接或者所有权,作为模式,uid吉德存储在您要从两个不同目录创建链接的索引节点中,而不是存储在目录条目本身中。

考虑:

$ touch file_a
$ touch file_b
$ ln file_a file_A
$ ls -iln
total 0
1310731 -rw-rw-r-- 2 1000 1000 0 Jul 11 08:45 file_a
1310731 -rw-rw-r-- 2 1000 1000 0 Jul 11 08:45 file_A
1320710 -rw-rw-r-- 1 1000 1000 0 Jul 11 08:45 file_b

======= ===================================== ======
^       ^                                     ^
|       |                                     \-- names, stored in directory
|       \-- file metadata, stored in inode
\-- inode number, stored in directory and pointing to inode

在这个例子中,file_a并且file_A有相同的inode号,所以一定将所有相同的属性存储在 inode 中。

相关内容