Czy istnieje mechanizm chroniący aplikacje podczas aktualizacji biblioteki?

10

Jeśli użytkownik pracuje nad aplikacją, która jest dynamicznie połączona, a system jest aktualizowany, czy istnieje jakiś mechanizm ochronny, który zapobiega uszkodzeniu aplikacji?

Czy to zależy od zastosowania?

sevo
źródło
Pamiętaj, aby przeczytać książkę o Linuksie o tym, jak powinieneś używać ln -sfprzy zamianie bibliotek, ponieważ -fpozwoliło to na „zastąpienie” istniejącego miejsca docelowego dowiązania symbolicznego nowym, bez jego „łamania” (inaczej niż w przypadku rmpóźniejszego a ln -s). Przed poleceniem biblioteka.so wskazała więc na starą wersję, np. biblioteka.so.4 ... po komendzie po prostu wskazywała na bibliotekę.so.5 (lub cokolwiek innego) - nigdy nie wskazując prawidłowej biblioteki.
Baard Kopperud

Odpowiedzi:

16

Jak wspomniano w @Kusalananda, zwykle aktualizacje są wykonywane przez usunięcie starego pliku i utworzenie nowego o tej samej nazwie. Spowoduje to utworzenie nowego pliku z nowym i-węzłem, pozostawiając systemowi możliwość korzystania ze starego, o ile jest on otwarty.

Jako uproszczony przykład, takie rzeczy

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

utworzy logicznie nowy plik i działa, nawet jeśli catmoże być uruchomiony. To samo dotyczy bibliotek. (Powyższe jest przykładem, a nie solidnym sposobem uaktualnienia pliku w prawdziwym świecie).


Ktoś może spróbować zmienić plik binarny na miejscu zamiast tworzyć nowy o tej samej nazwie. W takim przypadku przynajmniej Linux faktycznie uniemożliwia dokonywanie zmian w używanym pliku wykonywalnym:

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

Nie wydaje się to jednak działać z dynamicznie ładowanymi bibliotekami ...

Zrobiłem kopię libc.so.6do testowania i wypełniłem ją zerami, gdy była w użyciu:

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

(Tymczasem w innym oknie, po foo, przed segfault)

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

Naprawdę nic nie może zrobić sam program, ponieważ skutecznie edytowałem jego kod online.

(Prawdopodobnie byłoby to zależne od systemu, przetestowałem na Debian Jessie 8.5, Linux 3.16.7-ckt25-2 + deb8u3. W szczególności systemy Windows IIRC są jeszcze bardziej agresywne w zapobieganiu modyfikacji używanych plików.)


Wydaje mi się, że odpowiedzią jest, że aktualizacje są zwykle wykonywane w sposób pozwalający uniknąć problemów, a to pomaga wewnętrzne elementy systemu plików. Ale (w systemie Linux) wydaje się, że nie ma żadnych zabezpieczeń przed faktycznym uszkodzeniem bibliotek dynamicznych.

ilkkachu
źródło
installNarzędzie jest powszechnie stosowany do rzeczy jak ta. Nie musisz jawnie rmpliku docelowego. Ponadto zachowuje uprawnienia do istniejącego pliku, może wykonać kopię zapasową, ustawić nowy tryb itp. Przykładowe użycie:install /new/version/of/cat /bin/cat
Patrick
Pewnie. Znak rm+ cpbył pomyślany jako przykład. Rozsądne może być także umieszczenie nowego pliku atomowo za pomocą zmiany nazwy, unikając krótkiego okna, w którym żadna wersja nie jest dostępna. (Choć installwydaje się, że GNU tego nie robi, hmpf.)
ilkkachu
2
Chciałbym wyjaśnić coś, co znajduje się w tej odpowiedzi: w Uniksach, jeśli plik jest otwarty i usunięty ( rm), to nie jest jeszcze usunięty. Będzie istniał na dysku i nadal będzie mógł być odczytany przez wszystkie procesy, które go mają otwarte. Zostanie usunięty tylko wtedy, gdy liczba twardych linków osiągnie zero, a liczba precesji przy otwartym pliku osiągnie zero.
ctrl-alt-delor
@Patrick: installNarzędzie jest szczególnie niebezpieczne! Zastępuje on plik docelowy zamiast zastępować go atomowo. mv(z kodem źródłowym i docelowym w tym samym katalogu, źródło zwykle plik tymczasowy) jest jedynym bezpiecznym sposobem instalowania plików.
R .. GitHub ZATRZYMAJ LÓD
1
@Patrick, o ile mi stracemówi, installw GNU coreutils rozłącza plik docelowy, a następnie kopiuje nowy na swoje miejsce. Co oznacza, że ​​jest krótkie okno, w którym plik jest częściowy. Nie ustawia pliku atomowo w miejscu przy zmianie nazwy.
ilkkachu
3

Pliki nie zostaną „poprawnie usunięte”, jeśli zostaną rozłączone, gdy są jeszcze otwarte. Po ich zamknięciu wykorzystane miejsce na dysku zostanie ponownie uznane za „wolne”. Dotyczy to również obecnie działających aplikacji i ich bibliotek współdzielonych.

Jedyną rzeczą, która nie powiodła się, byłaby sytuacja, gdy program używałby dlopen()do ładowania biblioteki współdzielonej na żądanie lub gdyby program miał dostęp do innych plików na żądanie, takich jak słowniki, pliki motywów lub inne pliki, które nagle zniknęły.

Dla zilustrowania: Uruchamianie vimw jednej sesji powłoki podczas usuwania instalacji vimw innej sesji powłoki nie „uszkodzi” ani nie zakończy bieżącej vimsesji. Ale niektóre rzeczy zaczną się nie powieść, na przykład sprawdzanie pisowni, które wymaga vimotwarcia plików podczas instalacji.

Kusalananda
źródło