Vi может записывать в файл, несмотря на то, что файл доступен только для чтения

12

В следующем примере показано, как создать файл только с разрешениями на чтение. Как мы можем видеть, когда я пытаюсь записать в этот файл , используя команду эха я получаю, Permission denied.

Но почему, если мы используем vi, мы не получаем Permission denied? Как можно видеть здесь, мы можем записать в файл, даже если файл доступен только для чтения.

Что здесь происходит? Это ошибка ви?

[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
источник
1
К вашему сведению, для этого есть бета-версия SE - vi.stackexchange.com
Raystafarian

Ответы:

28

Примечание . Из-за устаревших причин лицензирования большинство дистрибутивов GNU / Linux не содержат оригинальную программу vi, написанную Биллом Джой. Вместо этого команда vi предоставляется при запуске Vim в режиме совместимости с vi. Следующий ответ основан на запуске Vim с его режимом совместимости с vi.

Изменение файла только для чтения

Вим предупреждает пользователя , если они изменяют буфер файла только для чтения, W10: Warning: Changing a readonly file. Если пользователь пытается записать в этот файл, он получает следующее сообщение об ошибке 'readonly' option is set (add ! to override).

Когда родительский каталог доступен для записи пользователем Vim

Vim, будучи полезным, позволяет пользователю знать, что он может настаивать на написании, добавляя восклицательный знак !в wкоманду. Если используется эта принудительная версия команды записи, Vim удаляет исходный файл (если при использовании Vim с установленной backupопцией Vim-only исходный файл фактически переименовывается, чтобы совпадать с файлом резервной копии). Затем он открывает (создает) новый файл с тем же именем, что и оригинал, и записывает содержимое своего буфера в этот новый файл. Это можно увидеть, проверив inode файла до и после запуска Vim:

$ 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системный вызов), записав буфер в файл, закрыв файл и изменив разрешения назад. Вот выдержка из системных вызовов, выполняемых при запуске vi через 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

Примечание. Этого не происходит, если пользователь Vim редактирует файл, владельцем которого он не является, поскольку Vim не сможет изменить права доступа к файлу.

добавление

Чтобы быть уверенным, что файл не может быть изменен (в системе GNU / Linux), запустите chattrкоманду как суперпользователь:

sudo chattr +i filename

От man chattr:

Файл с атрибутом «i» не может быть изменен: его нельзя удалить или переименовать, невозможно создать ссылку на этот файл и данные не могут быть записаны в файл. Только суперпользователь или процесс, обладающий возможностью CAP_LINUX_IMMUTABLE, может установить или очистить этот атрибут.

Энтони Геогеган
источник
2
Святой дым, это было основательно!
Камиль Гудесюн
4
@CamilleGoudeseune После того, как я опубликовал первую версию своего ответа, я провел несколько экспериментов и потратил около часа на то, чтобы запустить Vim через strace, чтобы увидеть, что он делает за кулисами в разных ситуациях (разные сочетания прав доступа и владельца файла и родительский каталог). Я иногда увлекаюсь, но как только я опубликовал ответ, я хотел быть уверен, что то, что я говорил, было правильным.
Энтони Геогеган
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
....

В этом случае номер индекса не изменяется.

Наконец, это не ошибка, так как если вам не разрешено изменять права доступа к файлу, вы не можете изменить его vi.

jlliagre
источник
Хах! После того, как я опубликовал свой ответ, я провел несколько экспериментов и потратил около часа на то, чтобы запустить Vim через strace, чтобы посмотреть, что он делает за кулисами в разных ситуациях (разные сочетания прав доступа и владения как файловым, так и родительским каталогом). Я только увидел ваш ответ после того, как закончил обобщать результаты своих экспериментов. Это был хороший учебный опыт.
Энтони Геогеган