rmdir은 빈 디렉토리를 삭제할 수 없습니다

rmdir은 빈 디렉토리를 삭제할 수 없습니다

빈 디렉터리를 삭제하는 데 문제가 있습니다. strace에 오류가 표시됩니다.

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

아무것도 ls -la empty_dir표시되지 않습니다. 그래서 나는 debugfs를 사용하여 fs(ext4)에 연결하고 이 디렉터리에 있는 숨겨진 파일을 봅니다.

# 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  

왜 이런 일이 발생합니까? 파일 시스템을 마운트 해제하고 완전히 확인하지 않고 이 문제를 해결할 수 있습니까?

추가 정보:

"숨겨진" 파일은 이미지 뷰어를 통해 열 수 있는 일반 jpg 파일입니다.

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동일한 오류를 사용할 수 없습니다:

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

find empty_dir/ -inum 26808797아무것도 표시되지 않습니다.

답변1

나는 추적 ls하여 더 많은 정보를 얻었습니다(중요하지 않은 시스템 호출 제거).

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

글쎄, 우리는 시스템 호출이 getdents잘 작동하고 3개의 항목('.', '..' 및 '------*')을 모두 반환하지만 ls'.' 및 '..'만 기록되는 것을 확인합니다. 이는 getdentscoreutils에서 사용하는 래퍼에 문제가 있음을 의미합니다. coreutils는 readdir이를 처리하기 위해 glibc 래퍼를 사용합니다. 또한 문제 없이 getdents의 예제 섹션에서 작은 프로그램을 테스트했음을 getdents증명합니다.getdents남성페이지. 프로그램이 모든 파일을 표시합니다.

어쩌면 우리가 glibc에서 버그를 발견한 걸까요? 그래서 glibc 패키지를 배포판의 최신 버전으로 업데이트했지만 좋은 결과를 얻지 못했습니다. 또한 bugzilla에서 관련 정보를 찾지 못했습니다.

그럼 좀 더 자세히 살펴보겠습니다.

# 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

무엇을 기다립니다? libncom.so.4.0.1? libc가 아닌가요? 예, 방금 악성 활동을 숨기는 데 사용되는 libc 함수가 포함된 악성 공유 라이브러리를 보았습니다.

# 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

루트킷 파일 제거, 모든 패키지 파일 확인( rpm -Va내 경우), 자동 시작 스크립트, 사전 로드/사전 링크 구성, 시스템 파일( 내 경우 find /+ ), 영향을 받는 비밀번호 변경, 루트킷 프로세스 찾기 및 종료:rpm -qf

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

마지막으로 전체 시스템 업데이트를 수행하고 재부팅하여 문제를 해결합니다. 성공적인 손상 이유: ipmi 인터페이스에는 공용 네트워크에서 갑자기 사용할 수 있는 매우 오래된 펌웨어가 있습니다.

답변2

debugfs거기서 파일을 삭제할 수 있습니다 . 파일 이름도 필요하지 않습니다(Francois P가 주석에서 추측한 것처럼 특수 문자 문제가 있는 경우 관련이 있을 수 있음).

kill_file <26808797>

답변3

제 경우에는 파일 시스템이 다음 전역 옵션을 사용하여 cifs smb/samba 공유로 마운트되었기 때문입니다.

[global]
   vfs objects = catia fruit streams_xattr
   fruit:aapl = yes

이는 Apple 컴퓨터와의 호환성 및 모든 미디어 유형(예: mp4)에 대한 보조 메타데이터 스트림을 생성하려는 욕구를 제공합니다.

하지만 작동 방식은 보이지 않는 도트 파일을 생성한다는 것입니다(예를 들어 .apple.mp4, apple.mp4원격 시스템은 이를 삭제할 수 없으며, apple.mp4로컬 시스템이 도트 파일을 삭제했지만 삭제하지 않으면 동기화가 해제될 수 있습니다).

해결 방법은 도트 파일을 볼 수 있고 편집할 수 있는 로컬 시스템으로 돌아가는 것입니다 rm.

관련 정보