Por que posso modificar um arquivo somente leitura?

41

Pergunta curta:

Por que podemos manipular um arquivo somente leitura no Vim usando : + w + q + ! mesmo sem ser um administrador?

Longa Pergunta:

Eu tenho um arquivo de texto (myFile.txt) que é somente leitura para todos:

[email protected]:~/ubuntuTest$ ls -l myFile.txt 
-r--r--r-- 1 navid navid 26 Aug 22 21:21 myFile.txt

Eu posso abri-lo com o Vim sem ter privilégios de administrador:

[email protected]:~/ubuntuTest$ vi myFile.txt 

Modifico e pressiono: Esc + : + w + q + Enter e vejo esta mensagem de erro:

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

Até agora, tudo faz sentido. Mas quando pressiono: Esc + : + w + q + ! + Enter , o Vim salva as alterações.

Estou usando o Ubuntu 16.04 e o VIM 7.4.

    
por Navid Vafaei 23.08.2016 / 17:06

7 respostas

57

Como @Rob já mencionado , você só pode fazer isso se tiver acesso de gravação ao diretório que contém o arquivo. A tentativa de fazer a mesma coisa em um arquivo, por exemplo, /etc falhará.

Quanto a como vim está fazendo isso, ele exclui o arquivo e o recria. Para testar isso, criei um arquivo de propriedade do root:

echo foo | sudo tee fff

Em seguida, continuei a editar o arquivo com vim da maneira que você descreve, mas anexando o processo a strace para ver o que está acontecendo:

strace vim fff 2> strace.out

Em seguida, verifiquei strace.out e encontrei:

unlink("fff")                           = 0
open("fff", O_WRONLY|O_CREAT|O_TRUNC, 0644) = 4
write(4, "foasdasdao\n", 11)            = 11

Assim, o arquivo foi excluído primeiro ( unlink("fff") ), então um novo arquivo com o mesmo nome foi criado ( open("fff", O_WRONLY|O_CREAT|O_TRUNC, 0644) ) e as modificações que eu fiz foram gravadas nele ( write(4, "foasdasdao\n", 11) ). Se você tentar isso em casa, verá que depois de editá-lo com vim , o arquivo agora pertencerá a você e não ao root.

Então, estritamente falando, vim não está editando um arquivo para o qual você não tem acesso de gravação. Ele está excluindo um arquivo de um diretório para o qual você possui acesso de gravação e, em seguida, criando um novo arquivo para o qual, novamente, você tem acesso de gravação.

    
por terdon 23.08.2016 / 17:40
15

Contanto que você possua o diretório pai, você pode remover ou substituir um arquivo, não importando a permissão, pois você pode alterar o conteúdo do diretório:).

Tente com outro comando como rm, ele irá avisar mas você ainda pode fazer isso. Torne o diretório não gravável e isso deve pará-lo.

Adição:

Apenas tentei, mas, desde que eu possua o arquivo, ainda posso modificá-lo, mesmo com a pasta somente leitura. No entanto, quando altero a propriedade para root: root, não é possível abrir o arquivo para gravação. Então resolve os arquivos modificados pertencentes a root (ou outra pessoa)

    
por Rob 23.08.2016 / 17:34
15

Usando w! , você está removendo o arquivo original ( que tem permissão para fazer ) e escrevendo sua versão.

Quando você tem acesso de gravação a um diretório, você pode: criar, mover ou excluir arquivos dentro desse diretório.

$ mkdir foo
$ echo hi > foo/file
$ chmod 777 foo
$ chmod 700 foo/file
$ ls -l foo/file 
-rwx------ 1 ravexina ravexina 7 Aug 31 03:19 foo/file

Agora, deixe-me mudar meu usuário e alterar o arquivo

$ sudo -u user2 -s
$ vi foo/a # save using w! (I wrote into the file bye)
$ ls -l foo/a
-rwx------ 1 user2 user2 7 Aug 31 03:20 foo/file

Agora veja o que está lá:

$ cat foo/file
bye
    
por Ravexina 31.08.2017 / 04:48
9

Veja :help write-readonly :

                                                        write-readonly
When the 'cpoptions' option contains 'W', Vim will refuse to overwrite a
readonly file.  When 'W' is not present, ":w!" will overwrite a readonly file,
if the system allows it (the directory must be writable).

Como você tem permissões de gravação no diretório (o que significa que pode criar, excluir ou renomear arquivos), o sistema permite isso.

O valor padrão de cpoptions não contém W :

                                                'cpoptions' 'cpo' cpo
'cpoptions' 'cpo'       string  (Vim default: "aABceFs",
                                 Vi default:  all flags)
                        global
    
por muru 31.08.2017 / 04:57
2

Este é o aviso do VIM para você que pode ser relativamente importante considerando como as permissões funcionam no UNIX. A aparente falta de intuição disso ocorre porque os sistemas de arquivos UNIX possuem permissões para o arquivo armazenado no nó i do arquivo. A estrutura de diretórios é de alguma forma separada e está ligando apenas esses i-nodes. Os diretórios também têm suas permissões que dizem se você pode vincular / desvincular arquivos para ele ou lê-lo ou atravessá-lo para subdiretórios. Esse design permite que o mesmo arquivo possa aparecer em vários locais diferentes na estrutura do diretório (por meio de links físicos). Ao dizer "add! To override", o VIM está tentando avisá-lo que o arquivo original será desvinculado (assim ele permanecerá em todos os outros locais intocados) e o novo arquivo será criado e vinculado ao local original na estrutura do diretório. Caso a contagem de links do arquivo original diminua para zero, o arquivo original será liberado, mas caso contrário, você estará efetivamente clonando o arquivo. A abertura do arquivo também conta como link, portanto, se algum programa abrir o arquivo e você concordar em "adicionar! Para substituir", o programa não verá as alterações feitas no arquivo por você com o VIM. O arquivo só é desvinculado do diretório pelo VIM e depois de fechar o arquivo por outro programa, o arquivo será liberado, a menos que esteja vinculado em outro lugar.

Por favor, note que no Windows, as permissões para arquivos são armazenadas no diretório, portanto, do ponto de vista do paradigma de permissões do Windows, esse comportamento do vim pode realmente parecer estranho. Para gravar no arquivo, o Windows logicamente também pode verificar algumas permissões de diretório, até mesmo as permissões de superdiretório. Como dito acima, no UNIX, as permissões de diretório são irrelevantes para a manipulação com o arquivo, desde que você possa listá-lo e abri-lo (ou seja, houve x para todos os superdiretórios). O arquivo aberto no UNIX pode não ter mais o nome do arquivo se ele foi desvinculado de todos os diretórios após a abertura.

Por exemplo, você tem o arquivo / home / user1 / foo e é o mesmo arquivo (isto é, hardlinked to) / home / user2 / foo e o arquivo não pode ser escrito por ninguém e atualmente aberto pelo programa P -write por programa iniciado por root). Se user1 abrir com vim e sobrescreve, ele faz sua própria cópia e não vê mais o arquivo original. Se subseqüentemente user2 abrir seu link com o vim e gravar nele, ele será desvinculado novamente e ele criará outra cópia. O programa P ainda verá o arquivo original e poderá ler ou gravar livremente nele. Assim que o programa fechar o arquivo, o arquivo desaparecerá (liberado pelo sistema de arquivos).

    
por ludvik02 25.08.2016 / 12:18
2

Tanto o processo do editor vim quanto o arquivo carregam o seu

 getpwnam("navid")->pw_uid

propriedade para que você também possa gastar

 :!chmod +w %

e você pode imaginar que, uma vez, o mais simples ainda

 :!rm %

(requerendo somente + w, u-t desvinculação de permissão em. e nem mesmo propriedade) tornou-se muito frequente para alguém digitar de forma que o vim fosse reprogramado para automaticamente oferecer e a pedido automagicamente realizar tal operação.

Tente substituir sua irmã mais velha

 /home/whoopi/.profile

como meras navid e apostas, o seu vim lhe dá a recusa desejada.

    
por Roman Czyborra 24.08.2016 / 21:43
1

Isso não é exatamente uma resposta, mas se você realmente quiser definir um arquivo para que ninguém possa alterá-lo ou excluí-lo, você poderá torná-lo imutável.

Normalmente, mesmo quando um arquivo é de propriedade do root, você ainda pode excluir o arquivo se tiver permissões de gravação para a pasta. Mas quando você torna o arquivo imutável, mesmo o root não pode modificá-lo ou excluí-lo.

Para tornar um arquivo imutável (você precisa de sudo ):

sudo chattr +i myFile.txt

Você pode ver isso com lsattr (a letra i no resultado):

$ lsattr myFile.txt
----i--------e-- myFile.txt

Para tornar o arquivo normal novamente:

sudo chattr -i myFile.txt

Para esclarecer: quando um arquivo é imutável, ele não pode ser excluído, renomeado, modificado ou até mesmo com hard-link.

Vale a pena ler man chattr , porque os arquivos podem ter vários atributos úteis.

Você também pode achar útil "exclusão restrita". Se colocado em uma pasta (não em um arquivo), isso significa que quem cria um arquivo dentro da pasta tem permissão para modificar ou excluir esse arquivo, mas ninguém mais é (exceto root). A pasta /tmp tem esse sinalizador definido. Você pode ver isso com o sinalizador t em /tmp :

$ ls -l --directory /tmp
drwxrwxrwt 10 root root 4096 Sep  6 09:00 /tmp

Para definir ou remover o sinalizador de exclusão restrita em uma pasta:

chmod +t myFolder      # Add the restricted deletion flag.
chmod -t myFolder      # Remove the restricted deletion flag.
    
por Paddy Landau 06.09.2017 / 10:11