Os subdiretórios não-vazios de outro usuário são seguros contra exclusão em meu diretório?

5

Na seguinte situação ls -alh

total 0
drwxrwx--- 1 user http  20 Nov 30 08:08 .
drwxrws--- 1 user http 310 Nov 30 08:07 ..
drwx------ 1 http http  10 Nov 30 08:08 empty-subdir
drwx------ 1 http http  12 Nov 30 08:08 non-empty-subdir

onde existem dois subdiretórios (não pertencentes a mim), que eu listo como:

sudo ls empty-subdir -alh
total 0
drwx------ 1 http http 10 Nov 30 08:08 .
drwxrwx--- 1 user http 20 Nov 30 08:08 ..

sudo ls non-empty-subdir -alh
total 0
drwx------ 1 http http 12 Nov 30 08:08 .
drwxrwx--- 1 user http 20 Nov 30 08:08 ..
drwx------ 1 http http  0 Nov 30 08:08 subdir

A diferença entre os dois subdiretórios é que o non-empty-subdir não vazio contém uma pasta.

Minha pergunta é se é por design que, ao tentar rm -rf remover os subdiretórios, obtenho resultados:

$ rm empty-subdir -rf
$ rm non-empty-subdir -rf
rm: cannot remove 'non-empty-subdir': Permission denied
$ ls -alh
total 0
drwxrwx---+ 1 user http  10 Nov 30 08:14 .
drwxrws---+ 1 user http 310 Nov 30 08:07 ..
drwx------+ 1 http http  12 Nov 30 08:08 non-empty-subdir

Parece que o usuário com permissões de gravação para um diretório pode remover uma entrada de um arquivo ou um subdiretório vazio de outro usuário, mas não um subdiretório não vazio .

Uma resposta ideal para essa pergunta forneceria informações como:

  • uma confirmação de que o comportamento esboçado é reproduzível em outras máquinas (e não meras peculiaridades da minha caixa estragada)
  • uma justificativa para explicar esse comportamento (por exemplo, há casos de uso?)
  • uma visão geral se houver diferenças entre sistemas (BSD, Linux ....)

Atualizar : Com relação ao comentário do Ipor Sircer, eu retestei o cenário, sem nenhum recurso de ACL e é o mesmo. Portanto, modifiquei a questão para remover os + es das listagens, para não dar origem a uma ideia de que o comportamento possa estar relacionado a ACLs.

    
por humanityANDpeace 30.11.2017 / 08:21

3 respostas

12

Só é possível remover um diretório (com a chamada de sistema rmdir() ), se estiver vazio.

rm -r dir remove o diretório e todos os arquivos nele, começando com as folhas da árvore de diretórios e caminhando até a raiz ( dir ).

Para remover um arquivo (com rmdir() para diretórios e unlink() para outros tipos de arquivos, ou *at() variants), o que importa não é a permissão do arquivo em si, mas do diretório que você está removendo o arquivo de (tenha cuidado com o t bit nas permissões, como por /tmp , adiciona mais complicações a isso).

Antes de tudo, você não está realmente removendo o arquivo , você está desvinculando-o de um diretório (e quando é o último link que você está removendo, o arquivo acaba sendo deletado como uma conseqüência), isto é, você está modificando o diretório, então você precisa de permissões modificando (gravação) para aquele diretório.

O motivo pelo qual você não pode remover non-empty-dir é que não é possível desvincular subdir do primeiro, pois você não tem o direito de modificar non-empty-dir . Você teria o direito de desvincular non-empty-dir do seu diretório pessoal, pois você tem permissão de gravação / modificação para esse, mas não é possível remover um diretório que não esteja vazio.

No seu caso, como observado por @PeterCordes nos comentários, a chamada do sistema rmdir() falha com um código de erro ENOTEMPTY (Diretório não vazio), mas você não tem lido permissão para o diretório, rm não pode nem mesmo descobrir quais arquivos e diretórios (incluindo subdir ) precisariam se desvincular dele para poder esvaziá-lo (não que ele pudesse desvinculá-los se soubesse, pois não faz isso) t tem permissões de gravação).

Você também pode entrar em situações em que rm poderia remover um diretório se ele pudesse descobrir quais arquivos estão nele, como no caso de um diretório somente de gravação:

$ mkdir dir
$ touch dir/file
$ chmod a=,u=wx dir
$ ls -ld dir
d-wx------ 2 me me 4096 Nov 30 19:43 dir/
$ rm -rf dir
rm: cannot remove 'dir': Permission denied

Ainda assim, posso removê-lo, pois sei que ele contém apenas um arquivo file :

$ rm dir/file
$ rmdir dir
$

Note também que com Unices modernos você poderia renomear o non-empty-dir , mas em alguns como Linux ou FreeBSD (mas não no Solaris), não movê-lo para um diretório diferente, mesmo se você também tivesse escrever permissão para esse diretório, como (eu acho e para o Linux, como sugerido por o comentário para o código relevante ) fazendo isso envolveria a modificação de non-empty-dir (a entrada .. apontaria para um diretório diferente).

Alguém poderia argumentar que remover seu empty-dir também envolve a remoção das entradas .. e . , portanto, modificando-o, mas ainda assim, o sistema permite que você faça isso.

    
por 30.11.2017 / 10:29
4

Ignorando a possível alteração através das ACLs, posso confirmar este comportamento para o meu sistema (sem ACLs).

O comportamento observado é a consequência lógica de dois princípios:

1) Os direitos de um diretório determinam quem pode alterar o diretório, ou seja, excluir entradas no diretório. Os direitos das entradas nesse diretório não desempenham nenhum papel nisso.

2) A remoção de um arquivo requer a remoção e a limpeza de informações associadas, ou seja, inodes, listas de alocação de blocos etc. Por isso, não é possível remover uma subdiretória não vazia sem ter limpado todos os arquivos contidos nela. que contém ficaria inacessível, mas a informação associada não teria sido limpa.

Portanto, você pode remover empty-subdir , porque você tem o direito de gravar no diretório em que está. Não é possível remover non-empty-subdir , porque você não tem os direitos para limpar os arquivos contidos neste subdir primeiro.

Não há justificativa ou caso de uso para isso. Poderíamos ter construído uma limpeza recursiva de um subdiretório no kernel, mas o Unix original mantinha tudo simples, e a limpeza recursiva teria sido complicada demais quando pode ser obtida com um utilitário de espaço do usuário.

Eu não posso fornecer uma visão geral abrangente entre sabores diferentes, mas esse era o comportamento no Unix original, e eu esperaria que fosse o mesmo em todos os sabores do Unix, e eu ficaria surpreso se houvesse um sabor do Unix que se comportou de maneira diferente.

    
por 30.11.2017 / 08:45
3

Eu tentei reproduzir o que você descreveu e executei strace rm -rf ./nonempty . O que isso revela é o seguinte:

unlinkat(4, "subdir", AT_REMOVEDIR)     = -1 EACCES (Permission denied)

e de acordo com unlinkat manual (que no Linux é igual a unlink(2) , ênfase adicionada por mim):

EACCES Write access to the directory containing pathname is not allowed for the process's effective UID, or one of the directories in pathname did not allow search permission. (See also path_resolution(7).)

Como o diretório pai, nonempty , não concede a permissão user x (pesquisa), faz sentido com base na descrição EACCES que subdir não pode ser removida.

    
por 30.11.2017 / 10:10