为什么不能在同一文件系统上的“ mount --bind”目录中创建到文件的“硬链接”?


9

原始问题

我在一个文件系统上有一个文件: /data/src/file

我想将其硬链接到: /home/user/proj/src/file

/home在一个磁盘上,而/data在另一个磁盘上,所以我得到一个错误:

$ cd /home/user/proj/src
$ ln /data/src/file .
ln: failed to create hard link './file' => '/data/src/file': Invalid cross-device link

好的,因此我了解到我无法跨设备进行硬链接。说得通。

眼前的问题

因此,我想我会很喜欢并绑定安装一个src位于/data的文件系统上的文件夹:

$ mkdir -p /data/other/src
$ cd /home/user/proj
$ sudo mount --bind /data/other/src src/
$ cd src
$ # (now we're technically on `/data`'s file system, right?)
$ ln /data/src/file .
ln: failed to create hard link './file' => '/data/src/file': Invalid cross-device link

为什么这仍然行不通?

解决方法

我知道我的设置正确,因为只要我在“真实” /data目录中即可,而不是绑定目录,就可以进行硬链接。

$ cd /data/other/src
$ ln /data/src/file .
$ # OK
$ cd /home/user/proj/src
$ ls -lh
total 35M
-rw------- 2 user user 35M Jul 17 22:22 file

$

一些系统信息

$ uname -a
Linux <host> 4.10.0-24-generic #28-Ubuntu SMP Wed Jun 14 08:14:34 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

$ findmnt
.
.
.
├─/home                               /dev/sdb8   ext4       rw,relatime,data=ordered
│ └─/home/usr/proj/src             /dev/sda2[/other/src]
│                                                 ext4       rw,relatime,data=ordered
└─/data                               /dev/sda2   ext4       rw,relatime,data=ordered

$ mountpoint -d /data
8:2

$ mountpoint -d /home/usr/proj/src/
8:2

注意:我手动更改了文件和目录名称,以使情况更加清楚,因此命令读数中可能会出现一两个错字。


2
挂载文件夹的位置无关紧要。它们物理上位于不同的分区上。每个分区都有自己的文件表,硬链接仅记录在该表中。
user996142

2
这里的要点是文件不在物理上不同的分区上。它是来自同一分区的相同文件系统。区别在于绑定安装。
roaima

绑定安装仅仅是一种虚构。它不会更改磁盘上的数据结构。文件系统在物理上仍然是分开的。
Bob Eager

但是,当我在其上创建硬链接时,/data我可以从绑定安装目录访问索引节点,因此绑定安装必须与处于同一分区/data,或者该硬链接跨设备工作,这应该是非法的,但仍然可以正常工作。我想念什么?
jdk1.0

Answers:


6

令人遗憾的是,代码中缺少注释。似乎没有人认为它有用,因为绑定绑定安装是在v2.4中实现的。当然,您需要做的就是.mnt->mnt_sb在显示的地方替换.mnt...

因为它为您提供了围绕子树的安全边界。

PS:已经讨论了很多次了,但是为了避免搜索:考虑例如mount --bind / tmp / tmp; 现在,您遇到了这样一种情况,即即使用户具有可写的/ tmp信息,他们也无法创建到其他没有root fs的链接。类似的技术也可以满足其他隔离需求-基本上,您可以将重命名/链接限制在给定的子树中。IOW,这是故意的功能。请注意,无论一年后主树中的内容如何重新排列,您都可以将一束树绑定到chroot中并获得可预测的限制。

- 阿尔维罗

后面有一个具体的例子

只要我们使mount -r --bind正常工作(我用来将必要的共享库的副本放置在chroot监狱中,同时允许页面缓存共享),此功能就会破坏安全性。

mkdir /usr/lib/libs.jail
for i in $LIST_OF_LIBRARIES; do
ln /usr/lib/$i /usr/lib/libs.jail/$i
done
mount -r /usr/lib/libs.jail /jail/lib
chown prisoner /usr/log/jail
mount /usr/log/jail /jail/usr/log
chrootuid /jail prisoner /bin/untrusted &

尽管保护应该足够,但是我宁愿避免将囚犯链接/jail/lib/libfoo.so(写入返回EROFS)链接到/ jail / usr / log,该链接可能是可写的。


-1

无法进行跨设备链接的原因是因为引入了歧义。该文件的目录条目包含(在简单系统中)有关文件的索引节点号。硬链接(只是另一个目录条目)也必须包含相同的索引节点号。很好,但是索引节点号仅在单个文件系统中唯一(它们通常是从1开始的密集集)。

您的绑定安装不能解决该问题。是的,它构造了结构的一种“虚构”,但是它没有做的是对一个文件系统上的所有i节点重新编号,以确保它们在有关的两个文件系统中都是唯一的!那太傻了。

在UNIX系统上,这种限制一直存在。为了解决这个问题,部分发明了符号链接。我知道它们在功能上并不完全相同,但通常都可以。

尝试符号链接?(ln -s


这里没有任何索引节点编号的名称。仅有一个基础文件系统,具有两个视图。
吉尔斯(Gilles)'所以

我不希望使用符号链接的原因之一是,因为我的路径很长,并且做一个ls -l。起初,Kinda愚蠢的推理,但随后导致了一个兔子洞,我对硬链接发生了什么感到好奇...
jdk1.0

@吉尔斯,那是我在说的。我要说的是,inode重编号是荒谬的。不知道为什么拒绝正确答案。
Bob Eager

您得出正确的结论,但是您的解释在很多地方都是错误的,因此您的回答总体上很容易让人产生误解。请参阅sourcejedi的答案以获取良好的解释。
吉尔斯(Gillles)“所以-别再邪恶了”

尽管我承认我可以更清楚一些,但我看不到任何错误。
Bob Eager
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.