我在删除空目录时遇到问题,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
只写入了 '.'和 '..'。这意味着getdents
coreutils 使用的包装器存在一些问题。 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
删除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 接口具有非常旧的固件,突然可以从公共网络获得。
答案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
for apple.mp4
,远程系统无法删除它,并且如果本地系统删除apple.mp4
但不删除点文件,则可能会不同步)。
解决方案是返回到本地系统,点文件在本地系统中可见并且可以进行rm
编辑。