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

1
FYI для цього є бета-сайт 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

В'ю, будучи корисним, дозволяє користувачеві знати , що вони можуть рішуче наполягати на написання, додаючи знак оклику, !до wкоманді. Якщо використовується ця силова версія команди запису, Vim видаляє вихідний файл (якщо Vim використовує з backupнабором параметрів лише Vim , оригінальний файл насправді перейменований на такий самий, як файл резервного копіювання). Потім він відкриває (створює) новий файл з тим же ім'ям , що і оригінал, і записує вміст його буфера в цей новий файл. Це можна помітити, перевіривши 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
Святий дим, це було ретельно!
Camille Goudeseune

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.


Га! Після того як я опублікував свою відповідь, я здійснив кілька експериментів і закінчив витрачати близько години, запускаючи Vim через strace, щоб побачити, що він робить поза кадром у різних ситуаціях (різні перестановки дозволів та права власності на файл та батьківський каталог). Я тільки що побачив вашу відповідь, коли закінчив підбивати підсумки своїх експериментів. Це був гарний досвід навчання.
Ентоні Геоґеган
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.