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 使用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 接口具有非常旧的固件,突然可以从公共网络获得。

答案2

您可以在其中debugfs删除该文件。您甚至不需要文件名(如果存在特殊字符问题,如 francois P 在评论中猜测的那样,这可能是相关的):

kill_file <26808797>

答案3

就我而言,这是因为文件系统被安装为带有以下全局选项的 cifs smb/samba 共享:

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

这提供了与 Apple 计算机的兼容性以及他们为所有媒体类型(例如 mp4)创建辅助元数据流的愿望。

但它的工作方式是创建不可见的点文件(例如.apple.mp4for apple.mp4,远程系统无法删除它,并且如果本地系统删除apple.mp4但不删除点文件,则可能会不同步)。

解决方案是返回到本地系统,点文件在本地系统中可见并且可以进行rm编辑。

相关内容