Dlaczego mogę zmodyfikować plik tylko do odczytu?

42

Krótkie pytanie:

Dlaczego możemy manipulować plikiem tylko do odczytu w Vimie, używając :+ w+ q+, !nawet nie będąc administratorem?

Długie pytanie:

Mam plik tekstowy (myFile.txt), który jest przeznaczony tylko do odczytu dla wszystkich:

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

Mogę go otworzyć za pomocą Vima bez uprawnień administratora:

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

Modyfikuję go i naciskam: Esc+ :+ w+ q+ Enteri widzę ten komunikat o błędzie:

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

Jak dotąd wszystko ma sens. Ale kiedy naciskam: Esc+ :+ w+ q+ !+ Enter, Vim zapisuje zmiany.

Używam Ubuntu 16.04 i VIM 7.4.

Navid Vafaei
źródło
1
@Zanna Czy jesteś właścicielem katalogu, w którym znajduje się plik?
Rob
Tak, w przeciwnym razie byłby to OGROMNY problem :)
Rob
11
Modyfikowanie i zastępowanie pliku to dwie różne rzeczy o różnych wymaganiach dotyczących uprawnień.
David Schwartz
1
Czasami warto spojrzeć na to . Zasadniczo odpowiada na twoje pytanie i jak słusznie zauważył @DavidSchwartz :Modifying a file and replacing a file are two different things
Panagiotis Tabakis
@PanagiotisTabakis Bardzo miło, że to jest genialne .. chmod, aby plik do odczytu-zapisu i wrócić, jeśli go posiadasz .. UWIELBIAM :)
Rob

Odpowiedzi:

58

Jak już wspomniano w @Rob , możesz to zrobić tylko wtedy, gdy masz dostęp do zapisu do katalogu zawierającego plik. Na przykład próba zrobienia tego samego dla pliku, /etczakończy się niepowodzeniem.

Jeśli chodzi o to, jak vim to robi, usuwa plik i odtwarza go. Aby to przetestować, utworzyłem plik należący do roota:

echo foo | sudo tee fff

Następnie przystąpiłem do edycji pliku vimw sposób opisany, ale dołączając proces, straceaby zobaczyć, co się dzieje:

strace vim fff 2> strace.out

Następnie sprawdziłem strace.outi znalazłem:

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

Tak więc plik został najpierw usunięty ( unlink("fff")), a następnie utworzono nowy plik o tej samej nazwie ( open("fff", O_WRONLY|O_CREAT|O_TRUNC, 0644)) i zapisano w nim modyfikacje ( write(4, "foasdasdao\n", 11)). Jeśli spróbujesz tego w domu, zobaczysz, że po edycji za pomocą vim, plik będzie należeć do ciebie, a nie do rootowania.

Ściśle mówiąc, vimnie edytuje pliku, do którego nie masz uprawnień do zapisu. Usuwa plik z katalogu, do którego masz dostęp do zapisu, a następnie tworzy nowy plik, do którego znowu masz dostęp do zapisu.

terdon
źródło
2
unix.stackexchange.com/questions/36467/...
Gilles 'SO- przestań być zły'
8
@CCJ to operacja zapisu w katalogu, ale nie w pliku, nie. Operacje zapisu na plikach to te, które zmieniają zawartość pliku. Z tego samego powodu tworzenie / usuwanie plików to operacje zapisu w katalogu, ponieważ zmieniasz jego zawartość.
terdon
2
To także niebezpieczna kolejność operacji. Bezpieczniej byłoby zapisać zamiennik na nową nazwę pliku, a następnie użyć rename(2)do zastąpienia starego pliku. Wtedy nie ma okna czasowego, w którym dane nie istnieją na dysku.
Peter Cordes
5
@PeterCordes um, OK. Możesz jednak skierować swoje skargi do programistów vim. Nawet tego nie używam, jestem w obozie emacsa.
terdon
3
@CCJ Usunięcie pliku to operacja zapisu do katalogu go zawierającego, a nie do samego pliku. Jest całkowicie intuicyjne, że jeśli jesteś odpowiedzialny za katalog (tj. Masz do niego dostęp do zapisu), powinieneś być w stanie kontrolować, co jest w nim zawarte, a właścicielowi indywidualnego pliku nie powinno się zezwalać na nadpisywanie cię.
fkraiem
16

Tak długo, jak jesteś właścicielem katalogu nadrzędnego, możesz usunąć lub zastąpić plik bez względu na uprawnienia, ponieważ możesz zmienić zawartość katalogu :).

Spróbuj użyć innej komendy, takiej jak rm, wyświetli się monit, ale nadal możesz to zrobić. Niech katalog nie będzie zapisywalny i to powinno go zatrzymać.

Dodanie:

Właśnie go wypróbowałem, ale dopóki jestem właścicielem pliku, nadal mogę go modyfikować, nawet z folderem tylko do odczytu. Jednak po zmianie właściciela na root: root nie można otworzyć pliku do zapisu. Rozwiązuje więc modyfikowanie plików należących do roota (lub kogoś innego)

Obrabować
źródło
7
Wygląda na to, że VIM wybiera spośród wielu strategii, w tym przepisuje na miejscu lub rozłącza + napisz nowy plik.
Peter Cordes,
3
@PeterCordes Tak Najwyraźniej będzie bardzo starał się robić to, co mu powiesz :) bardzo przebiegły. :)
Rob
16

Za pomocą w!usuwasz oryginalny plik ( co możesz robić ) i piszesz wersję.

Gdy masz dostęp do zapisu do katalogu, możesz: tworzyć, przenosić lub usuwać pliki w tym katalogu.

$ 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

Teraz pozwól mi zmienić mojego użytkownika i zmienić plik

$ 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

Teraz zobacz, co tam jest:

$ cat foo/file
bye
Ravexina
źródło
10

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

Ponieważ masz uprawnienia do zapisu w katalogu (co oznacza, że ​​możesz w nim tworzyć, usuwać lub zmieniać nazwy plików), system na to zezwala.


Wartość domyślna cpoptionsnie zawiera W:

                                                'cpoptions' 'cpo' cpo
'cpoptions' 'cpo'       string  (Vim default: "aABceFs",
                                 Vi default:  all flags)
                        global
muru
źródło
2

Jest to ostrzeżenie VIM, które może być stosunkowo ważne, biorąc pod uwagę sposób działania uprawnień w systemie UNIX. Pozorna niekonwencjonalność tego wynika z faktu, że systemy plików UNIX mają uprawnienia do pliku przechowywanego w i-węźle pliku. Struktura katalogów jest jakoś osobna i łączy tylko te i-węzły. Katalogi mają również swoje uprawnienia, które mówią, czy można do nich podłączać / odłączać pliki, czy czytać je, czy przechodzić do podkatalogów. Taka konstrukcja pozwala na pojawienie się tego samego pliku w kilku różnych miejscach w strukturze katalogów (poprzez twarde linki). Mówiąc „dodaj! Zastąpić” VIM próbuje ostrzec cię, że oryginalny plik zostanie rozłączony (więc pozostanie nietknięty we wszystkich innych miejscach), a nowy plik zostanie utworzony i połączony z oryginalnym miejscem w strukturze katalogów. W przypadku, gdy liczba linków oryginalnego pliku zmniejszy się do zera, oryginalny plik zostanie zwolniony, ale jeśli nie, skutecznie klonujesz plik. Otwarcie pliku jest również liczone jako link, więc jeśli jakiś program otworzył plik i wyrazisz zgodę na „dodaj! Zastąpić”, program nie zobaczy zmian wprowadzonych do pliku przez Ciebie za pomocą VIM. Plik zostanie odłączony od katalogu tylko przez VIM, a po zamknięciu go przez inny program, plik zostanie zwolniony, chyba że zostanie połączony gdzie indziej.

Należy pamiętać, że w systemie Windows uprawnienia do plików są przechowywane w katalogu, więc z punktu widzenia paradygmatu uprawnień systemu Windows takie zachowanie vima może wyglądać dziwnie. Podczas zapisywania do pliku system Windows logicznie może również sprawdzić niektóre uprawnienia do katalogu, nawet uprawnienia do super-katalogu. Jak wspomniano powyżej, w systemie UNIX uprawnienia do katalogu nie mają znaczenia przy manipulowaniu plikiem, o ile można go było wyświetlić i otworzyć (tzn. Dla wszystkich super-katalogów było x). Plik otwarty w systemie UNIX może nawet nie mieć nazwy, jeśli po otwarciu został odłączony od wszystkich katalogów.

Na przykład, masz plik / home / user1 / foo i jest to ten sam plik, co (tzn. Podłączony do linku) / home / user2 / foo, a plik nie jest zapisywalny przez nikogo i obecnie otwarty przez program P (otwarty do odczytu i zapisu przez program uruchomiony przez root). Jeśli użytkownik1 otworzy go za pomocą vima i nadpisze, tworzy własną kopię i nie widzi już oryginalnego pliku. Jeśli następnie użytkownik2 otworzy swój link za pomocą vima i zapisze się w nim, zostanie on rozłączony ponownie i utworzy kolejną kopię. Program P nadal zobaczy oryginalny plik i może swobodnie w nim czytać lub zapisywać. Gdy tylko program zamknie plik, plik zniknie (zostanie zwolniony przez system plików).

ludvik02
źródło
2

Zarówno proces edytora vim, jak i plik zawierają

 getpwnam("navid")->pw_uid

własność, abyś mógł również wyrzucić

 :!chmod +w %

i możesz się domyślać, że kiedyś jeszcze prostsze

 :!rm %

(wymaganie tylko + w, ut unlink na., a nawet własność) stało się zbyt częste, aby ktoś mógł pisać, więc vim został przeprogramowany, aby automatycznie oferować i na żądanie automatycznie wykonać taką operację.

Spróbuj zastąpić starszą siostrę

 /home/whoopi/.profile

jak zwykłe navid i zakłady są twoje vim daje pożądaną odmowę.

Roman Czyborra
źródło
Dziękuję @Zanna za edycję kodu, mimo że nowicjusz kosztował mnie trochę reputacji, choć zasłużenie.
Roman Czyborra,
1

To nie jest dokładnie odpowiedź, ale jeśli naprawdę chcesz ustawić plik, aby nikt nie mógł go zmienić ani usunąć, możesz uczynić go niezmiennym.

Zwykle nawet jeśli plik należy do katalogu głównego, nadal możesz go usunąć, jeśli masz uprawnienia do zapisu w folderze. Ale kiedy uczynisz plik niezmiennym, nawet root nie będzie mógł go modyfikować ani usuwać.

Aby plik był niezmienny (potrzebujesz sudo):

sudo chattr +i myFile.txt

Możesz to zobaczyć za pomocą lsattr(litery iw wyniku):

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

Aby przywrócić normalny plik:

sudo chattr -i myFile.txt

Wyjaśnienie: Gdy plik jest niezmienny, nie można go usunąć, zmienić jego nazwy, zmodyfikować, a nawet połączyć na stałe.

Warto przeczytać man chattr, ponieważ pliki mogą mieć wiele przydatnych atrybutów.

Przydatne może być również „ograniczone usuwanie”. Jeśli zostanie umieszczony w folderze (nie pliku), oznacza to, że ktokolwiek tworzy plik w folderze, może modyfikować lub usuwać ten plik, ale nikt inny nie jest (z wyjątkiem root). Folder /tmpma ustawioną tę flagę. Możesz to zobaczyć z tflagą na /tmp:

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

Aby ustawić lub usunąć flagę ograniczonego usuwania w folderze:

chmod +t myFolder      # Add the restricted deletion flag.
chmod -t myFolder      # Remove the restricted deletion flag.
Paddy Landau
źródło