Vim puede romper los permisos de archivo?

8

Estaba usando Vim el otro día como siempre, cuando noté algo extraño. Esto es lo que hice:

~$ touch testfile
~$ ls -l | grep testfile
-rw-r--r-- 1 username groupname 0 Jul 23 10:00 testfile
~$ vim testfile

Luego hice un cambio, y salvé y renuncié :wq. Muy normal. Entonces, sin embargo:

~$ sudo chown root:root testfile
~$ sudo chmod 644 testfile
~$ sudo -k
~$ ls -l | grep testfile
-rw-r--r-- root root 0 Jul 23 10:02 testfile
~$ vim testfile

Por lo tanto, el usuario root debería tener acceso a R / W y todos los demás solo deberían haber leído. Edite el archivo, intente guardar, no puede. Impresionante, trabajando según lo previsto. Sin embargo, si guarda con :w!, vim cambia de algún modo la propiedad del archivo a nombre de usuario: grupo de usuarios y el archivo se guarda. Incluso si haces esto:

~$ sudo chmod 444 testfile
~$ sudo -k
~$ ls -l | grep testfile
-r--r--r-- 1 root root 0 Jul 23 10:06 testfile
~$ vim testfile

¡ Todavía puedes sobrescribir con :w!! ¿Qué está pasando? ¿Cómo puede violar las leyes de propiedad de archivos y permisos como este? Miré la página de ayuda en vim diciendo :help :wy encontré esto:

:w[rite]! [++opt]    Like ":write", but forcefully write when 'readonly' is set or there is another reason why writing was refused.
                     Note: This may change the permission and ownership of the file and break (symbolic) links. Add the 'W' flage to 'cpoptions' to avoid this.

No he podido escribir en un archivo en vim anteriormente cuando no debería, así que supongo que el verdadero corazón de mi pregunta es, ¿cómo puedo hacer que un archivo no sea editable por vim y por qué no se basa en el archivo? permisos del sistema, como era de esperar, y ¿qué mecanismo está usando vim para editar el archivo que otros editores (gedit, nano) no pueden usar?

EDITAR: La computadora en la que probé esto está usando el kernel de Linux 3.15.5-2-ARCH. El número de versión de Vim es 7.4.373-1, y es el que instaló pacman: no lo compilé desde cero con ninguna opción especial.

zrneely
fuente
Parece que no puedo reproducir el problema, a menos que haga algunos trucos como se describe aquí
Davyzhu
Lo intenté nuevamente usando los comandos de la pregunta y sucedió de la misma manera. Sin embargo, editaré la pregunta para agregar detalles sobre mi computadora, ya que parece que esto puede depender de la plataforma.
zrneely
Mi primer presentimiento es que puedes cambiar la propiedad de los archivos en un directorio al que tienes acceso de escritura. Pero parece que ese no es el caso . CAP_CHOWNSe requiere llamar chown(2). Por cierto, puedo reproducir en Debian, con vim 7.4.
Bob

Respuestas:

10

Puedo ver que su ruta actual es ~, el directorio de inicio de su usuario. Debería tener permisos de escritura en ese directorio.

Piénselo de otra manera: si tiene permisos de lectura y escritura en el directorio, ¿qué le impide copiar el archivo, eliminar el antiguo y renombrar el nuevo con diferentes permisos?

¡Esto es exactamente lo que hace vim!


Si ejecuta vim bajo strace, por ejemplo:

open("testfile", O_WRONLY|O_CREAT|O_TRUNC, 0644) = -1 EACCES (Permission denied)
lstat("testfile", {st_mode=S_IFREG|0644, st_size=10, ...}) = 0
getuid()                                = 1000
unlink("testfile")                      = 0
open("testfile", O_WRONLY|O_CREAT|O_TRUNC, 0644) = 3
write(3, "ffjidfjds\n", 10)             = 10
fsync(3)                                = 0
close(3)                                = 0
chmod("testfile", 0644)                 = 0

Basado en este registro, puedo adivinar el siguiente proceso:

Algunas verificaciones de permisos anteriores (e chownintentos, etc.) se omiten por brevedad.

  1. open Intento de abrir el archivo para escritura (falla: permiso denegado)
  2. lstat Comprueba el propietario del archivo
  3. getuuid Verifique la ID de usuario actual para ver si coinciden con el propietario del archivo
  4. unlink Elimine el archivo (esto está permitido porque tiene permiso de escritura en el directorio)
  5. open Crea un nuevo archivo con el mismo nombre
  6. write El contenido del archivo (leído anteriormente, escribí algunas galimatías)
  7. fsync Vaciar el archivo al disco (no es realmente importante)
  8. close
  9. chmod Cambie los permisos del nuevo archivo para que se parezca al anterior; ahora tiene un nuevo propietario.
Beto
fuente
OK gracias. Me alegra haberlo resuelto. Entonces, si no tengo permisos de escritura en el directorio, no podré usar :w!, lo cual tiene sentido.
zrneely
Además, la información de strace es realmente útil: ahora tengo otra herramienta para mis propias investigaciones en el futuro.
zrneely
1
@zrneely Un consejo para strace: usar la -oopción para escribir la salida en un archivo; de lo contrario, choca con vimla salida de. En cuanto a los permisos de escritura, no veo que la comprobación de permisos de directorio con statpero no intente crear un archivo (llamado así 4913, parece aleatorio) en el directorio actual y luego eliminarlo.
Bob
Parece que en 4913realidad es solo el primer nombre que intenta, y su propósito es verificar si tiene suficientes permisos para hacerlo. Ver: bugzilla.redhat.com/show_bug.cgi?id=427711#c6 y groups.google.com/forum/#!topic/vim_dev/sppdpElxY44
Bob