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

関連情報