Vim pode quebrar permissões de arquivo?

Vim pode quebrar permissões de arquivo?

Outro dia eu estava usando o Vim como sempre, quando notei algo estranho. Aqui está o que eu fiz:

~$ touch testfile
~$ ls -l | grep testfile
-rw-r--r-- 1 username groupname 0 Jul 23 10:00 testfile
~$ vim testfile

Então fiz uma alteração, salvei e fechei com :wq. Bem normal. Então, porém:

~$ sudo chown root:root testfile
~$ sudo chmod 644 testfile
~$ sudo -k
~$ ls -l | grep testfile
-rw-r--r-- root root 0 Jul 23 10:02 testfile
~$ vim testfile

Portanto, o root deve ter acesso r/w e todos os outros devem apenas ler. Edite o arquivo, tente salvar - você não pode. Incrível, funcionando como pretendido. No entanto, se você salvar com :w!, o vim de alguma forma alterará a propriedade do arquivo de volta para nome de usuário: grupo de usuários e o arquivo será salvo. Mesmo se você fizer isso:

~$ sudo chmod 444 testfile
~$ sudo -k
~$ ls -l | grep testfile
-r--r--r-- 1 root root 0 Jul 23 10:06 testfile
~$ vim testfile

Você podeaindasubstituir por :w!! O que está acontecendo? Como o vim pode violar as leis de propriedade e permissão de arquivos como esta? Olhei a página de ajuda do vim dizendo :help :we encontrei isto:

:w[rite]! [++opt]    Like ":write", but forcefully write when 'readonly' is set or there is another reason why writing was refused.
                     Note: This may change the permission and ownership of the file and break (symbolic) links. Add the 'W' flage to 'cpoptions' to avoid this.

Não consegui gravar em um arquivo no vim anteriormente quando não deveria, então acho que o verdadeiro cerne da minha pergunta é: como posso tornar um arquivo não editável pelo vim e por que ele não é baseado em arquivo permissões do sistema, como eu esperava, e qual mecanismo o vim está usando para editar o arquivo que outros editores (gedit, nano) não podem usar?

EDIT: O computador em que tentei está usando o kernel Linux 3.15.5-2-ARCH. O número da versão do Vim é 7.4.373-1, e é aquele instalado por pacman- não o compilei do zero com nenhuma opção especial.

Responder1

Posso ver que seu caminho atual é ~o diretório inicial do seu usuário. Você deve ter permissões de gravação nesse diretório.

Pense de outra maneira - se você tiver permissões de leitura e gravação no diretório, o que o impede de copiar o arquivo, excluir o antigo e renomear o novo com permissões diferentes?

Isso é exatamente o que o vim faz!


Se você executar o vim sob strace, por exemplo:

open("testfile", O_WRONLY|O_CREAT|O_TRUNC, 0644) = -1 EACCES (Permission denied)
lstat("testfile", {st_mode=S_IFREG|0644, st_size=10, ...}) = 0
getuid()                                = 1000
unlink("testfile")                      = 0
open("testfile", O_WRONLY|O_CREAT|O_TRUNC, 0644) = 3
write(3, "ffjidfjds\n", 10)             = 10
fsync(3)                                = 0
close(3)                                = 0
chmod("testfile", 0644)                 = 0

Com base neste log, posso adivinhar o seguinte processo:

Algumas verificações de permissão anteriores (e chowntentativas, etc.) são omitidas por questões de brevidade.

  1. openTentativa de abrir o arquivo para gravação (falha: permissão negada)
  2. lstatVerifique o proprietário do arquivo
  3. getuuidVerifique o ID do usuário atual para ver se ele corresponde ao proprietário do arquivo
  4. unlinkExclua o arquivo (isso é permitido devido à permissão de gravação no diretório)
  5. openCrie um novo arquivo com o mesmo nome
  6. writeO conteúdo do arquivo (li antes, digitei algumas coisas sem sentido)
  7. fsyncDescarregue o arquivo no disco (não é realmente importante)
  8. close
  9. chmodAltere as permissões do novo arquivo para se parecer com o antigo - agora ele tem um novo proprietário.

informação relacionada