Existe-t-il un mécanisme qui protège les applications lors de la mise à niveau de la bibliothèque?

10

Si l'utilisateur travaille sur une application liée dynamiquement et que le système est mis à niveau, existe-t-il un mécanisme de protection qui empêche la corruption des applications?

Ou est-ce à la demande?

sevo
la source
N'oubliez pas de lire un livre Linux sur la façon dont vous devez utiliser ln -sflorsque vous permutez des bibliothèques, car cela -fvous permet de "remplacer" la destination existante du lien symbolique par une nouvelle, sans qu'il soit jamais "cassé" (contrairement à si vous avez fait un rmsuivi par a ln -s). Donc, avant la commande, library.so pointait vers l'ancienne version, par exemple. library.so.4 ... après la commande, il suffit pointé library.so.5 (ou autre) à la place - sans jamais ne pointant vers une bibliothèque valide.
Baard Kopperud

Réponses:

16

Comme mentionné par @Kusalananda, les mises à niveau sont généralement effectuées en supprimant l'ancien fichier et en créant un nouveau avec le même nom. Cela créera en fait un nouveau fichier avec un nouvel inode, laissant le système libre d'utiliser l'ancien tant qu'il est ouvert.

Comme exemple simplifié, des trucs comme

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

va créer un nouveau fichier logique et fonctionne même s'il catest en cours d'exécution. Il en va de même pour les bibliothèques. (Ce qui précède est un exemple, pas un moyen robuste de mettre à niveau un fichier dans le monde réel.)


Quelqu'un pourrait essayer de changer le binaire en place au lieu d'en créer un nouveau avec le même nom. Dans ce cas, au moins Linux empêche en fait d'apporter des modifications à un exécutable en cours d'utilisation:

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

Cependant, cela ne semble pas fonctionner avec les bibliothèques chargées dynamiquement ...

J'ai fait une copie de libc.so.6pour tester et l' ai remplie de zéros pendant son utilisation:

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

(Pendant ce temps dans une autre fenêtre, après le foo, avant la faute de segmentation)

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

Il n'y a vraiment rien que le programme lui-même puisse faire contre cela, car j'ai effectivement édité son code en ligne.

(Cela dépendrait probablement du système, j'ai testé sur Debian Jessie 8.5, Linux 3.16.7-ckt25-2 + deb8u3. Les systèmes Windows IIRC en particulier sont encore plus agressifs pour empêcher la modification des fichiers en cours d'utilisation.)


Donc, je suppose que la réponse est que les mises à niveau sont généralement effectuées de manière à éviter tout problème, et cela est aidé par les internes du système de fichiers. Mais (sous Linux) il ne semble pas y avoir de protection contre la corruption des bibliothèques dynamiques.

ilkkachu
la source
L' installutilitaire est couramment utilisé pour des trucs comme celui-ci. Vous n'avez pas besoin de explicitement rmle fichier de destination. De plus, il préserve les autorisations du fichier existant, peut faire une sauvegarde, définir un nouveau mode, etc. Exemple d'utilisation:install /new/version/of/cat /bin/cat
Patrick
Sûr. Le rm+ cpétait donné à titre d'exemple. Il peut également être judicieux de mettre le nouveau fichier en place de manière atomique avec un renommage, afin d'éviter une courte fenêtre dans laquelle aucune version n'est disponible. (Bien que GNU installne semble même pas faire ça, hmpf.)
ilkkachu
2
Je voudrais clarifier quelque chose qui se trouve dans cette réponse: sous Unixes, si un fichier est ouvert et supprimé ( rm), il n'est pas encore supprimé. Il existera sur le disque et pourra toujours être lu par tous les processus qui l'ont ouvert. Il ne sera supprimé que lorsque son nombre de liens durs atteindra zéro ET que le nombre de précessions avec le fichier ouvert atteindra zéro.
ctrl-alt-delor
@Patrick: L' installutilitaire est particulièrement dangereux! Il écrase le fichier cible en place plutôt que de le remplacer atomiquement. mv(avec source et dest dans le même répertoire, source généralement un fichier temporaire) est le seul moyen sûr d'installer des fichiers.
R .. GitHub STOP HELPING ICE
1
@Patrick pour autant que je le stracedise, installdans GNU coreutils dissocie le fichier cible, puis copie un nouveau à sa place. Ce qui signifie qu'il y a une courte fenêtre pendant laquelle le fichier est partiel. Il ne définit pas le fichier atomiquement en place avec un renommage.
ilkkachu
3

Les fichiers ne seront pas "correctement supprimés" s'ils ne sont pas liés lorsqu'ils sont encore ouverts. Lorsqu'ils sont fermés, l'espace disque qu'ils ont utilisé sera à nouveau considéré comme "libre". Cela vaut également pour les applications en cours d'exécution et leurs bibliothèques partagées.

La seule chose que je pouvais voir échouer serait si un programme utilisé dlopen()pour charger une bibliothèque partagée à la demande, ou si le programme devait accéder à d'autres fichiers à la demande tels que des dictionnaires, des fichiers de thème ou d'autres fichiers qui ont soudainement disparu.

Pour illustrer: Exécuter vimdans une session shell tout en supprimant l'installation de vimdans une autre session shell ne "corrompra" pas ou ne mettra pas fin à la vimsession en cours d'exécution . Mais certaines choses vont commencer à échouer, comme la vérification orthographique par exemple, qui nécessite vimd'ouvrir des fichiers dans son installation.

Kusalananda
la source