O Vi pode gravar no arquivo, apesar do arquivo ser somente leitura


12

O exemplo a seguir mostra como criar um arquivo com apenas permissões de leitura. Como podemos ver, quando tento gravar neste arquivo usando o comando echo que recebo Permission denied,.

Mas por que, no caso de usarmos vi, não conseguimos Permission denied? Como pode ser visto aqui, podemos gravar no arquivo, mesmo que o arquivo seja somente leitura.

O que esta acontecendo aqui? Isso é um bug do 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
Para sua informação, existe um site beta SE para isso - vi.stackexchange.com
Raystafarian 13/15

Respostas:


28

Nota : Devido a razões de licenciamento herdadas, a maioria das distribuições GNU / Linux não inclui o programa vi original, conforme escrito por Bill Joy. Em vez disso, o comando vi é fornecido executando o Vim no modo de compatibilidade com vi. A resposta a seguir é baseada na execução do Vim com seu modo de compatibilidade com o vi.

Modificando um arquivo somente leitura

O Vim avisa o usuário se ele modificar o buffer de um arquivo somente leitura W10: Warning: Changing a readonly file,. Se o usuário tenta escrever para esse arquivo, eles recebem a seguinte mensagem de erro, 'readonly' option is set (add ! to override).

Quando o diretório pai é gravável pelo usuário do Vim

O Vim, sendo útil, permite que o usuário saiba que ele pode insistir forçosamente na gravação anexando um ponto de exclamação !ao wcomando. Se esta versão vigorosa do comando write for usada, o Vim excluirá o arquivo original (se estiver usando o Vim com a backupopção somente Vim configurada, o arquivo original será renomeado para ser o mesmo que o arquivo de backup). Em seguida, ele abre (cria) um novo arquivo com o mesmo nome que o original e grava o conteúdo de seu buffer nesse novo arquivo. Isso pode ser observado verificando o inode do arquivo antes e depois da execução do 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

Nota: Isso também pode alterar a permissão e a propriedade do arquivo e quebrar os links (simbólicos), por exemplo, se o arquivo original pertencer a outro usuário, o novo arquivo pertencerá ao usuário que executa o Vim.

Um processo só pode fazer isso se tiver permissão de gravação para o diretório pai do arquivo. Em geral, para garantir que um programa não possa modificar um arquivo, as permissões do próprio arquivo e de seu diretório pai devem ser protegidas.

Quando o diretório pai não é gravável pelo usuário do Vim

No entanto, mesmo nesse caso, o Vim ainda faz o possível para ajudar o usuário insistente a sobrescrever o arquivo. Se o usuário do Vim tiver a propriedade do arquivo, o Vim poderá contornar a restrição de diretório pai somente leitura alterando temporariamente a permissão do arquivo (usando a chmodchamada do sistema), gravando o buffer no arquivo, fechando o arquivo e, em seguida, alterando o permissões de volta. Aqui está um extrato das chamadas do sistema feitas durante a execução do vi através do 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

Nota: Isso não acontece se o usuário do Vim estiver editando um arquivo do qual não possui propriedade, pois o Vim não poderá alterar as permissões do arquivo.

Termo aditivo

Para ter certeza de que um arquivo não pode ser modificado (em um sistema GNU / Linux), execute o chattrcomando como superusuário:

sudo chattr +i filename

De man chattr:

Um arquivo com o atributo 'i' não pode ser modificado: não pode ser excluído ou renomeado, nenhum link pode ser criado para esse arquivo e nenhum dado pode ser gravado no arquivo. Somente o superusuário ou um processo que possui o recurso CAP_LINUX_IMMUTABLE pode definir ou limpar esse atributo.


2
Santo fumo, isso foi completo!
Camille Goudeseune 13/04

4
@CamilleGoudeseune Depois de postar a primeira versão da minha resposta, fiz alguns experimentos e acabei gastando cerca de uma hora executando o Vim através do strace para ver o que estava fazendo nos bastidores em diferentes situações (diferentes permutações de permissões e propriedade de ambos os arquivos e Diretório Parental). Às vezes me empolgo, mas depois de publicar uma resposta, queria ter certeza de que o que estava dizendo estava correto.
Anthony Geoghegan

5

A maioria, se não todas as viimplementações impedi-lo para gravar o arquivo se você usar um regular comando Salvar como quer ZZ, :w, :wqou :x, por exemplo, com vim:

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

Por outro lado, se você pedir vipara gravar o arquivo apesar de suas permissões, usando algo como :x!ou :wq!, o editor estará relaxando temporariamente as permissões para permitir que o arquivo seja gravado:

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

Nesse caso, o número do inode permanece inalterado.

Finalmente, isso não é um bug, como se você não tivesse permissão para alterar as permissões do arquivo, não poderá modificá-lo completamente vi.


Hah! Depois de postar minha resposta, fiz alguns experimentos e acabei passando quase uma hora executando o Vim através do strace para ver o que estava fazendo nos bastidores em diferentes situações (permutações diferentes de permissões e propriedade do arquivo e do diretório pai). Acabei de ver sua resposta depois que terminei de resumir os resultados de minhas experiências. Foi uma boa experiencia de aprendizado.
Anthony Geoghegan
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.