Apakah ada mekanisme yang melindungi aplikasi selama pemutakhiran perpustakaan?

10

Jika pengguna bekerja pada aplikasi yang terhubung secara dinamis, dan sistem sedang ditingkatkan, apakah ada mekanisme perlindungan yang mencegah korupsi aplikasi?

Atau terserah aplikasi?

sevo
sumber
Ingat membaca buku Linux tentang bagaimana Anda harus menggunakan ln -sfketika menukar perpustakaan, karena -fmemungkinkan Anda untuk "menimpa" tujuan yang ada dari tautan simbolik dengan yang baru, tanpa pernah "rusak" (tidak seperti jika Anda rmdiikuti oleh a ln -s). Jadi sebelum perintah, library.so menunjuk ke versi lama, mis. library.so.4 ... setelah perintah, itu hanya menunjuk ke library.so.5 (atau apa pun) bukan - tanpa pernah tidak menunjuk ke perpustakaan valid.
Baard Kopperud

Jawaban:

16

Seperti disebutkan oleh @ Kusalananda, biasanya peningkatan dilakukan dengan menghapus file lama, dan membuat yang baru dengan nama yang sama. Ini sebenarnya akan membuat file baru dengan inode baru, membiarkan sistem bebas untuk menggunakan yang lama asalkan terbuka.

Sebagai contoh yang disederhanakan, hal-hal seperti

rm /bin/cat
cp /new/version/of/cat /bin/cat

akan membuat file baru secara logis, dan berfungsi meskipun catmungkin sedang berjalan. Hal yang sama berlaku untuk perpustakaan. (Di atas adalah contoh, bukan cara yang kuat untuk memutakhirkan file di dunia nyata.)


Seseorang dapat mencoba mengubah biner di tempat alih-alih membuat biner baru dengan nama yang sama. Dalam hal ini, setidaknya Linux sebenarnya mencegah membuat perubahan pada executable yang sedang digunakan:

window 1 # ./cat
window 2 # echo foobar > cat
-bash: cat: Text file busy

Namun, ini tampaknya tidak berfungsi dengan perpustakaan yang dimuat secara dinamis ...

Saya membuat salinan libc.so.6untuk pengujian, dan mengisinya dengan nol saat sedang digunakan:

window 1 /tmp/lib# LD_LIBRARY_PATH=/tmp/lib ldd ./cat
    linux-vdso.so.1 (0x00007ffcfaf30000)
    libc.so.6 => /tmp/lib/libc.so.6 (0x00007f1145e67000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f1146212000)

window 1 /tmp/lib# LD_LIBRARY_PATH=/tmp/lib ./cat
foo
foo

Segmentation fault

(Sementara itu di jendela lain, setelah foo, sebelum segfault)

window 2 /tmp/lib# dd if=/dev/zero of=libc.so.6 bs=1024 count=2000

Benar-benar tidak ada yang dapat dilakukan oleh program itu sendiri terhadap hal ini, karena saya secara efektif mengedit kodenya secara online.

(Ini kemungkinan akan tergantung pada sistem, saya menguji Debian Jessie 8.5, Linux 3.16.7-ckt25-2 + deb8u3. Sistem IIRC Windows khususnya lebih agresif dalam mencegah modifikasi file yang sedang digunakan dari modifikasi.)


Jadi saya kira jawabannya adalah bahwa upgrade biasanya dilakukan dengan cara yang menghindari masalah, dan ini dibantu oleh internal filesystem. Tapi (di Linux) tampaknya tidak ada perlindungan terhadap perpustakaan dinamis yang benar-benar merusak.

ilkkachu
sumber
The installutilitas umumnya digunakan untuk hal-hal seperti ini. Anda tidak perlu secara eksplisit rmfile tujuan. Plus itu mempertahankan izin dari file yang ada, dapat membuat cadangan, mengatur mode baru, dll. Contoh penggunaan:install /new/version/of/cat /bin/cat
Patrick
Tentu. The rm+ cpdimaksudkan sebagai contoh. Mungkin juga pintar untuk menempatkan file baru di tempat secara atomis dengan mengganti nama, menghindari jendela pendek di mana tidak ada versi yang tersedia. (Meskipun GNU installtampaknya tidak melakukan itu, hmpf.)
ilkkachu
2
Saya ingin memperjelas sesuatu yang ada di jawaban ini: Di ​​Unixes jika file terbuka, dan dihapus ( rm), maka itu belum dihapus. Itu akan ada pada disk dan masih bisa dibaca oleh semua proses yang membuatnya terbuka. Ini hanya akan dihapus ketika jumlah hard-link-nya mencapai nol DAN jumlah presesi dengan file yang terbuka mencapai nol.
ctrl-alt-delor
@ Patrick: installUtilitas ini secara khusus tidak aman! Itu menimpa file target di tempat daripada menggantikannya secara atom. mv(dengan sumber dan dest dalam direktori yang sama, sumber biasanya file temp) adalah satu-satunya cara aman untuk menginstal file.
R .. GitHub BERHENTI MEMBANTU ICE
1
@Patrick sejauh yang saya stracekatakan, installdi GNU coreutils menghapus tautan file target dan kemudian menyalin yang baru di tempatnya. Yang berarti bahwa ada jendela pendek di mana file tersebut parsial. Itu tidak mengatur file secara atom di tempat dengan mengganti nama.
ilkkachu
3

File tidak akan "dihapus dengan benar" jika mereka tidak terhubung saat masih dibuka. Ketika mereka ditutup, ruang disk yang mereka gunakan akan dianggap "bebas" lagi. Ini berlaku untuk aplikasi yang sedang berjalan dan perpustakaan bersama mereka juga.

Satu-satunya hal yang saya lihat gagal adalah jika program yang digunakan dlopen()untuk memuat perpustakaan bersama berdasarkan permintaan, atau jika program harus mengakses file lain sesuai permintaan seperti kamus, file tema, atau file lain yang tiba-tiba menghilang.

Sebagai ilustrasi: Menjalankan vimdalam satu sesi shell sambil menghapus instalasi vimdi sesi shell lain tidak akan "merusak" atau mengakhiri vimsesi yang sedang berjalan . Tetapi beberapa hal akan mulai gagal, seperti pemeriksaan ejaan misalnya, yang mengharuskan vimuntuk membuka file dalam pemasangannya.

Kusalananda
sumber