原始问题
我在一个文件系统上有一个文件:/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
笔记:我手动更改了文件和目录名称以使情况更清晰,因此命令读数中可能有一两个拼写错误。
答案1
令人失望的是缺乏评论代码。自从绑定挂载在 v2.4 中实现以来,就好像没有人认为它有用一样。当然,您需要做的就是替换.mnt->mnt_sb
它所说的地方.mnt
......
因为它为您提供了子树周围的安全边界。
PS:这已经讨论过很多次了,但为了避免搜索:考虑例如 mount --bind /tmp /tmp;现在你遇到了这样一种情况,即用户无法创建到其他地方没有根文件系统的链接,即使他们具有可写的 /tmp 。类似的技术适用于其他隔离需求 - 基本上,您可以将重命名/链接限制到给定的子树。 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 ,因为它可能是可写的。
答案2
您无法进行跨设备链接的原因是因为您引入了歧义。文件的目录条目包含(在简单系统中)相关文件的索引节点号。硬链接(只是另一个目录条目)也必须包含相同的 i 节点号。这很好,但 i 节点编号仅在单个文件系统中是唯一的(它们通常是从 1 开始的密集集)。
您的绑定安装无法解决该问题。是的,它构建了一种结构的“虚构”,但它没有做的是重新编号一个文件系统上的所有 i 节点,以确保它们在相关文件系统中都是唯一的!那太愚蠢了。
这个限制在 UNIX 系统上一直存在。符号链接的发明部分是为了解决这个问题。我知道它们在功能上并不完全相同,但通常都很好。
尝试符号链接吗? ( ln -s
)