Como o vim rouba arquivos de propriedade da raiz?

38

Testemunhe o seguinte:

sh-3.2$ mkdir testcase
sh-3.2$ cd testcase
sh-3.2$ sudo touch temp
sh-3.2$ ls -al
total 0
drwxr-xr-x   3 glen  staff  102 19 Dec 12:38 .
drwxr-xr-x  12 glen  staff  408 19 Dec 12:38 ..
-rw-r--r--   1 root  staff    0 19 Dec 12:38 temp

sh-3.2$ echo nope > temp
sh: temp: Permission denied

sh-3.2$ vim temp
# inside vim
itheivery
# press [ESC]
:wq!
# vim exits

sh-3.2$ ls -al
total 8
drwxr-xr-x   3 glen  staff  102 19 Dec 12:38 .
drwxr-xr-x  12 glen  staff  408 19 Dec 12:38 ..
-rw-r--r--   1 glen  staff    7 19 Dec 12:38 temp

De alguma forma, o vim pegou esse arquivo de propriedade da raiz e o transformou em um arquivo de propriedade do usuário!

Isso só parece funcionar se o usuário possui o diretório - mas ainda parece que não deveria ser possível. Alguém pode explicar como isso é feito?

    
por Glenjamin 19.12.2012 / 13:43

3 respostas

50

Você, glen , é o proprietário do diretório (veja o arquivo . em sua listagem). Um diretório é apenas uma lista de arquivos e você tem permissão para alterar essa lista (por exemplo, adicionar arquivos, remover arquivos, alterar propriedades para torná-lo seu novamente, etc.). Você pode não ser capaz de alterar os conteúdos do arquivo diretamente, mas você pode ler e desvincular (remover) o arquivo como um todo e adicionar novos arquivos posteriormente. 1 Apenas testemunhando o antes e depois, este pode parecer o arquivo foi alterado.

O Vim usa arquivos de swap e move arquivos em volta da água, então isso explica porque parece escrever no mesmo arquivo que você faz no seu shell, mas não é a mesma coisa. 2

Então, o que o Vim faz se resume a isso:

cat temp > .temp.swp          # copy file by contents into a new glen-owned file
echo nope >> .temp.swp        # or other command to alter the new file
rm temp && mv .temp.swp temp  # move temporary swap file back

1 Esta é uma diferença importante na manipulação de permissões de arquivos entre o Windows e o Unices. No Windows, geralmente não é possível remover arquivos para os quais você não tem permissão de gravação.

2 update: conforme observado nos comentários, o Vim não faz isso dessa maneira para alterar a propriedade, pois o número de inode no arquivo temp não é alterado (comaring ls -li antes e depois). Usando strace , podemos ver exatamente o que o vim faz. A parte interessante está aqui:

open("temp", O_WRONLY|O_CREAT|O_TRUNC, 0664) = -1 EACCES (Permission denied)
unlink("temp")                               = 0
open("temp", O_WRONLY|O_CREAT|O_TRUNC, 0664) = 4
write(4, "more text bla\n", 14)              = 14
close(4)                                     = 0
chmod("temp", 0664)                          = 0

Isso mostra que apenas desvincula , mas não fecha o descritor de arquivo para temp . Em vez disso, apenas sobrescreve todo o seu conteúdo ( more text bla\n no meu caso). Eu acho que isso explica porque o número do inode não muda.

    
por 19.12.2012 / 13:48
15

antes:

-rw-r--r-- 1 root staff 0 19 Dec 12:38 temp

depois:

-rw-r--r-- 1 glen staff 7 19 Dec 12:38 temp

O vim não rompe a barreira de permissão. Basta dar uma olhada nas informações do arquivo listadas cuidadosamente, então você pode descobrir que o vim realmente apagou o arquivo original (porque você tem permissão para remover o arquivo, embora não possa alterar seu conteúdo) e criou um novo arquivo de sua propriedade. veja o dono não é mais 'root').

E enquanto você está editando o arquivo original no vim, ele avisa que você está alterando um arquivo somente leitura. Então, quando você digitar o comando :wq! (forçar a operação), o que o vim pode fazer é excluir o arquivo existente e criar um novo arquivo que tenha o mesmo nome.

Espero que ajude.

    
por 19.12.2012 / 13:47
1

Use a opção -i de ls para ver o número do inode, que é um identificador exclusivo (dentro do sistema de arquivos) de um arquivo ou outro objeto.

Você verá que o arquivo foi substituído por um objeto diferente: o número do inode provavelmente será alterado.

Ver o mesmo número de inode não é prova de nada: um número de inode pode ser reciclado. Se removermos o último link para um arquivo e, em seguida, criarmos um novo arquivo, poderemos obter um com o mesmo número de inode. Mas isso não pode acontecer se o arquivo antigo for removido depois que o novo arquivo for criado. Por exemplo. %código%. Eu suspeito que o vim realmente faça algo análogo a esse mv file file.tmp; touch file; rm file.tmp . A operação echo new_content > tmpfile; mv tmpfile file será convertida para uma chamada de sistema mv , portanto, a atribuição de números de inode depende de como o sistema de arquivos implementa uma renomeação que desvincula um destino.

    
por 20.12.2012 / 02:56