web-dev-qa-db-ja.com

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  

なぜこれが起こるのでしょうか?そして、アンマウントして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は何も表示しません。

7
Jo Kin

私はlsをトレースし、Digに詳細情報を取得しました(重要でないシステムコールを取り除いた):

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

うーん、syscall getdentsは正しく機能し、3つのエントリ( '。'、 '..'および '_--- *')をすべて返しましたが、lsは '。'のみを書き込んだことがわかります。および「..」。これは、coreutilsで使用されるgetdentsのラッパーに問題があることを意味します。また、coreutilsはreaddirgetdents glibcラッパーを使用します。また、getdentsに問題がないことを証明するために、getdentsのサンプルセクションの man ページの小さなプログラムをテストしました。このプログラムはすべてのファイルを表示しました。

たぶん、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インターフェイス。

4
Jo Kin

debugfs内でファイルを削除できます。ファイル名も必要ありません(コメントでfrancois Pが推測したように、特殊文字に問題がある場合に関連する可能性があります)。

kill_file <26808797>
1
Hauke Laging