Como o vim rouba arquivos pertencentes à raiz?

39

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 raiz e o transformou em um arquivo de propriedade do usuário!

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

Glenjamin
fonte

Respostas:

51

Você glené o proprietário do diretório (consulte o .arquivo na 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 a propriedade para torná-lo seu novamente, etc.). Você pode não conseguir alterar o conteúdo do arquivo diretamente, mas pode ler e desvincular (remover) o arquivo como um todo e adicionar novos arquivos posteriormente. 1 Apenas testemunhando o antes e o depois, pode parecer que o arquivo foi alterado.

O Vim usa arquivos de troca e os move debaixo d'água, o que explica por que parece gravar no mesmo arquivo que você faz no shell, mas não é a mesma coisa. 2

Então, o que o Vim faz, resume-se 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 Essa é uma diferença importante no tratamento de permissão de arquivo 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 atualização: conforme observado nos comentários, o Vim não faz isso dessa maneira para alterar a propriedade, pois o número do inode no temparquivo não muda (comparação de marcas ls -liantes e depois). Usando stracepodemos ver exatamente o que vimfaz. 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 ele apenas desassocia , mas não fecha o descritor de arquivo temp. Em vez disso, apenas substitui todo o seu conteúdo ( more text bla\nno meu caso). Eu acho que isso explica por que o número do inode não muda.

gertvdijk
fonte
3
FWIW, você pode verificar se isso está acontecendo executando ls -ilantes e depois ... se tempo número do inode foi alterado, você sabe que é um arquivo diferente com o mesmo nome.
inútil
3
Pode-se acrescentar que o rm não remove o arquivo, mas apenas remove um link para o arquivo, e o arquivo não é excluído antes que o número de links diminua para 0. O rm remove a entrada para o arquivo no diretório Se o root tiver outro link (hard link) para o arquivo em outro diretório, o usuário não poderá remover o arquivo.
Gerrit
11
@ Useless eu tentei, e o número não mudou, embora o proprietário e o carimbo de data e hora tenham mudado!
Amyassin
11
@amyassin Você está certo! Atualizei minha resposta com um trecho de strace explicando-a.
gertvdijk
11
Como parte de sua observação sobre as permissões Windows vs. Unix, se você quiser um comportamento semelhante ao Windows no Unix, poderá criar um diretório pertencente à raiz (ou outro usuário que deva ter permissões universais de remover / renomear / etc) e definir a opção bit no diretório Em seguida, os usuários poderão excluir apenas seus próprios arquivos.
precisa
16

antes:

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

depois de:

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

O vim não rompe a barreira da permissão. Basta dar uma olhada nas informações do arquivo listadas com cuidado e descobrir que o vim realmente excluiu 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 ( veja que o proprietário não é mais 'root').

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

Espero que ajude.

ymfoi
fonte
1

Use a -iopção de lspara 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 nada: um número de inode pode ser reciclado. Se removermos o último link para um arquivo e 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 após a criação do novo. Por exemplo mv file file.tmp; touch file; rm file.tmp. Eu suspeito que o vim realmente faz algo análogo a isso echo new_content > tmpfile; mv tmpfile file. A mvoperação será convertida em uma renamechamada do sistema, portanto, a atribuição de números de inode depende de como o sistema de arquivos implementa uma renomeação que desvincula um destino.

Kaz
fonte