Vi może zapisywać do pliku, mimo że plik jest tylko do odczytu

12

Poniższy przykład pokazuje, jak utworzyć plik z tylko uprawnieniami do odczytu. Jak widać, przy próbie zapisu do tego pliku za pomocą polecenia echo I get Permission denied.

Ale dlaczego, w przypadku, gdy używamy vi, nie otrzymujemy Permission denied? Jak widać tutaj, możemy zapisać do pliku, nawet jeśli plik jest tylko do odczytu.

Co tu się dzieje? Czy to błąd 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
źródło
1
Do Twojej dyspozycji jest strona beta SE - vi.stackexchange.com
Raystafarian

Odpowiedzi:

28

Uwaga : Ze względu na starsze licencje większość dystrybucji GNU / Linux nie zawiera oryginalnego programu vi, napisanego przez Billa Joya. Zamiast tego polecenie vi jest uruchamiane przez uruchomienie Vima w trybie zgodności vi. Poniższa odpowiedź oparta jest na uruchomieniu Vima w trybie zgodności z vi.

Modyfikowanie pliku tylko do odczytu

Vim ostrzega użytkownika, jeśli one modyfikować bufor pliku tylko do odczytu, W10: Warning: Changing a readonly file. Jeśli użytkownik próbuje pisać do tego pliku, ale pojawia się następujący komunikat o błędzie 'readonly' option is set (add ! to override).

Gdy katalog nadrzędny jest zapisywalny przez użytkownika Vima

Vim, będąc pomocnym, informuje użytkownika, że ​​może zdecydowanie nalegać na pisanie, dodając wykrzyknik !do wpolecenia. Jeśli używana jest ta wymuszona wersja polecenia zapisu, Vim usuwa oryginalny plik (jeśli używa Vima z backupzestawem opcji tylko dla Vima , nazwa oryginalnego pliku jest faktycznie zmieniana na taką samą jak plik kopii zapasowej). Następnie otwiera (tworzy) nowy plik o tej samej nazwie co oryginał i zapisuje zawartość bufora w tym nowym pliku. Można to zaobserwować sprawdzając i- węzeł pliku przed i po uruchomieniu Vima:

$ 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

Uwaga: może to również zmienić uprawnienia i własność pliku oraz zerwać (symboliczne) łącza, np. Jeśli oryginalny plik był własnością innego użytkownika, nowy plik byłby własnością użytkownika uruchamiającego Vima.

Proces może to zrobić tylko wtedy, gdy ma uprawnienia do zapisu dla katalogu nadrzędnego pliku. Zasadniczo, aby upewnić się, że program nie może zmodyfikować pliku, należy zabezpieczyć uprawnienia zarówno do samego pliku, jak i jego katalogu nadrzędnego.

Gdy katalog nadrzędny nie jest zapisywalny przez użytkownika Vima

Jednak nawet w tym przypadku Vim nadal dokłada wszelkich starań, aby uporczywy użytkownik nadpisał plik. Jeśli użytkownik Vima jest właścicielem pliku, Vim może obejść ograniczenie katalogu nadrzędnego tylko do odczytu, tymczasowo zmieniając uprawnienia do pliku (za pomocą chmodwywołania systemowego), zapisując bufor do pliku, zamykając plik, a następnie zmieniając uprawnienia z powrotem. Oto fragment wywołań systemowych wykonanych podczas uruchamiania vi przez 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

Uwaga: Nie dzieje się tak, jeśli użytkownik Vima edytuje plik, do którego nie ma prawa własności, ponieważ Vim nie będzie mógł zmienić uprawnień do pliku.

Uzupełnienie

Aby mieć pewność, że pliku nie można zmodyfikować (w systemie GNU / Linux), uruchom chattrkomendę jako administrator:

sudo chattr +i filename

Od man chattr:

Pliku z atrybutem „i” nie można modyfikować: nie można go usunąć ani zmienić jego nazwy, nie można utworzyć łącza do tego pliku i nie można zapisać danych w pliku. Tylko superużytkownik lub proces posiadający zdolność CAP_LINUX_IMMUTABLE może ustawić lub usunąć ten atrybut.

Anthony Geoghegan
źródło
2
Święty dymu, to było dokładne!
Camille Goudeseune,
4
@CamilleGoudeseune Po opublikowaniu pierwszej wersji mojej odpowiedzi przeprowadziłem kilka eksperymentów i spędziłem około godziny na bieganiu Vimem, aby zobaczyć, co robi za kulisami w różnych sytuacjach (różne permutacje uprawnień i własności zarówno pliku, jak i nadrzędna Lokalizacja). Czasem daję się ponieść emocjom, ale kiedy opublikowałem odpowiedź, chciałem mieć pewność, że to, co mówię, jest prawidłowe.
Anthony Geoghegan
5

Większość, jeśli nie wszystkie viimplementacje uniemożliwić napisać plik, jeśli używasz polecenia Zapisz regularny jak bądź ZZ, :w, :wqlub :x, na przykład z vim:

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

Z drugiej strony, jeśli każesz vinapisać plik pomimo jego uprawnień, używając czegoś takiego jak :x!lub :wq!, edytor tymczasowo rozluźnia uprawnienia, aby umożliwić zapisanie pliku:

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

W takim przypadku numer i-węzła pozostaje niezmieniony.

Wreszcie, nie jest to błąd, ponieważ jeśli nie możesz zmieniać uprawnień do plików, nie możesz go modyfikować vi.

jlliagre
źródło
Hah! Po opublikowaniu mojej odpowiedzi przeprowadziłem kilka eksperymentów i spędziłem prawie godzinę na uruchomieniu Vima przez strace, aby zobaczyć, co robi za kulisami w różnych sytuacjach (różne permutacje uprawnień i własności zarówno pliku, jak i katalogu macierzystego). Dopiero zobaczyłem twoją odpowiedź po tym, jak skończyłem podsumowywać wyniki moich eksperymentów. To było dobre doświadczenie edukacyjne.
Anthony Geoghegan,