Mengapa saya tidak bisa membuat `hardlink` ke file dari direktori" mount --bind "pada sistem file yang sama?

9

Masalah Asli

Saya punya file di satu sistem file: /data/src/file

dan saya ingin menghubungkannya dengan keras: /home/user/proj/src/file

tetapi /homepada satu disk, dan /datapada yang lain jadi saya mendapatkan kesalahan:

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

Oke, jadi saya belajar bahwa saya tidak bisa menautkan keras lintas perangkat. Masuk akal.

Masalah yang dihadapi

Jadi saya pikir saya akan suka dan mengikat mount srcfolder yang ada /datadi sistem file:

$ 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

Mengapa ini masih tidak berhasil?

Penanganan masalah

Saya tahu saya memiliki pengaturan ini dengan benar karena saya dapat membuat tautan keras selama saya berada di /datadirektori "asli" daripada yang terikat.

$ 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

$

Beberapa Info Sistem

$ 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

Catatan : Saya secara manual mengubah nama file dan direktori untuk membuat situasi lebih jelas, sehingga mungkin ada salah ketik atau dua dalam pembacaan perintah.

jdk1.0
sumber
2
Tidak masalah di mana Anda memasang folder. Mereka secara fisik di partisi yang berbeda. Setiap partisi memiliki tabel file sendiri dan hardlink hanya merekam di tabel ini.
user996142
2
Intinya di sini adalah bahwa file BUKAN pada partisi yang berbeda secara fisik. Ini adalah sistem file yang sama dari partisi yang sama. Perbedaannya adalah bind mount.
roaima
Bind mount hanyalah sebuah fiksi. Itu tidak mengubah struktur data pada disk. Sistem file masih terpisah secara fisik.
Bob Eager
Tetapi ketika saya membuat tautan keras di, /datasaya dapat mengakses inode dari direktori bind mount, jadi bind mount harus berada di partisi yang sama dengan /data, atau tautan keras bekerja di seluruh perangkat, yang seharusnya ilegal, tetapi tetap berfungsi. Apa yang saya lewatkan?
jdk1.0

Jawaban:

6

Ada kekurangan komentar yang mengecewakan dalam kode . Seolah-olah tidak ada yang pernah berpikir itu berguna, karena waktu bind mount diimplementasikan di v2.4. Tentunya yang perlu Anda lakukan adalah mengganti di .mnt->mnt_sbmana dikatakan .mnt...

Karena itu memberi Anda batas keamanan di sekitar subtree.

PS: yang telah dibahas beberapa kali, tetapi untuk menghindari pencarian: pertimbangkan misalnya mount --bind / tmp / tmp; sekarang Anda punya situasi ketika pengguna tidak dapat membuat tautan ke tempat lain tanpa root fs, meskipun mereka memiliki / tmp dapat ditulisi oleh mereka. Teknik serupa berfungsi untuk kebutuhan isolasi lainnya - pada dasarnya, Anda dapat membatasi penggantian nama / tautan ke subtree yang diberikan. TKI, ini fitur yang disengaja. Perhatikan bahwa Anda dapat mengikat seikat pohon menjadi chroot dan mendapatkan batasan yang dapat diprediksi terlepas dari bagaimana hal-hal tersebut dapat diatur ulang setahun kemudian di pohon utama, dll.

- Al Viro

Ada contoh nyata lebih jauh ke bawah

Setiap kali kita membuat mount -r --bind berfungsi dengan baik (yang saya gunakan untuk menempatkan salinan pustaka bersama yang diperlukan di dalam chroot jails sementara memungkinkan berbagi cache halaman), fitur ini akan merusak keamanan.

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 &

Meskipun perlindungan seharusnya cukup, tetapi saya lebih suka menghindari tautan narapidana /jail/lib/libfoo.so (tulis pengembalian EROFS) ke / jail / usr / log di tempat yang berpotensi dapat ditulisi.

sourcejedi
sumber
-1

Alasan Anda tidak dapat melakukan penautan lintas perangkat adalah karena Anda memperkenalkan ambiguitas. Entri direktori untuk file berisi (dalam sistem sederhana) nomor i-node untuk file yang bersangkutan. Tautan keras (hanya entri direktori lain) juga harus berisi nomor i-simpul yang sama. Ini baik-baik saja, tetapi angka-angka i-node hanya unik dalam satu sistem file (mereka biasanya satu set padat mulai dari 1).

Bind mount Anda tidak memperbaiki masalah itu. Ya, itu membangun semacam 'fiksi' dari struktur, tetapi yang tidak dilakukannya adalah menghitung ulang semua i-node pada satu sistem file untuk memastikan semuanya unik di kedua sistem file yang bersangkutan! Itu akan konyol.

Pembatasan ini selalu ada di sistem UNIX. Tautan simbolis diciptakan sebagian untuk menyelesaikan ini. Saya tahu mereka secara fungsional tidak persis sama, tetapi mereka biasanya OK.

Coba tautan simbolis? ( ln -s)

Bob Eager
sumber
Tidak akan ada nama untuk inode yang dinomori ulang di sini. Hanya ada satu sistem file yang mendasarinya, dengan dua tampilan.
Gilles 'SANGAT berhenti menjadi jahat'
Salah satu alasan saya tidak menginginkan tautan simbolis adalah karena jalur saya panjang dan berantakan ls -l. Agak konyol penalaran pada awalnya, tetapi kemudian mengarah ke lubang kelinci dan saya ingin tahu apa yang terjadi dengan tautan keras ...
jdk1.0
@Gilles, itu yang aku katakan. Maksud saya adalah bahwa nomor baru inode akan konyol. Tidak tahu mengapa jawaban yang benar diturunkan.
Bob Eager
Anda mendapatkan kesimpulan yang benar, tetapi penjelasan Anda salah di banyak tempat sehingga jawaban Anda secara keseluruhan sangat menyesatkan. Lihat jawaban sourcejedi untuk penjelasan yang bagus.
Gilles 'SANGAT berhenti menjadi jahat'
Saya tidak melihat kesalahan sama sekali, meskipun saya akui saya bisa lebih jelas.
Bob Eager