¿Existe algún mecanismo que proteja las aplicaciones durante la actualización de la biblioteca?

10

Si el usuario trabaja en una aplicación que está vinculada dinámicamente y el sistema se está actualizando, ¿existe algún mecanismo de protección que evite la corrupción de la aplicación?

¿O depende de la aplicación?

sevo
fuente
Recuerde leer un libro de Linux sobre cómo debe usar ln -sfal intercambiar bibliotecas, ya -fque le permite "sobrescribir" el destino existente del enlace simbólico con uno nuevo, sin que nunca se "rompa" (a diferencia de si hiciera un rmseguimiento por a ln -s) Entonces, antes del comando, library.so apuntaba a la versión anterior, por ejemplo. library.so.4 ... después de la orden, se limitó a señalar library.so.5 (o lo que sea) en vez - sin tener que no apunta a una biblioteca válida.
Baard Kopperud

Respuestas:

16

Como mencionó @Kusalananda, por lo general, las actualizaciones se realizan eliminando el archivo antiguo y creando uno nuevo con el mismo nombre. En realidad, esto creará un nuevo archivo con un nuevo inodo, dejando al sistema libre para usar el antiguo siempre que esté abierto.

Como ejemplo simplificado, cosas como

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

creará un archivo lógicamente nuevo y funciona aunque catpueda estar ejecutándose. Lo mismo vale para las bibliotecas. (Lo anterior es un ejemplo, no una forma sólida de actualizar un archivo en el mundo real).


Alguien podría intentar cambiar el binario in situ en lugar de crear uno nuevo con el mismo nombre. En este caso, al menos Linux realmente evita realizar cambios en un ejecutable que está en uso:

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

Sin embargo, esto no parece funcionar con bibliotecas cargadas dinámicamente ...

Hice una copia libc.so.6para probar y la llené con ceros mientras estaba en uso:

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

(Mientras tanto, en otra ventana, después de foo, antes de la segfault)

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

Realmente no hay nada que el programa en sí pueda hacer contra esto, ya que efectivamente edité su código en línea.

(Esto probablemente dependerá del sistema, probé en Debian Jessie 8.5, Linux 3.16.7-ckt25-2 + deb8u3. Los sistemas Windows IIRC en particular son aún más agresivos para evitar que se modifiquen los archivos en uso).


Entonces, supongo que la respuesta es que las actualizaciones generalmente se realizan de una manera que evita cualquier problema, y ​​esto es ayudado por los componentes internos del sistema de archivos. Pero (en Linux) no parece haber ninguna protección contra la corrupción de las bibliotecas dinámicas.

ilkkachu
fuente
La installutilidad se usa comúnmente para cosas como esta. No necesita explícitamente rmel archivo de destino. Además, conserva los permisos del archivo existente, puede hacer una copia de seguridad, establecer un nuevo modo, etc. Ejemplo de uso:install /new/version/of/cat /bin/cat
Patrick
Seguro. El rm+ cpse entiende como un ejemplo. También podría ser inteligente colocar el nuevo archivo atómicamente con un cambio de nombre, para evitar una ventana corta en la que ninguna versión esté disponible. (Aunque GNU installni siquiera parece hacer eso, hmpf.)
ilkkachu
2
Me gustaría aclarar algo que está en esta respuesta: en Unixes si un archivo está abierto y eliminado ( rm), aún no se ha eliminado. Existirá en el disco y aún puede ser leído por todos los procesos que lo tienen abierto. Solo se eliminará cuando su recuento de enlaces duros llegue a cero Y el número de precesos con el archivo abierto llegue a cero.
ctrl-alt-delor
@Patrick: ¡La installutilidad es específicamente insegura! Sobrescribe el archivo de destino en su lugar en lugar de reemplazarlo atómicamente. mv(con fuente y destino en el mismo directorio, la fuente suele ser un archivo temporal) es la única forma segura de instalar archivos.
R .. GitHub DEJA DE AYUDAR A HIELO
1
@Patrick hasta donde yo digo strace, installen GNU coreutils desvincula el archivo de destino y luego copia uno nuevo en su lugar. Lo que significa que hay una ventana corta durante la cual el archivo es parcial. No establece el archivo atómicamente en su lugar con un cambio de nombre.
ilkkachu
3

Los archivos no se "eliminarán correctamente" si se desvinculan mientras todavía están abiertos. Cuando están cerrados, el espacio en disco que usaron se considerará "libre" nuevamente. Esto también se aplica a las aplicaciones que se ejecutan actualmente y sus bibliotecas compartidas.

Lo único que podría ver fallar sería si un programa solía dlopen()cargar una biblioteca compartida a pedido, o si el programa tuviera que acceder a otros archivos a pedido, como diccionarios, archivos de temas u otros archivos que desaparecieron repentinamente.

Para ilustrar: la ejecución vimen una sesión de shell mientras se elimina la instalación de vimotra sesión de shell no "corromperá" ni terminará la vimsesión actualmente en ejecución . Pero algunas cosas comenzarán a fallar, como la corrección ortográfica, por ejemplo, que requiere vimabrir archivos en su instalación.

Kusalananda
fuente