Vim kann Dateiberechtigungen brechen?

8

Ich habe neulich wie immer Vim benutzt, als ich etwas Seltsames bemerkte. Folgendes habe ich getan:

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

Dann nahm ich eine Änderung vor und speicherte und beendete mit :wq. Ziemlich normal. Dann jedoch:

~$ 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

Root sollte also R / W-Zugriff haben und alle anderen sollten nur gelesen haben. Bearbeiten Sie die Datei, versuchen Sie zu speichern - Sie können nicht. Genial, wie vorgesehen zu arbeiten. Wenn Sie jedoch mit speichern :w!, ändert vim den Dateieigentum irgendwie wieder in Benutzername: Benutzergruppe und die Datei wird gespeichert. Auch wenn Sie dies tun:

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

Sie können immer noch mit überschreiben :w!! Was ist los? Wie kann vim die Gesetze des Dateieigentums und der Erlaubnis wie diese brechen? Ich habe mir die Hilfeseite in vim angesehen :help :wund Folgendes gefunden:

: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.

Ich konnte vorher nicht in eine Datei in vim schreiben, wenn ich es nicht sollte. Ich denke, das eigentliche Herz meiner Frage ist, wie ich eine Datei von vim nicht editierbar machen kann und warum sie nicht auf einer Datei basiert Systemberechtigungen, wie ich es erwarten würde, und welchen Mechanismus verwendet vim, um die Datei zu bearbeiten, die andere Editoren (gedit, nano) nicht verwenden können?

BEARBEITEN: Der Computer, auf dem ich dies ausprobiert habe, verwendet den Linux-Kernel 3.15.5-2-ARCH. Die Versionsnummer von Vim lautet 7.4.373-1 und ist die von pacman- Ich habe sie nicht mit speziellen Optionen von Grund auf neu kompiliert.

zrneely
quelle
Ich scheine nicht in der Lage zu sein, das Problem zu reproduzieren, es sei denn, ich nehme einige Tricks wie hier
Davyzhu
Ich habe es einfach noch einmal mit den Befehlen in der Frage versucht, und es ist auf die gleiche Weise passiert. Ich werde die Frage bearbeiten, um Details zu meinem Computer hinzuzufügen, da dies möglicherweise plattformabhängig ist.
Zrneely
Meine erste Vermutung ist, dass Sie den Besitz von Dateien in einem Verzeichnis ändern dürfen, auf das Sie Schreibzugriff haben. Aber das scheint nicht der Fall zu sein . CAP_CHOWNist erforderlich, um anzurufen chown(2). Übrigens kann ich mit vim 7.4 auf Debian reproduzieren.
Bob

Antworten:

10

Ich kann sehen, dass Ihr aktueller Pfad ~das Home-Verzeichnis Ihres Benutzers ist. Sie sollten über Schreibberechtigungen für dieses Verzeichnis verfügen.

Stellen Sie sich das anders vor: Wenn Sie Lese- und Schreibberechtigungen für das Verzeichnis haben, was hindert Sie daran, die Datei zu kopieren, die alte zu löschen und die neue mit anderen Berechtigungen umzubenennen?

Genau das macht vim!


Wenn Sie vim unter Strace laufen lassen, zum Beispiel:

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

Basierend auf diesem Protokoll kann ich den folgenden Prozess erraten:

Einige frühere Berechtigungsprüfungen (und chownVersuche usw.) sind der Kürze halber weggelassen.

  1. open Versuch, die Datei zum Schreiben zu öffnen (fehlgeschlagen: Berechtigung verweigert)
  2. lstat Überprüfen Sie den Eigentümer der Datei
  3. getuuid Überprüfen Sie die aktuelle Benutzer-ID, um festzustellen, ob sie mit dem Dateieigentümer übereinstimmt
  4. unlink Löschen Sie die Datei (dies ist zulässig, da die Schreibberechtigung für das Verzeichnis vorliegt).
  5. open Erstellen Sie eine neue Datei mit demselben Namen
  6. write Der Dateiinhalt (früher gelesen, ich habe etwas Kauderwelsch eingegeben)
  7. fsync Leeren Sie die Datei auf die Festplatte (nicht wirklich wichtig)
  8. close
  9. chmod Ändern Sie die Berechtigungen der neuen Datei so, dass sie wie die alte aussehen - sie hat gerade einen neuen Besitzer.
Bob
quelle
OK danke. Ich bin froh, dass ich das herausgefunden habe. Wenn ich also keine Schreibberechtigungen für das Verzeichnis habe, kann ich diese nicht verwenden :w!, was sinnvoll ist.
Zrneely
Außerdem sind die Strace-Informationen sehr praktisch - jetzt habe ich ein weiteres Tool für meine eigenen Untersuchungen in der Zukunft.
Zrneely
1
@zrneely Ein Tipp für strace: Verwenden Sie die -oOption, um eine Ausgabe in eine Datei zu schreiben. Andernfalls kollidiert es mit vimder Ausgabe. Was Schreibberechtigungen betrifft , sehe ich keine Überprüfung der Verzeichnisberechtigungen mit, stataber es wird versucht, eine Datei (benannt 4913, scheint zufällig zu sein) im aktuellen Verzeichnis zu erstellen und sie dann zu löschen.
Bob
Es scheint, als 4913sei es nur der Vorname, den es versucht, und es soll überprüft werden, ob es über genügend Berechtigungen verfügt. Siehe: bugzilla.redhat.com/show_bug.cgi?id=427711#c6 und groups.google.com/forum/#!topic/vim_dev/sppdpElxY44
Bob