¿Por qué puedo modificar un archivo de solo lectura?

42

Pregunta corta

¿Por qué podemos manipular un archivo de solo lectura en Vim usando :+ w+ q+ !incluso sin ser administrador?

Pregunta larga:

Tengo un archivo de texto (myFile.txt) que es de solo lectura para todos:

navid@navid-ThinkPad-T530:~/ubuntuTest$ ls -l myFile.txt 
-r--r--r-- 1 navid navid 26 Aug 22 21:21 myFile.txt

Puedo abrirlo con Vim sin tener privilegios de administrador:

navid@navid-ThinkPad-T530:~/ubuntuTest$ vi myFile.txt 

Lo modifico y presiono: Esc+ :+ w+ q+ Entery veo este mensaje de error:

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

Hasta ahora, todo tiene sentido. Pero cuando presiono: Esc+ :+ w+ q+ !+ Enter, Vim guarda los cambios.

Estoy usando Ubuntu 16.04 y VIM 7.4.

Navid Vafaei
fuente
1
@Zanna ¿Es dueño del directorio en el que se encuentra el archivo?
Rob
Sí, esto sería un problema ENORME de lo contrario :)
Rob
11
Modificar un archivo y reemplazar un archivo son dos cosas diferentes con diferentes requisitos de permiso.
David Schwartz el
1
Es posible que desee echar un vistazo a esto . Básicamente responde a su pregunta y como @DavidSchwartz señaló correctamente :Modifying a file and replacing a file are two different things
Panagiotis Tabakis
@PanagiotisTabakis Muy agradable encontrar esto es genial ... chmod para hacer que el archivo lea-escriba y vuelva a serlo si lo posee ... LOVE IT :)
Rob

Respuestas:

58

Como @Rob ya mencionó , solo puede hacer esto si tiene acceso de escritura al directorio que contiene el archivo. Intentar hacer lo mismo con un archivo, por ejemplo, /etcfallará.

En cuanto a cómo vim está haciendo esto, elimina el archivo y lo vuelve a crear. Para probar esto, creé un archivo propiedad de root:

echo foo | sudo tee fff

Y luego procedió a editar el archivo vimde la manera que usted describe, pero adjuntando el proceso stracepara ver qué está sucediendo:

strace vim fff 2> strace.out

Luego verifiqué strace.outy encontré:

unlink("fff")                           = 0
open("fff", O_WRONLY|O_CREAT|O_TRUNC, 0644) = 4
write(4, "foasdasdao\n", 11)            = 11

Entonces, primero se eliminó el archivo ( unlink("fff")), luego se creó un nuevo archivo con el mismo nombre ( open("fff", O_WRONLY|O_CREAT|O_TRUNC, 0644)) y las modificaciones que hice se escribieron en él ( write(4, "foasdasdao\n", 11)). Si prueba esto en casa, verá que después de editarlo vim, el archivo ahora le pertenecerá a usted y no a la raíz.

Entonces, estrictamente hablando, vimno está editando un archivo al que no tiene acceso de escritura. Está eliminando un archivo de un directorio en el que tiene acceso de escritura y luego crea un nuevo archivo al que, nuevamente, tiene acceso de escritura.

terdon
fuente
2
unix.stackexchange.com/questions/36467/…
Gilles 'SO- deja de ser malvado'
8
@CCJ es una operación de escritura en el directorio pero no en el archivo, no. Las operaciones de escritura en archivos son aquellas que cambian el contenido del archivo. Del mismo modo, crear / eliminar archivos son operaciones de escritura en el directorio ya que está cambiando su contenido.
terdon
2
Además, ese es un orden de operaciones peligroso. Sería más seguro escribir el reemplazo a un nuevo nombre de archivo y luego usarlo rename(2)para reemplazar el archivo anterior. Entonces no hay una ventana de tiempo donde sus datos no existan en el disco.
Peter Cordes el
55
@PeterCordes um, OK. Sin embargo, es posible que desee dirigir sus quejas a los desarrolladores de vim. Ni siquiera uso la cosa, estoy en el campamento de emacs.
terdon
3
@CCJ Eliminar un archivo es una operación de escritura en el directorio que lo contiene, no en el archivo en sí. Es perfectamente intuitivo que si está a cargo de un directorio (es decir, tiene acceso de escritura), debería poder controlar lo que contiene y no se debería permitir que el propietario de un archivo individual lo anule.
fkraiem
16

Siempre que posea el directorio principal, puede eliminar o reemplazar un archivo sin importar el permiso, ya que puede cambiar el contenido del directorio :).

Pruébelo con otro comando como rm, se lo indicará pero aún puede hacerlo. Haga que el directorio no se pueda escribir y eso debería detenerlo.

Adición:

Solo lo probé, pero mientras sea propietario del archivo, aún puedo modificarlo, incluso con la carpeta de solo lectura. Sin embargo, cuando cambio la propiedad a root: root no puede abrir el archivo para escribir. Entonces resuelve los archivos de modificación propiedad de root (u otra persona)

Robar
fuente
77
Parece que VIM elige entre múltiples estrategias, incluyendo reescribir en el lugar o desvincular + escribir un nuevo archivo.
Peter Cordes
3
@PeterCordes Sí Al parecer, se esforzará mucho para hacer lo que le dices :) muy astuto. :)
Rob
16

Al w!usarlo, está eliminando el archivo original ( que se le permite hacer ) y escribiendo su versión en su lugar.

Cuando tiene acceso de escritura a un directorio, puede: crear, mover o eliminar archivos dentro de ese directorio.

$ mkdir foo
$ echo hi > foo/file
$ chmod 777 foo
$ chmod 700 foo/file
$ ls -l foo/file 
-rwx------ 1 ravexina ravexina 7 Aug 31 03:19 foo/file

Ahora déjame cambiar mi usuario y cambiar el archivo

$ sudo -u user2 -s
$ vi foo/a # save using w! (I wrote into the file bye)
$ ls -l foo/a
-rwx------ 1 user2 user2 7 Aug 31 03:20 foo/file

Ahora mira lo que hay allí:

$ cat foo/file
bye
Ravexina
fuente
10

Ver :help write-readonly:

                                                        write-readonly
When the 'cpoptions' option contains 'W', Vim will refuse to overwrite a
readonly file.  When 'W' is not present, ":w!" will overwrite a readonly file,
if the system allows it (the directory must be writable).

Como tiene permisos de escritura en el directorio (lo que significa que puede crear, eliminar o renombrar archivos en él), el sistema lo permite.


El valor predeterminado de cpoptionsno contiene W:

                                                'cpoptions' 'cpo' cpo
'cpoptions' 'cpo'       string  (Vim default: "aABceFs",
                                 Vi default:  all flags)
                        global
muru
fuente
2

Esta es la advertencia de VIM que puede ser relativamente importante teniendo en cuenta cómo funcionan los permisos en UNIX. La aparente falta de intuición de esto se debe a que los sistemas de archivos UNIX tienen permisos para el archivo almacenado en el nodo i del archivo. La estructura del directorio está de alguna manera separada y solo está vinculando estos i-nodos. Los directorios también tienen sus permisos que dicen si puede vincular / desvincular archivos en él, o leerlo o atravesar subdirectorios. Este diseño permite que el mismo archivo pueda aparecer en varios lugares diferentes en la estructura del directorio (a través de enlaces duros). Al decir "agregar! Para anular", VIM está tratando de advertirle que el archivo original estará desvinculado (por lo que permanecerá intacto en todos los demás lugares) y el nuevo archivo se creará y vinculará al lugar original en la estructura del directorio. En caso de que el recuento de enlaces del archivo original disminuya a cero, el archivo original se liberará, pero si no, está clonando efectivamente el archivo. La apertura del archivo también cuenta como enlace, por lo que si algún programa abrió el archivo y usted acepta "agregar! Para anular", el programa no verá los cambios realizados en el archivo con VIM. El archivo solo se desvincula del directorio por VIM y después de cerrar el archivo por otro programa, el archivo se liberará, a menos que esté vinculado en otro lugar.

Tenga en cuenta que en Windows, los permisos para los archivos se almacenan en el directorio, por lo que desde el punto de vista del paradigma de los permisos de Windows, este comportamiento vim puede parecer extraño. Para escribir en el archivo, Windows lógicamente también puede verificar algunos permisos de directorio, incluso permisos de super-directorio. Como se dijo anteriormente, en UNIX, los permisos de directorio son irrelevantes para la manipulación del archivo en la medida en que pudo enumerarlo y abrirlo (es decir, había x para todos los super-directorios). Es posible que el archivo abierto en UNIX ya no tenga el nombre del archivo si se desvincula de todos los directorios después de abrirlo.

Por ejemplo, tiene el archivo / home / user1 / foo y es el mismo archivo que (es decir, está vinculado a) / home / user2 / foo y nadie puede escribir el archivo y actualmente está abierto por el programa P (lectura-escritura abierta por programa iniciado por root). Si user1 lo abre con vim y lo sobrescribe, hace su propia copia y ya no ve el archivo original. Si posteriormente user2 abre su enlace con vim y escribe en él, se volverá a desvincular y creará otra copia. El programa P seguirá viendo el archivo original y podrá leerlo o escribirlo libremente. Tan pronto como el programa cierre el archivo, el archivo desaparecerá (el sistema de archivos lo liberará).

ludvik02
fuente
2

Tanto su proceso de editor vim como su archivo llevan su

 getpwnam("navid")->pw_uid

propiedad para que también puedas pagar

 :!chmod +w %

y podrías adivinar que alguna vez fue aún más simple

 :!rm %

(que requiere solo + w, el permiso de desvinculación de ut en. y ni siquiera la propiedad) se volvió demasiado frecuente para que alguien teclee, de modo que vim se reprogramó para ofrecer automáticamente y, a pedido, realizar automáticamente tal operación.

Intenta sobrescribir la de tu hermana mayor

 /home/whoopi/.profile

como simples navid y apuestas son tu vim te da tu negativa deseada.

Roman Czyborra
fuente
Gracias @Zanna por la edición del código, aunque me costó un poco de reputación al principiante, aunque merecidamente.
Roman Czyborra
1

Esto no es exactamente una respuesta, pero si realmente desea configurar un archivo para que nadie pueda cambiarlo o eliminarlo, puede hacerlo inmutable.

Normalmente, incluso cuando un archivo es propiedad de root, aún puede eliminar el archivo si tiene permisos de escritura en la carpeta. Pero cuando hace que el archivo sea inmutable, incluso la raíz no puede modificarlo ni eliminarlo.

Para hacer que un archivo sea inmutable (necesita sudo):

sudo chattr +i myFile.txt

Puedes ver esto con lsattr(la letra ien el resultado):

$ lsattr myFile.txt
----i--------e-- myFile.txt

Para volver a normalizar el archivo:

sudo chattr -i myFile.txt

Para aclarar: cuando un archivo es inmutable, no se puede eliminar, renombrar, modificar o incluso enlazar.

Vale la pena leerlo man chattr, porque los archivos pueden tener varios atributos útiles.

También puede encontrar útil la "eliminación restringida". Si se coloca en una carpeta (no un archivo), esto significa que quien crea un archivo dentro de la carpeta puede modificarlo o eliminarlo, pero nadie más lo está (excepto el usuario root). La carpeta /tmptiene este conjunto de banderas. Puedes ver esto con la tbandera en /tmp:

$ ls -l --directory /tmp
drwxrwxrwt 10 root root 4096 Sep  6 09:00 /tmp

Para establecer o eliminar la marca de eliminación restringida en una carpeta:

chmod +t myFolder      # Add the restricted deletion flag.
chmod -t myFolder      # Remove the restricted deletion flag.
Paddy Landau
fuente