rmdir não conseguiu remover o diretório vazio

7

Eu tenho um problema com a remoção de dir vazio, strace mostra erro:

rmdir("empty_dir") = -1 ENOTEMPTY (Directory not empty)

E ls -la empty_dir não mostra nada. Então eu conectei ao fs (ext4) com o debugfs e vejo o arquivo oculto dentro desse diretório:

# ls -lia empty_dir/
total 8
44574010 drwxr-xr-x 2 2686 2681 4096 Jan 13 17:59 .
44573990 drwxr-xr-x 3 2686 2681 4096 Jan 13 18:36 ..

debugfs:  ls empty_dir
 44574010  (12) .    44573990  (316) ..  
 26808797  (3768) _-----------------------------------------------------------.jpg  

Por que isso aconteceu? E alguma chance de resolver este problema sem desmontar e checar completamente o fs?

Informações adicionais:

O arquivo "oculto" é apenas um arquivo jpg normal e pode ser aberto pelo visualizador de imagens:

debugfs:  dump empty_dir/_-----------------------------------------------------------.jpg /root/hidden_file

# file /root/hidden_file 
/root/hidden_file: JPEG image data, JFIF standard 1.02

rm -rf empty_dir não está funcionando com o mesmo erro:

unlinkat(AT_FDCWD, "empty_dir", AT_REMOVEDIR) = -1 ENOTEMPTY (Directory not empty)

find empty_dir/ -inum 26808797 não mostra nada.

    
por Jo Kin 13.01.2018 / 17:40

2 respostas

4

Eu alterei ls e obtive mais informações para escavar (syscalls não importantes despojadas):

open("empty_dir", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 3
getdents(3, /* 3 entries */, 32768)     = 80
write(1, ".\n", 2.)                     = 2
write(1, "..\n", 3..)                   = 3

Hmm, vemos que o syscall getdents funciona corretamente e retornou todas as 3 entradas ('.', '..' e '_--- *'), mas ls escreveu apenas '.' e '..'. Isso significa que temos algum problema com o wrapper em torno de getdents , que é usado pelo coreutils. E os coreutils usam readdir glibc wrapper para getdents . Também para provar que não há problemas com getdents i testado pequeno prog da seção de exemplo do de getdents homem . Este prog mostrou todos os arquivos.

Talvez tenhamos encontrado um bug no glibc? Então eu atualizei o pacote glibc para a última versão na minha distro, mas não obtive nenhum bom resultado. Também não encontrei nenhuma informação correlata no bugzilla.

Então, vamos mais fundo:

# gdb ls
(gdb) break readdir
(gdb) run
Breakpoint 1, 0x00007ffff7dfa820 in readdir () from /lib64/libncom.so.4.0.1
(gdb) info symbol readdir
readdir in section .text of /lib64/libncom.so.4.0.1

Espere, o que? libncom.so.4.0.1? Não é uma libc? Sim, acabamos de ver uma biblioteca compartilhada maliciosa com funções libc para ocultar atividades maliciosas:

# LD_PRELOAD=/lib64/libc.so.6 find / > good_find
# find / > injected_find
# diff good_find injected_find
10310d10305
< /lib64/libncom.so.4.0.1
73306d73300
< /usr/bin/_-config
73508d73501
< /usr/bin/_-pud
73714d73706
< /usr/bin/_-minerd
86854d86845
< /etc/ld.so.preload

Removendo arquivos de rootkit, verificando todos os arquivos de pacotes ( rpm -Va no meu caso), scripts de auto-inicialização, configurações de pré-carregamento / pré-instalação, arquivos de sistema ( find / + rpm -qf no meu caso), alterando senhas afetadas, encontrando e matando os processos do rootkit:

# for i in /proc/[1-9]*; do name=$(</proc/${i##*/}/comm); ps -p ${i##*/} > /dev/null || echo $name; done
_-minerd

No final, atualização completa do sistema, reinicialização e problema resolvido. Razão do hacking bem sucedido: interface ipmi com firmware muito antigo que de repente estava disponível a partir da rede pública.

    
por 15.01.2018 / 01:15
1

Dentro de debugfs você pode excluir o arquivo. Você nem precisa do nome do arquivo (o que pode ser relevante se houver problemas com caracteres especiais como o francois P adivinhou nos comentários):

kill_file <26808797>
    
por 13.01.2018 / 18:37