Vi pode gravar no arquivo apesar de o arquivo ser somente leitura

11

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, Permission denied .

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

O que está 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
    
por maihabunash 13.04.2015 / 07:57

2 respostas

25

Observação : devido a motivos de licenciamento legado, 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 do vi. A resposta a seguir é baseada na execução do Vim com seu modo de compatibilidade de compatibilidade visual.

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 tentar gravar nesse arquivo, receberá 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 pode insistir com insistência em escrever anexando um ponto de exclamação, ! ao comando w . Se essa versão forçada do comando write for usada, o Vim excluirá o arquivo original (se estiver usando o Vim com a opção backup definida pelo Vim, 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 como o original e grava o conteúdo de seu buffer nesse novo arquivo. Isso pode ser observado ao verificar o inode do arquivo antes e depois de executar o 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 links (simbólicos), por exemplo, se o arquivo original pertencesse a outro usuário, o novo arquivo seria de propriedade do usuário executando 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 neste caso, o Vim ainda faz o possível para ajudar o usuário insistente a gravar 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 chamada de sistema chmod ), gravando o buffer no arquivo, fechando o arquivo e em seguida, alterando as permissões de volta. Esta é uma extração das chamadas do sistema feitas durante a execução do vi por 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

Observação: isso não acontece se o usuário do Vim estiver editando um arquivo do qual não tenha propriedade, pois o Vim não poderá alterar as permissões do arquivo.

Adendo

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

sudo chattr +i filename

De man chattr :

A file with the ‘i’ attribute cannot be modified: it cannot be deleted or renamed, no link can be created to this file and no data can be written to the file. Only the superuser or a process possessing the CAP_LINUX_IMMUTABLE capability can set or clear this attribute.

    
por 13.04.2015 / 10:15
5

A maioria, senão todas as implementações de vi impedem que você grave o arquivo se usar um comando de salvamento regular, como ZZ , :w , :wq ou :x , por exemplo, com vim :

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

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

...
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 é mantido inalterado.

Finalmente, isso não é um erro, como se você não tivesse permissão para alterar as permissões do arquivo, você não pode modificá-lo através de vi .

    
por 13.04.2015 / 11:26

Tags