Почему я не могу создать `hardlink` для файла из каталога« 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

Примечание . Я вручную изменил имена файлов и каталогов, чтобы сделать ситуацию более понятной, поэтому в показаниях команд может быть одна или две опечатки.

jdk1.0
источник
2
Неважно, куда вы монтируете папку. Они физически на разных разделах. Каждый раздел имеет свою собственную таблицу файлов, а жесткая ссылка - это просто запись в этой таблице.
user996142
2
Дело в том, что файлы НЕ находятся на физически разных разделах. Это та же файловая система из того же раздела. Разница заключается в креплении.
Ройма
Привязка - просто выдумка. Это не меняет структуры данных на дисках. Файловые системы все еще физически разделены.
Боб
Но когда я создаю жесткую ссылку, /dataя могу получить доступ к inode из каталога подключения bind, так что либо подключение bind должно быть в том же разделе /data, либо жесткая ссылка работает на всех устройствах, что должно быть недопустимым, но все равно работает. Что мне не хватает?
jdk1.0

Ответы:

6

В коде разочаровывает отсутствие комментариев . Как будто никто никогда не думал, что это полезно, так как временные привязки были реализованы в 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 (write возвращает EROFS) на / jail / usr / log, где это потенциально доступно для записи.

sourcejedi
источник
-1

Причина, по которой вы не можете выполнять связывание между устройствами, заключается в том, что вы вводите неоднозначности. Запись каталога для файла содержит (в простых системах) номер i-узла для соответствующего файла. Жесткая ссылка (просто еще одна запись в каталоге) также должна содержать тот же номер i-узла. Это нормально, но номера i-узлов уникальны только в пределах одной файловой системы (обычно это плотный набор, начинающийся с 1).

Ваша привязка не решает эту проблему. Да, он создает своего рода «фикцию» структуры, но он не выполняет повторную нумерацию всех i-узлов в одной файловой системе, чтобы убедиться, что все они уникальны в обеих файловых системах! Это было бы глупо.

Это ограничение всегда было в системах UNIX. Символическая ссылка была изобретена частично, чтобы решить эту проблему. Я знаю, что они функционально не совсем одинаковы, но обычно они в порядке.

Попробуйте символическую ссылку? ( ln -s)

Боб Айгер
источник
Там не будет никакого имени для любого нумерации inode здесь. Существует только одна базовая файловая система с двумя представлениями.
Жиль "ТАК - перестань быть злым"
Одна из причин, по которой я не хотел символическую ссылку, заключалась в том, что мои пути были длинными, и делать это было грязно ls -l. Сначала глупо рассуждать, но потом это привело к кроличьей норе, и мне стало любопытно, что происходит с жесткими связями ...
jdk1.0
@ Жиль, это то, что я говорил. Я хотел сказать, что перенумерация узлов была бы нелепой. Не знаю, почему правильный ответ был опущен.
Боб
Вы получаете правильное заключение, но ваше объяснение неверно во многих местах, поэтому ваш ответ в целом вводит в заблуждение. Посмотрите ответ Sourcejedi для хорошего объяснения.
Жиль "ТАК - перестань быть злым"
Я не вижу никаких ошибок, хотя признаю, что мог бы быть более ясным.
Боб