Vi puede escribir en el archivo a pesar de que el archivo es de solo lectura

12

El siguiente ejemplo muestra cómo crear un archivo con solo permisos de lectura. Como podemos ver, cuando trato de escribir en este archivo usando el comando echo obtengo Permission denied,.

Pero, ¿por qué, en el caso de que usemos vi, no obtenemos Permission denied? Como se puede ver aquí, podemos escribir en el archivo a pesar de que el archivo es de solo lectura.

¿Que está sucediendo aquí? ¿Es esto un error vi?

[admin@madona-machine1 ~]$ touch test-file
[admin@madona-machine1 ~]$ ls -ltr
total 0
-rw-r--r-- 1 admin admin 0 Apr 13 07:32 test-file
[admin@madona-machine1 ~]$ chmod -w  test-file
[admin@madona-machine1 ~]$ ls -ltr
total 0
-r--r--r-- 1 admin admin 0 Apr 13 07:32 test-file
[admin@madona-machine1 ~]$ echo try_to_write > test-file
-bash: test-file: Permission denied
[admin@madona-machine1 ~]$ vi test-file

I am good singer,

 ~
 ~
 ~
 ~
 ~
 ~
 ~                                                
   "test-file" 1L, 4C written
maihabunash
fuente
1
FYI hay un sitio beta SE para esto - vi.stackexchange.com
Raystafarian

Respuestas:

28

Nota : Debido a razones de licencias heredadas, la mayoría de las distribuciones de GNU / Linux no incluyen el programa vi original tal como lo escribió Bill Joy. En cambio, el comando vi se proporciona ejecutando Vim en modo de compatibilidad vi. La siguiente respuesta se basa en ejecutar Vim con su modo de compatibilidad vi.

Modificar un archivo de solo lectura

Vim avisa al usuario si modifican el buffer de un archivo de sólo lectura, W10: Warning: Changing a readonly file. Si el usuario intenta escribir en este archivo, que reciben el mensaje de error siguiente, 'readonly' option is set (add ! to override).

Cuando el usuario de Vim puede escribir el directorio principal

Vim, al ser útil, le informa al usuario que puede insistir forzosamente en escribir agregando un signo de exclamación !al wcomando. Si se usa esta versión contundente del comando de escritura, Vim elimina el archivo original (si usa Vim con la backupopción de solo Vim establecida, el archivo original se renombra para que sea el mismo que el archivo de respaldo). Luego abre (crea) un nuevo archivo con el mismo nombre que el original y escribe el contenido de su búfer en este nuevo archivo. Esto se puede observar comprobando el inodo del archivo antes y después de ejecutar Vim:

$ ls -l --inode t

131529 -r--r--r-- 1 anthony anthony 0 Apr 13 09:23 t

$ vi t
$ ls -l --inode t

131649 -r--r--r-- 1 anthony anthony 4 Apr 13 09:23 t

Nota: Esto también puede cambiar el permiso y la propiedad del archivo y romper los enlaces (simbólicos), por ejemplo, si el archivo original era propiedad de otro usuario, el nuevo archivo sería propiedad del usuario que ejecuta Vim.

Un proceso solo puede hacer esto si tiene permiso de escritura para el directorio padre del archivo. En general, para garantizar que un programa no pueda modificar un archivo, los permisos tanto del archivo en sí como de su directorio principal deben estar protegidos.

Cuando el usuario principal no puede escribir en el directorio principal

Sin embargo, incluso en este caso, Vim hace todo lo posible para ayudar al usuario insistente a sobrescribir el archivo. Si el usuario de Vim tiene la propiedad del archivo, Vim puede sortear la restricción del directorio principal de solo lectura cambiando temporalmente el permiso del archivo (usando la chmodllamada al sistema), escribiendo el búfer en el archivo, cerrando el archivo y luego cambiando el permisos de vuelta. Aquí hay un extracto de las llamadas al sistema realizadas mientras se ejecuta vi a través de strace strace -o ../vi.trace vi t:

getuid()                                = 501
chmod("t", 0100644)                     = 0
open("t", O_WRONLY|O_CREAT|O_TRUNC, 0644) = 4
write(4, "I am good singer,\n", 18)     = 18
fsync(4)                                = 0
close(4)                                = 0
chmod("t", 0100444)                     = 0

Nota: Esto no sucede si el usuario de Vim está editando un archivo del que no es propietario, ya que Vim no podrá cambiar los permisos del archivo.

Apéndice

Para estar realmente seguro de que un archivo no puede modificarse (en un sistema GNU / Linux), ejecute el chattrcomando como superusuario:

sudo chattr +i filename

De man chattr:

Un archivo con el atributo 'i' no se puede modificar: no se puede eliminar ni renombrar, no se puede crear ningún enlace a este archivo y no se pueden escribir datos en el archivo. Solo el superusuario o un proceso que posee la capacidad CAP_LINUX_IMMUTABLE puede establecer o borrar este atributo.

Anthony Geoghegan
fuente
2
¡Santo cielo, eso fue minucioso!
Camille Goudeseune
44
@CamilleGoudeseune Después de publicar la primera versión de mi respuesta, realicé algunos experimentos y terminé pasando aproximadamente una hora ejecutando Vim a través de una ventana para ver qué estaba haciendo detrás de escena en diferentes situaciones (diferentes permutaciones de permisos y propiedad de ambos archivos y archivos). directorio de padres). A veces me dejo llevar, pero una vez que publiqué una respuesta, quería asegurarme de que lo que decía era correcto.
Anthony Geoghegan
5

La mayoría, si no todas las viimplementaciones le impiden escribir el archivo si utiliza un habitual comando Guardar como sea ZZ, :w, :wqo :x, por ejemplo, con vim:

:w
E45: 'readonly' option is set (add ! to override)

Por otro lado, si le dice vique escriba el archivo a pesar de sus permisos, con el uso de algo como :x!o :wq!, el editor está relajando temporalmente los permisos para permitir que se escriba el archivo:

...
stat("test-file", {st_mode=S_IFREG|0444, st_size=7, ...}) = 0
getuid()                                = 1000
chmod("test-file", 0100644)             = 0
...
open("test-file", O_WRONLY|O_CREAT|O_TRUNC, 0644) = 4
write(4, "I am good singer,\n", 18)               = 18
fsync(4)                                = 0
close(4)                                = 0
chmod("test-file", 0100444)             = 0
....

En ese caso, el número de inodo no se modifica.

Finalmente, esto no es un error, ya que si no tiene permiso para cambiar los permisos del archivo, no puede modificarlo vi.

jlliagre
fuente
Ja! Después de publicar mi respuesta, realicé algunos experimentos y terminé pasando cerca de una hora ejecutando Vim a través de una ventana para ver qué estaba haciendo detrás de escena en diferentes situaciones (diferentes permutaciones de permisos y propiedad del archivo y el directorio principal). Acabo de ver tu respuesta después de terminar de resumir los resultados de mis experimentos. Fue una buena experiencia de aprendizaje.
Anthony Geoghegan