Mengapa saya bisa memodifikasi file read-only?

42

Pertanyaan pendek:

Mengapa kita dapat memanipulasi file read-only di Vim menggunakan :+ w+ q+ !bahkan tanpa menjadi administrator?

Pertanyaan panjang:

Saya memiliki file teks (myFile.txt) yang hanya-baca untuk semua orang:

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

Saya bisa membukanya dengan Vim tanpa memiliki hak admin:

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

Saya memodifikasinya dan tekan: Esc+ :+ w+ q+ Enterdan saya melihat pesan kesalahan ini:

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

Sejauh ini, semuanya masuk akal. Tetapi ketika saya menekan: Esc+ :+ w+ q+ !+ Enter, Vim menyimpan perubahan.

Saya menggunakan Ubuntu 16.04 dan VIM 7.4.

Navid Vafaei
sumber
1
@Zanna Apakah Anda memiliki direktori tempat file itu berada?
Rob
Ya ini akan menjadi masalah BESAR kalau tidak :)
Rob
11
Memodifikasi file dan mengganti file adalah dua hal yang berbeda dengan persyaratan izin yang berbeda.
David Schwartz
1
Anda mungkin ingin kita lihat ini . Hal ini pada dasarnya menjawab pertanyaan Anda dan sebagai @DavidSchwartz benar menunjukkan :Modifying a file and replacing a file are two different things
Panagiotis Tabakis
@PanagiotisTabakis Sangat bagus menemukan ini brilian .. chmod untuk membuat file baca-tulis dan kembali lagi jika Anda memilikinya .. LOVE IT :)
Rob

Jawaban:

58

Seperti yang telah disebutkan @Rob , Anda hanya dapat melakukan ini jika Anda memiliki akses tulis ke direktori yang berisi file. Mencoba melakukan hal yang sama ke file di, misalnya, /etcakan gagal.

Adapun bagaimana vim melakukan ini, ia menghapus file dan membuatnya kembali. Untuk menguji ini, saya membuat file yang dimiliki oleh root:

echo foo | sudo tee fff

Dan kemudian melanjutkan untuk mengedit file dengan vimcara yang Anda gambarkan, tetapi lampirkan proses straceuntuk melihat apa yang terjadi:

strace vim fff 2> strace.out

Saya kemudian memeriksa strace.outdan menemukan:

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

Jadi, file itu pertama kali dihapus ( unlink("fff")), kemudian file baru dengan nama yang sama dibuat ( open("fff", O_WRONLY|O_CREAT|O_TRUNC, 0644)) dan modifikasi yang saya buat ditulis untuk itu ( write(4, "foasdasdao\n", 11)). Jika Anda mencoba ini di rumah, Anda akan melihat bahwa setelah Anda mengeditnya vim, file sekarang akan menjadi milik Anda dan bukan root.

Jadi, sebenarnya, vimbukan mengedit file yang Anda tidak memiliki akses tulis. Itu menghapus file dari direktori di mana Anda memiliki akses tulis dan kemudian membuat file baru yang, sekali lagi, Anda memiliki akses tulis.

terdon
sumber
2
unix.stackexchange.com/questions/36467/...
Gilles 'SO- stop being evil'
8
@ CCJ ini adalah operasi tulis pada direktori tetapi tidak pada file, tidak. Operasi tulis pada file adalah operasi yang mengubah konten file. Dengan cara yang sama, membuat / menghapus file adalah operasi tulis pada direktori karena Anda mengubah isinya.
terdon
2
Juga, itu urutan operasi yang berbahaya. Akan lebih aman untuk menulis penggantian ke nama file baru dan kemudian gunakan rename(2)untuk mengganti file lama. Maka tidak ada jendela waktu di mana data Anda tidak ada pada disk.
Peter Cordes
5
@PeterCordes um, oke. Anda mungkin ingin mengarahkan keluhan Anda ke pengembang vim. Saya bahkan tidak menggunakan benda itu, saya di kamp emacs.
terdon
3
@ CCJ Menghapus file adalah operasi tulis ke direktori yang berisi itu, bukan ke file itu sendiri. Sangat intuitif bahwa jika Anda bertanggung jawab atas sebuah direktori (yaitu, memiliki akses tulis ke sana), Anda harus dapat mengontrol apa yang ada di dalamnya, dan pemilik file individual tidak boleh diizinkan untuk menimpa Anda.
fkraiem
16

Selama Anda memiliki direktori induk, Anda dapat menghapus, atau mengganti file, apa pun izinnya karena Anda dapat mengubah konten direktori :).

Cobalah dengan perintah lain seperti rm, itu akan meminta Anda tetapi Anda masih bisa melakukannya. Buat direktori tidak dapat ditulisi dan itu harus menghentikannya.

Tambahan:

Hanya mencobanya tetapi selama saya memiliki file saya masih dapat memodifikasinya, bahkan dengan folder hanya baca. Namun ketika saya mengubah kepemilikan menjadi root: root tidak dapat membuka file untuk ditulis. Jadi, selesaikan memodifikasi file yang dimiliki oleh root (atau orang lain)

rampok
sumber
7
Sepertinya VIM memilih dari beberapa strategi, termasuk menulis ulang di tempat atau menghapus tautan + menulis file baru.
Peter Cordes
3
@PeterCordes Ya Tampaknya akan berusaha sangat keras untuk melakukan apa yang Anda katakan :) sangat licik. :)
Rob
16

Menggunakan w!Anda menghapus file asli ( yang diizinkan untuk Anda lakukan ) dan menulis versi Anda.

Ketika Anda memiliki akses tulis ke direktori, Anda dapat: membuat, memindahkan, atau menghapus file di dalam direktori itu.

$ 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

Sekarang izinkan saya beralih pengguna saya dan ubah file

$ 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

Sekarang lihat apa yang ada di sana:

$ cat foo/file
bye
Ravexina
sumber
10

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

Karena Anda memiliki izin menulis pada direktori (artinya Anda dapat membuat, menghapus, atau mengganti nama file di dalamnya), sistem mengizinkannya.


Nilai default dari cpoptionstidak mengandung W:

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

Ini adalah peringatan VIM untuk Anda yang mungkin relatif penting mengingat cara kerja izin di UNIX. Ketidaktepatan yang terlihat dari ini adalah karena sistem file UNIX memiliki izin untuk file yang disimpan dalam i-node file. Struktur direktori entah bagaimana terpisah dan hanya menghubungkan simpul-simpul ini. Direktori juga memiliki izin yang menyatakan apakah Anda dapat menautkan / membatalkan tautan file ke dalamnya, atau membacanya atau melintasi sub-direktori. Desain ini memungkinkan file yang sama dapat muncul di beberapa tempat berbeda dalam struktur direktori (melalui tautan keras). Dengan mengatakan "tambahkan! Untuk menimpa" VIM berusaha memperingatkan Anda bahwa file asli akan dibatalkan tautannya (sehingga akan tetap di semua tempat lain yang tidak tersentuh) dan file baru akan dibuat dan ditautkan ke tempat asli dalam struktur direktori. Jika jumlah tautan dari file asli berkurang menjadi nol, file asli akan dibebaskan, tetapi jika tidak, Anda secara efektif mengkloning file tersebut. Pembukaan file juga dianggap sebagai tautan, jadi jika beberapa program membuka file dan Anda setuju untuk "menambahkan! Untuk menimpa", program tidak akan melihat perubahan yang dilakukan pada file oleh Anda dengan VIM. File hanya akan dibatalkan tautannya dari direktori oleh VIM dan setelah menutup file oleh program lain, file tersebut akan dibebaskan, kecuali jika ditautkan di tempat lain.

Harap dicatat bahwa di Windows, izin untuk file disimpan dalam direktori, jadi dari sudut pandang paradigma izin Windows, perilaku vim ini mungkin memang terlihat aneh. Untuk menulis ke file, Windows secara logis mungkin juga memeriksa beberapa izin direktori, bahkan izin super-direktori. Seperti dikatakan di atas, dalam UNIX, izin direktori tidak relevan untuk manipulasi dengan file sejauh Anda dapat membuat daftar dan membukanya (yaitu ada x untuk semua direktori super). File yang dibuka di UNIX mungkin bahkan tidak memiliki nama file lagi jika itu diputuskan tautannya dari semua direktori setelah dibuka.

Misalnya, Anda memiliki file / home / user1 / foo dan itu adalah file yang sama dengan (yaitu hardlinked to) / home / user2 / foo dan file tidak dapat ditulisi oleh siapa pun dan saat ini dibuka oleh program P (dibuka baca-tulis oleh program dimulai oleh root). Jika user1 membukanya dengan vim dan menimpa, ia membuat salinan sendiri dan tidak lagi melihat file asli. Jika kemudian user2 membuka tautannya dengan vim dan menulis ke dalamnya, tautan itu akan dibatalkan tautannya lagi dan ia akan membuat salinan lain. Program P masih akan melihat file asli dan dapat dengan bebas membaca atau menulis di dalamnya. Segera setelah program menutup file, file tersebut akan hilang (dibebaskan oleh filesystem).

ludvik02
sumber
2

Baik editor vim Anda dan file Anda membawa

 getpwnam("navid")->pw_uid

kepemilikan sehingga Anda juga bisa keluar

 :!chmod +w %

dan Anda mungkin menebak bahwa pada suatu waktu bahkan lebih sederhana

 :!rm %

(hanya membutuhkan + w, ut unlink izin pada. dan bahkan kepemilikan) menjadi terlalu sering bagi seseorang untuk mengetik sehingga vim diprogram ulang untuk secara otomatis menawarkan dan berdasarkan permintaan secara otomatis melakukan operasi seperti itu.

Cobalah menimpa kakakmu

 /home/whoopi/.profile

sebagai navid belaka dan taruhan adalah vim Anda memberi Anda penolakan yang Anda inginkan.

Roman Czyborra
sumber
Terima kasih @Zanna untuk pengeditan kode meskipun saya baru sedikit reputasi, sepatutnya.
Roman Czyborra
1

Ini bukan jawaban yang tepat, tetapi jika Anda benar-benar ingin mengatur file sehingga tidak ada yang dapat mengubah atau menghapusnya, Anda dapat membuatnya tidak berubah.

Biasanya, bahkan ketika file dimiliki oleh root, Anda masih dapat menghapus file jika Anda memiliki izin menulis ke folder. Tetapi ketika Anda membuat file tidak dapat diubah, bahkan root tidak dapat memodifikasi atau menghapusnya.

Untuk membuat file tidak berubah (Anda perlu sudo):

sudo chattr +i myFile.txt

Anda dapat melihat ini dengan lsattr(huruf idi hasil):

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

Untuk membuat file kembali normal:

sudo chattr -i myFile.txt

Untuk memperjelas: Ketika suatu file tidak dapat diubah, itu tidak dapat dihapus, diganti namanya, dimodifikasi, atau bahkan dihubungkan dengan keras.

Ini layak dibaca man chattr, karena file dapat memiliki sejumlah atribut yang bermanfaat.

Anda mungkin juga menemukan "penghapusan terbatas" berguna. Jika ditempatkan pada folder (bukan file), ini berarti bahwa siapa pun yang membuat file di dalam folder diizinkan untuk memodifikasi atau menghapus file itu, tetapi tidak ada orang lain (kecuali root). Folder /tmpmemiliki set bendera ini. Anda dapat melihat ini dengan tbendera di /tmp:

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

Untuk mengatur atau menghapus bendera penghapusan terbatas pada folder:

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