Os subdiretórios não vazios de outro usuário estão protegidos contra exclusão no meu diretório?

Os subdiretórios não vazios de outro usuário estão protegidos contra exclusão no meu diretório?

Na seguinte situaçãols -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 (que não são de minha propriedade), que 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 não vazio non-empty-subdircontém uma pasta.

Minha pergunta é se é intencional que ao tentar rm -rfremover 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 em um diretório tem permissão para remover uma entrada de um arquivo ou um subdiretório vazio de algum outro usuário, mas não umnão vaziosubdiretório.

Uma resposta ideal a esta pergunta forneceria informações como:

  • uma confirmação de que o comportamento descrito é reproduzível em outras máquinas (e não meras peculiaridades da minha caixa bagunçada)
  • uma justificativa para explicar esse comportamento (por exemplo, existem 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, testei novamente o cenário, sem nenhum recurso de ACL e é o mesmo. Portanto, modifiquei a pergunta para remover os +es das listagens, para não dar origem à ideia de que o comportamento possa estar relacionado às ACLs.

Responder1

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

rm -r dirremove o diretório e todos os arquivos nele contidos, começando pelas folhas da árvore de diretórios e subindo até a raiz ( dir).

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

Antes de tudo, você não está realmente removendo oarquivo, você está desvinculando ele de um diretório (e quando é o último link que você está removendo, o arquivo acaba sendo deletado como consequência), ou seja, você está modificando o diretório, então você precisamodificando(gravar) permissões para esse diretório.

O motivo pelo qual você não pode remover non-empty-diré que você não pode desvinculá subdir-lo primeiro, pois não tem o direito de modificar o arquivo non-empty-dir. Você teria o direito de desvincular-se non-empty-dirdo seu diretório inicial, pois tem permissão de gravação/modificação para esse diretório, mas não pode remover um diretório que não esteja vazio.

No seu caso, conforme observado por @PeterCordes nos comentários, a rmdir()chamada do sistema falha com um ENOTEMPTYcódigo de erro (Diretório não vazio), mas como você não temlerpermissão para o diretório, rmnão consegue nem descobrir quais arquivos e diretórios (incluindo subdir) ele precisaria desvincular para poder esvaziá-lo (não que pudesse desvinculá-los se soubesse, pois não possui permissões de gravação).

Você também pode entrar em situações em querm poderiaremova um diretório se ele puder descobrir quais arquivos estão nele, como no caso de um diretório somente 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, consigo removê-lo, pois sei que ele contém apenas um filearquivo:

$ rm dir/file
$ rmdir dir
$

Observe também que com Unices modernos você pode renomear isso non-empty-dir, mas em alguns como Linux ou FreeBSD (mas não Solaris),nãomova-o para um diretório diferente, mesmo que você também tenha permissão de gravação para esse diretório, como (eu acho e para Linux, como sugerido poro comentário para o código relevante) isso envolveria modificação non-empty-dir(a ..entrada apontaria para um diretório diferente).

Pode-se argumentar que remover o seu empty-dirtambém envolve remover as entradas ..e .nele, modificando-o, mas ainda assim, o sistema permite que você faça isso.

Responder2

Ignorando a possível alteração por meio das ACLs, posso confirmar esse 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 alterá-lo, ou seja, excluir entradas do diretório. Os direitos das entradas nesse diretório não desempenham nenhum papel nisso.

2) A remoção de um arquivo potencialmente requer a remoção e limpeza de informações associadas, ou seja, inodes, listas de alocação de blocos, etc. É por isso que você não pode remover um subdiretório não vazio sem limpar todos os arquivos que ele contém, porque caso contrário, os arquivos que ele contém seriam tornar-se-ia inacessível, mas as informações associadas não teriam sido limpas.

Portanto, você pode remover empty-subdir, porque tem o direito de gravar no diretório em que está. Você não pode remover non-empty-subdir, porque não tem o direito de limpar primeiro os arquivos contidos neste subdiretório.

Não há realmente nenhuma justificativa ou caso de uso para isso. Alguém poderia ter construído uma limpeza recursiva de um subdiretório no kernel, mas o Unix original manteve tudo simples, e a limpeza recursiva teria sido muito complicada quando pudesse ser alcançada com um utilitário de espaço do usuário.

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

Responder3

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

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

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

EACCES O acesso de gravação ao diretório que contém o nome do caminho não é permitido para o UID efetivo do processo, ou um dos diretórios no nome do caminho não permitiu permissão de pesquisa. (Veja também path_resolution(7).)

Como o diretório pai, nonempty, não concede userpermissão x (pesquisa), faz sentido com base na EACCESdescrição que subdirnão pode ser removida.

informação relacionada