Linux上的核心转储文件:如何获取有关打开文件的信息?

时间:2020-03-05 18:52:05  来源:igfitidea点击:

我有一个进程可能有文件描述符泄漏的核心转储文件(它会打开文件和套接字,但显然有时会忘记关闭其中的一些文件)。有没有办法找出进程在崩溃前打开了哪些文件和套接字?我无法轻松地重现崩溃,因此分析核心文件似乎是获得有关该漏洞的提示的唯一方法。

解决方案

回答

核心转储是进程崩溃时可以访问的内存的副本。根据泄漏的发生方式,可能会丢失对句柄的引用,因此可能被证明是无用的。

lsof列出了系统中当前所有打开的文件,我们可以检查其输出以查找泄漏的套接字或者文件。是的,我们需要运行该流程。我们可以使用特定的用户名运行它,以轻松识别正在调试的进程中的打开文件。

我希望其他人有更好的信息:-)

回答

我们可以尝试使用strace查看程序调用的open,socket和close。

编辑:我认为我们无法从核心获取信息;最多它的某个地方会有文件描述符,但这仍然不能提供实际的文件/套接字。 (假设我们可以区分打开文件描述符和关闭文件描述符,我也对此表示怀疑。)

回答

仅在运行时才发现进程再次打开哪些文件的另一种方法是查看/ proc / PID / fd /,其中包含用于打开文件的符号链接。

回答

如果程序忘记关闭这些资源,则可能是因为发生了以下类似情况:

fd = open("/tmp/foo",O_CREAT);
//do stuff
fd = open("/tmp/bar",O_CREAT); //Oops, forgot to close(fd)

现在,我将在内存中没有foo的文件描述符。

如果没有发生,我们也许可以找到文件描述符号,但是再说一次,这不是很有用,因为它们在不断变化,在我们进行调试时,我们将不知道它实际上意味着哪个文件当时。

我真的认为我们应该与strace,lsof和朋友一起对此进行实时调试。

如果有办法从核心转储中做到这一点,我也很想知道:-)

回答

最好的选择是为导致程序崩溃的任何信号(SIGSEGV等)安装信号处理程序。

然后,在信号处理程序中,检查/ proc / self / fd,然后将内容保存到文件中。这是我们可能看到的示例:

Anderson cxc # ls -l  /proc/8247/fd
total 0
lrwx------ 1 root root 64 Sep 12 06:05 0 -> /dev/pts/0
lrwx------ 1 root root 64 Sep 12 06:05 1 -> /dev/pts/0
lrwx------ 1 root root 64 Sep 12 06:05 10 -> anon_inode:[eventpoll]
lrwx------ 1 root root 64 Sep 12 06:05 11 -> socket:[124061]
lrwx------ 1 root root 64 Sep 12 06:05 12 -> socket:[124063]
lrwx------ 1 root root 64 Sep 12 06:05 13 -> socket:[124064]
lrwx------ 1 root root 64 Sep 12 06:05 14 -> /dev/driver0
lr-x------ 1 root root 64 Sep 12 06:05 16 -> /temp/app/whatever.tar.gz
lr-x------ 1 root root 64 Sep 12 06:05 17 -> /dev/urandom

然后,我们可以从信号处理程序中返回,并且应该照常进行核心转储。

回答

如果我们有一个核心文件,并且已使用调试选项(-g)编译了该程序,则可以看到将核心转储到的位置:

$ gcc -g -o something something.c
$ ./something
Segmentation fault (core dumped)
$ gdb something core

我们可以使用它来进行事后调试。一些gdb命令:br打印堆栈,fr跳到给定的堆栈帧(请参阅br的输出)。

现在,如果我们想查看在分段错误时打开了哪些文件,只需处理SIGSEGV信号,然后在处理程序中仅转储/ proc / PID / fd目录的内容(即,使用system('ls -l / proc / PID / fs')或者execv)。

有了这些信息,我们可以轻松找到导致崩溃的原因,打开了哪些文件以及崩溃和文件描述符泄漏是否已连接。