Vi kann in eine Datei schreiben, obwohl diese schreibgeschützt ist

12

Das folgende Beispiel zeigt, wie eine Datei nur mit Leseberechtigungen erstellt wird. Wie wir sehen können, wenn ich versuche , auf diese Datei mit dem Befehl echo I, erhalten zu schreiben Permission denied.

Aber warum bekommen wir in dem Fall, dass wir vi benutzen, nichtPermission denied ? Wie hier zu sehen ist, können wir in die Datei schreiben, obwohl die Datei schreibgeschützt ist.

Was passiert hier? Ist das ein vi Bug?

[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
quelle
1
Zu Ihrer
Information

Antworten:

28

Hinweis : Aus Gründen der älteren Lizenzierung enthalten die meisten GNU / Linux-Distributionen nicht das ursprüngliche vi-Programm, wie es von Bill Joy geschrieben wurde. Stattdessen wird der Befehl vi bereitgestellt, indem Vim im Vi-Kompatibilitätsmodus ausgeführt wird. Die folgende Antwort basiert auf dem Ausführen von Vim mit seinem Vi-Kompatibilitätsmodus.

Ändern einer schreibgeschützten Datei

Vim warnt den Benutzer, wenn er den Puffer einer schreibgeschützten Datei ändert W10: Warning: Changing a readonly file. Wenn der Benutzer versucht , auf diese Datei zu schreiben, erhalten sie die folgende Fehlermeldung, 'readonly' option is set (add ! to override).

Wenn das übergeordnete Verzeichnis vom Vim-Benutzer beschrieben werden kann

Da Vim hilfreich ist, weist er den Benutzer darauf hin, dass er mit Nachdruck auf dem Schreiben bestehen kann, indem er ein Ausrufezeichen anfügt. ! an den wBefehl angehängt wird. Wenn diese erzwungene Version des Schreibbefehls verwendet wird, löscht Vim die Originaldatei (wenn Vim mit der backupOption Nur Vim verwendet wird , wird die Originaldatei tatsächlich so umbenannt , dass sie mit der Sicherungsdatei identisch ist). Anschließend wird eine neue Datei mit demselben Namen wie das Original geöffnet (erstellt) und der Inhalt des Puffers in diese neue Datei geschrieben. Dies kann beobachtet werden, indem der Inode der Datei vor und nach dem Ausführen von Vim überprüft wird :

$ 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

Hinweis: Dies kann auch die Berechtigung und den Besitz der Datei ändern und (symbolische) Links unterbrechen. Wenn z. B. die ursprüngliche Datei einem anderen Benutzer gehört, gehört die neue Datei dem Benutzer, der Vim ausführt.

Ein Prozess kann dies nur tun, wenn er über Schreibrechte für das übergeordnete Verzeichnis der Datei verfügt. Um sicherzustellen, dass ein Programm eine Datei nicht ändern kann, sollten im Allgemeinen die Berechtigungen sowohl für die Datei selbst als auch für das übergeordnete Verzeichnis gesichert werden.

Wenn das übergeordnete Verzeichnis vom Vim-Benutzer nicht beschreibbar ist

Selbst in diesem Fall versucht Vim dem Benutzer zu helfen, die Datei zu überschreiben. Wenn der Vim-Benutzer Eigentümer der Datei ist, kann Vim die Einschränkung des schreibgeschützten übergeordneten Verzeichnisses umgehen, indem er vorübergehend die Berechtigung der Datei ändert (mithilfe des chmodSystemaufrufs), den Puffer in die Datei schreibt, die Datei schließt und dann die Datei ändert Berechtigungen zurück. Hier ist ein Auszug der Systemaufrufe, die ausgeführt werden, während vi durch strace läuft 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

Hinweis: Dies ist nicht der Fall, wenn der Vim-Benutzer eine Datei bearbeitet, deren Eigentümer er nicht ist, da Vim die Dateiberechtigungen nicht ändern kann.

Nachtrag

Um wirklich sicher zu sein, dass eine Datei nicht geändert werden kann (auf einem GNU / Linux-System), führen Sie die aus chattr Befehl als Superuser aus:

sudo chattr +i filename

Von man chattr:

Eine Datei mit dem Attribut 'i' kann nicht geändert werden: Sie kann nicht gelöscht oder umbenannt werden, es kann kein Link zu dieser Datei erstellt werden und es können keine Daten in die Datei geschrieben werden. Nur der Superuser oder ein Prozess mit der Funktion CAP_LINUX_IMMUTABLE kann dieses Attribut festlegen oder löschen.

Anthony Geoghegan
quelle
2
Heiliger Rauch, das war gründlich!
Camille Goudeseune
4
@CamilleGoudeseune Nachdem ich die erste Version meiner Antwort gepostet hatte, führte ich einige Experimente durch und verbrachte am Ende ungefähr eine Stunde damit, Vim durch die Straßen zu führen, um zu sehen, was es hinter den Kulissen in verschiedenen Situationen tat (unterschiedliche Permutationen der Berechtigungen und des Eigentums an beiden Dateien und übergeordnetes Verzeichnis). Ich werde manchmal mitgerissen, aber nachdem ich eine Antwort veröffentlicht hatte, wollte ich sicher sein, dass das, was ich sagte, richtig war.
Anthony Geoghegan
5

Die meisten , wenn nicht alle viImplementierungen verhindern , dass Sie die Datei zu schreiben , wenn Sie regelmäßig wie entweder speichern Befehl verwenden ZZ, :w, :wqoder :x, zB mit vim:

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

Wenn Sie andererseits festlegen vi, dass die Datei trotz der Berechtigungen geschrieben werden soll, und Sie etwas wie :x!oder verwenden :wq!, werden die Berechtigungen für das Schreiben der Datei vorübergehend vom Editor gelockert:

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

In diesem Fall bleibt die Inode-Nummer unverändert.

Schließlich ist dies kein Fehler, da Sie die Dateiberechtigungen nicht ändern dürfen, sondern nicht durch vi.

jlliagre
quelle
Hah! Nachdem ich meine Antwort gepostet hatte, führte ich einige Experimente durch und verbrachte fast eine Stunde damit, Vim durchzuarbeiten, um zu sehen, was hinter den Kulissen in verschiedenen Situationen geschah (unterschiedliche Permutationen von Berechtigungen und Besitz von Datei und übergeordnetem Verzeichnis). Ich habe Ihre Antwort erst gesehen, nachdem ich die Ergebnisse meiner Experimente zusammengefasst hatte. Es war eine gute Lernerfahrung.
Anthony Geoghegan