Eu estava usando o Vim 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, salvei e saí com :wq
. Bastante 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 todo mundo deve ter lido apenas. Edite o arquivo, tente salvar - você não pode. Incrível, funcionando como pretendido. No entanto, se você salvar com :w!
, o vim alterará de alguma forma a propriedade do arquivo de volta para nome de usuário: usergroup 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ê ainda pode substituir com :w!
! O que está acontecendo? Como o vim pode violar as leis de propriedade e permissão de arquivos assim? Olhei para a página de ajuda no vim dizendo :help :w
e encontrei o seguinte:
: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 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 não é baseado em arquivo permissões de sistema, 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 em que tentei usar o kernel do Linux 3.15.5-2-ARCH. O número da versão do Vim é 7.4.373-1 e é o instalado por pacman
- eu não o compilei do zero com nenhuma opção especial.
fonte
CAP_CHOWN
é necessário ligarchown(2)
. A propósito, eu posso reproduzir no Debian, com o vim 7.4.Respostas:
Percebo que seu caminho atual é
~
o diretório inicial do usuário. Você deve ter permissões de gravação nesse diretório.Pense de outra maneira - se você tem permissões de leitura e gravação no diretório, o que impede você de copiar o arquivo, excluir o antigo e renomear o novo com permissões diferentes?
É exatamente isso que o vim faz!
Se você executar o vim sob strace, por exemplo:
Com base nesse log, posso adivinhar o seguinte processo:
Algumas verificações de permissão anteriores (e
chown
tentativas, etc.) são omitidas por questões de brevidade.open
Tentativa de abrir o arquivo para gravação (falha: permissão negada)lstat
Verifique o proprietário do arquivogetuuid
Verifique o ID do usuário atual para ver se eles correspondem ao proprietário do arquivounlink
Exclua o arquivo (isso é permitido porque a permissão de gravação no diretório)open
Crie um novo arquivo com o mesmo nomewrite
O conteúdo do arquivo (leia mais cedo, eu digitei algumas semelhanças)fsync
Liberar o arquivo no disco (não é realmente importante)close
chmod
Altere as permissões do novo arquivo para se parecer com o antigo - acontece agora de ter um novo proprietário.fonte
:w!
, o que faz sentido.strace
: use a-o
opção para gravar a saída em um arquivo; caso contrário, entrará em conflito comvim
a saída. Quanto permissões de gravação, eu não vê-lo verificar as permissões de diretório comstat
mas não tentar criar um arquivo (chamado4913
, parece aleatório) no diretório atual e, em seguida, excluí-lo.4913
na verdade, é apenas o primeiro nome que ele tenta e seu objetivo é verificar se ele possui permissões suficientes para isso. Veja: bugzilla.redhat.com/show_bug.cgi?id=427711#c6 and groups.google.com/forum/#!topic/vim_dev/sppdpElxY44