Cuando trato de sobrescribir un archivo binario que se inicia actualmente, cp
no se puede sobrescribir, pero es posible que rm
lo haga cp
. Por ejemplo:
user@poste:~$ cp binaryFile /tmp
user@poste:~$ sudo cp /tmp/binaryFile binaryFile
[sudo] password for user:
cp: cannot create regular file `binaryFile`: Text file busy
user@poste:~$ sudo rm binaryFile
user@poste:~$ sudo cp /tmp/binaryFile binaryFile
user@poste:~$ file binaryFile
binaryFile : ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0x7ce005d9eb50e2574246b6a881e625802f7e49f2, not stripped
¿Alguna idea de por qué?
Respuestas:
En el primer caso, está intentando sobrescribir el contenido de un archivo que se está ejecutando actualmente como un programa. Linux no lo permite: si lo hiciera, sobrescribiría el código justo cuando el sistema operativo lo estaba ejecutando; La primera diferencia podría bloquear el programa o hacer que funcione mal.
Pero en el segundo caso, en realidad no está cambiando el contenido del archivo antiguo: está creando un nuevo archivo en su lugar, mientras que el anterior simplemente pierde el nombre del archivo pero mantiene su contenido intacto.
(Recuerde que
rm
no técnicamente borrar archivos, que sólo elimina los enlaces de directorio - similar a cómoln
añade más enlaces a un mismo archivo Sólo cuando un archivo no tiene enlaces. Y no hay referencias de archivos abiertos, automáticamente se elimina.)El sistema hace referencia a los archivos en uso por su inodo, por lo que no importa que tengan el mismo nombre de archivo; sigue siendo el archivo antiguo que permanece abierto por el sistema, y aunque ya no tiene enlaces, solo se eliminará una vez que todos los programas lo cierran.
fuente
/proc/*/fd
para acceder a él y opcionalmente linkat () para agregar un nuevo enlace al sistema de archivos.linkat()
, por razones de seguridad . (Excepción a esta regla: a menos que se haya creado conopen(O_TMPFILE)
él, así que comenzó con cero enlaces). Si lo intenta,linkat()
devuelve ENOENT, incluso como root. Vea mi respuesta a esa pregunta para que se ejecute un script perllinkat
y demuestre que no funciona, incluso como root: /