Ext4

rmdir 刪除空目錄失敗

  • January 12, 2022

我在刪除空目錄時遇到問題,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  

為什麼會發生這種情況?有沒有機會在不解除安裝和全面檢查 fs 的情況下解決這個問題?

附加資訊:

“隱藏”文件只是一個普通的 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什麼都不顯示。

我跟踪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 使用readdirglibc 包裝器用於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

刪除 rootkit 文件,檢查所有包的文件(rpm -Va在我的例子中),自動啟動腳本,預載入/預連結配置,系統文件(在我的例子中是find /+ rpm -qf),更改受影響的密碼,查找和殺死 rootkit 的程序:

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

最後完整系統更新,重新啟動並解決問題。黑客成功的原因:ipmi 介面帶有非常舊的韌體,突然可以從公共網路獲得。

引用自:https://unix.stackexchange.com/questions/416852