ファイルが読み取り専用であっても、Viはファイルに書き込むことができます


12

次の例は、読み取り権限のみを持つファイルを作成する方法を示しています。ご覧のとおり、エコーコマンドを使用してこのファイルに書き込もうとすると、が表示されますPermission denied

しかし、なぜviを使用する場合、取得しないのですPermission deniedか?ここに見られるように、ファイルが読み取り専用であってもファイルに書き込むことができます。

ここで何が起きてるの?これは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

回答:


28

:レガシーライセンスの理由により、ほとんどのGNU / Linuxディストリビューションには、Bill Joyによって書かれたオリジナルのviプログラムが含まれていません。代わりに、viコマンドは、vi-compatibilityモードでVimを実行することにより提供されます。次の回答は、vi互換モードでVimを実行することに基づいています。

読み取り専用ファイルの変更

Vimは、読み取り専用ファイルのバッファーを変更すると、ユーザーに警告しますW10: Warning: Changing a readonly file。ユーザーがこのファイルへの書き込みを試みると、次のエラーメッセージが表示されます'readonly' option is set (add ! to override)

親ディレクトリがVimユーザーによって書き込み可能な場合

Vimは、有用であること、彼らは強制的に、感嘆符を付加することにより、書き込みを主張することができ、ユーザを知ることができます!wコマンドを。書き込みコマンドのこの強制バージョンが使用される場合、Vimは元のファイルを削除します(Vimのみのbackupオプションが設定されたVimを使用する場合、元のファイルは実際バックアップファイルと同じ名前変更されます)。次に、元のファイル同じ名前の新しいファイルを開き(作成し)、その新しいファイルにバッファーの内容を書き込みます。これは、Vimを実行する前後にファイルのiノードをチェックすることで確認できます。

$ 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

注:これにより、ファイルの許可と所有権が変更され、リンクが解除されます(たとえば、元のファイルが別のユーザーによって所有されている場合、新しいファイルはVimを実行しているユーザーによって所有されます)。

プロセスは、ファイルの親ディレクトリへの書き込み権限がある場合にのみこれを行うことができます。一般に、プログラムがファイルを変更できないようにするには、ファイル自体とその親ディレクトリの両方のアクセス許可を保護する必要があります。

Vimユーザーが親ディレクトリに書き込みできない場合

ただし、この場合でも、Vimは引き続き、頑固なユーザーがファイルを上書きできるように最善を尽くします。Vimユーザーがファイルの所有権を持っている場合、Vimは一時的にファイルのパーミッションを変更し(chmodシステムコールを使用)、バッファーをファイルに書き込み、ファイルを閉じてから、許可を戻します。以下は、straceを使用してviを実行中に行われたシステムコールの抜粋です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

注:Vimはファイルのアクセス許可を変更できないため、Vimユーザーが所有権のないファイルを編集している場合、これは発生しません。

補遺

(GNU / Linuxシステムで)ファイルを変更できないことを本当に確認するにはchattr、スーパーユーザーとしてコマンドを実行します。

sudo chattr +i filename

からman chattr

「i」属性を持つファイルは変更できません。削除または名前の変更はできません。このファイルへのリンクは作成できず、ファイルにデータを書き込むこともできません。この属性を設定またはクリアできるのは、スーパーユーザーまたはCAP_LINUX_IMMUTABLE機能を持つプロセスのみです。


2
聖なる煙、それは徹底的でした!
カミーユグースヌ

4
@CamilleGoudeseune回答の最初のバージョンを投稿した後、いくつかの実験を行い、Vimをstraceで実行して約1時間を費やし、さまざまな状況(ファイルと親ディレクトリ)。私は時々夢中になりますが、答えを公開したら、私が言っていたことが正しいことを確認したかったのです。
アンソニージョ

5

ほとんどすべてではないvi実装はあなたがいずれかのようなコマンドの保存通常の使用している場合は、ファイルを書き込むことができなくZZ:w:wqまたは:xで、例えばvim

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

一方、またはのviようなものを使用して、アクセス許可にもかかわらずファイルを書き込むように指示すると、エディターは一時的にアクセス許可を緩和してファイルの書き込みを許可します。:x!:wq!

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

その場合、iノード番号は変更されません。

最後に、これはバグではありません。ファイルのアクセス許可を変更することは許可されていないため、で変更することはできませんvi


ハァッ!回答を投稿した後、いくつかの実験を行い、Vimをstraceで実行するのに1時間近く費やし、さまざまな状況(ファイルと親ディレクトリの両方のアクセス許可と所有権の異なる順列)で舞台裏で何をしているかを確認しました。私の実験結果のまとめが終わってから、あなたの答えを見ました。良い学習体験でした。
アンソニージョゲガン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.