O Vim pode quebrar as permissões de arquivo?

7

Eu estava usando o Vim no outro dia, como de costume, 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 e salvei e saí com :wq . Bem normal. Então, no entanto:

~$ 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 demais devem ter lido apenas. Edite o arquivo, tente salvar - você não pode. Incrível, trabalhando como pretendido. No entanto, se você salvar com :w! , o vim de alguma forma altera a propriedade do arquivo de volta para username: usergroup e o arquivo é 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ê ainda pode substituir com :w! ! O que está acontecendo? Como pode violar as leis de propriedade e permissão de arquivos como essa? Eu olhei para a página de ajuda no vim dizendo :help :w e achei isso:

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

Eu não consegui escrever em um arquivo no vim anteriormente quando não deveria, então eu acho que o verdadeiro coração da minha pergunta é, como eu posso fazer um arquivo uneditable pelo vim e por que não é com base nas permissões do sistema de arquivos, como eu esperaria, e qual mecanismo o vim está usando para editar o arquivo que outros editores (gedit, nano) não podem usar?

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

    
por zrneely 23.07.2014 / 16:25

1 resposta

9

Eu posso ver que seu caminho atual é ~ , o diretório inicial do seu usuário. Você deve ter permissões de gravação para esse diretório.

Pense nisso de outra forma - se você leu e gravou permissões no diretório, o que impede você 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 nesse log, posso adivinhar o seguinte processo:

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

  1. open Tentativa de abrir o arquivo para gravação (falha: permissão negada)
  2. lstat Verifique o dono do arquivo
  3. getuuid Verifique o ID do usuário atual para ver se eles correspondem ao proprietário do arquivo
  4. unlink Exclua o arquivo (isso é permitido porque a permissão de gravação está no diretório)
  5. open Cria um novo arquivo com o mesmo nome
  6. write O conteúdo do arquivo (leia antes, eu digitei algumas coisas sem sentido)
  7. fsync Flush o arquivo para o disco (não é realmente importante)
  8. close
  9. chmod Altere as permissões do novo arquivo para se parecer com o antigo - acontece que agora ele tem um novo proprietário.
por 23.07.2014 / 17:08