在Ubuntu22.04下有个程序不定期崩溃,但没产生core dump文件。本文记录分析和解决问题的过程。
1、检查系统关于core文件方面的限制设置
ltmz@VirtualBox:/home/$ ulimit -a
real-time non-blocking time (microseconds, -R) unlimited
core file size (blocks, -c) unlimited
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 15328
max locked memory (kbytes, -l) 500060
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 15328
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
我的系统都是unlimited,所以不是这个原因。
补充1:新装的ubuntu系统默认core file size 是0,需要运行下面命令解除限制:
ltmz@VirtualBox:/home$ ulimit -c unlimited
ltmz@VirtualBox:/home$ ulimit -c
unlimited
补充2:通过上述命令设置后,只是在当前控制台会话有效。如果要整个系统永久有效,需要在/etc/security/limits.conf中增加一行:
#<domain> <type> <item> <value>
* soft core unlimited
2、检查“/proc/sys/fs/suid_dumpable”文件的值
在Linux系统中,/proc/sys/fs/suid_dumpable文件用于控制哪些程序可以产生core dump文件。文件可以是以下几个值之一:
- 0:禁止所有set-user-ID和set-group-ID程序生成core dump文件。这是默认的安全设置。
- 1:允许set-user-ID和set-group-ID程序生成core dump文件,但是core dump文件的所有者将是程序的原始文件所有者,而不是启动它的用户。这有助于防止某些安全漏洞,但仍然允许调试。
- 2:允许set-user-ID和set-group-ID程序生成core dump文件,并且core dump文件的所有者将是启动程序的用户。这提供了最大的调试灵活性,但也增加了安全风险,因为如果攻击者能够诱导一个set-user-ID程序崩溃并生成core dump文件,那么他们可能会获得对系统敏感信息的访问。
我的系统里的值是2,没有禁止所有程序生产core dump文件。程序所有者和所有用户组都是ltmz,而运行程序也是用ltmz用户运行,满足2的要求。所以不是这个原因。
补充:set-user-ID和set-group-ID是程序里分别调用了setuid()和setgid()函数实现的。
3、检查core文件生成的目录
core的缺省位置是程序所在目录,可以通过修改/proc/sys/kernel/core_pattern来指定core文件生成位置了名称。
ltmz@VirtualBox:/home$ cat /proc/sys/kernel/core_pattern
|/usr/share/apport/apport -p%p -s%s -c%c -d%d -P%P -u%u -g%
core_pattern里的配置含义是,用 ‘|’ 管道符把生成的core文件传递给apport文件处理。apport 是一个在Ubuntu和其他基于Debian的Linux发行版中用于自动收集崩溃报告的工具。它帮助用户收集程序崩溃时的相关信息,并可以自动提交报告给开发者。apport生成的报告通常保存在/var/crash/目录下,以.crash为扩展名的文件。
我的系统里/var/crash/目录找不到任何崩溃报告。apport没生成崩溃报告的原因不明。因为我的目标是产生core dump文件,所以apport没生成崩溃报告的问题先放一放。
/proc/sys/kernel/core_pattern文件里可以使用以下通配符模板:
%%:输出一个单一的 % 字符。
%p:被转储进程的PID。
%u:被转储进程的实际用户ID。
%g:被转储进程的实际组ID。
%s:导致产生核心转储的信号名称。
%t:核心转储文件生成时的UNIX时间戳。
%h:主机名。
%e:可执行文件的文件名。
%E:与%e相同,但文件名被转义,以便在shell中安全使用。
尝试修改/proc/sys/kernel/core_pattern文件,但没成功。这文件不让直接vim修改。只能通过以下命令把内容改成core。
ltmz@VirtualBox:/home$ sudo bash -c "echo core.APP-%e.PID-%p.HOST-%h.TIME-%t.UID-%u.GID-%g > /proc/sys/kernel/core_pattern"
ltmz@VirtualBox:/home$ cat /proc/sys/kernel/core_pattern
core
再运行崩溃的程序,终于在程序目录生成core.APP-xxxx.PID-4648.HOST-VirtualBox.TIME-1728355240.UID-1000.GID-1000文件了(xxxx是程序名)。
至此,问题得以解决。