Linux上核心转储(Core Dumps)的设置
2023-07-02 21:48:35 阿炯

为诊断和调试Linux应用程序中的错误而创建的核心转储(Core Dumps)。它们也称为内存转储、崩溃转储、系统转储或ABEND转储。但核心转储可能包含敏感信息,例如密码、用户数据(如PAN、SSN)或加密密钥。因此必须在生产Linux服务器上禁用它们。在传统的init与systemd的初始方式下对其的关闭各有千秋。

简单地说,核心转储只不过是应用程序在Linux上崩溃时的内存记录。通常包括:应用程序名称、日期和时间、寄存器、程序计数器、堆栈指针、内存管理信息、其他CPU和Linux系统标志和信息

正如前所述,早期的核心转储可能包含攻击者可能利用的信息,此外还占用了大量的磁盘空间。因此必须在生产服务器上禁用它们。请注意,出于调试目的,开发人员需要在其开发系统或服务器上启用并保持崩溃转储。默认情况下,Linux将转储存于/var/crash/目录中。使用systemd启动服务或进程时,它们将存于/var/lib/systemd/coredump/目录中。

在Linux上禁用核心转储

Linux提供了各种方法来禁用核心转储。当Linux内核在运行时由于段冲突或任何不可预见的错误而删除程序时,最常见有三种方式来关闭核心转储的方法。

如何使用limits.conf和sysctl方法禁用Linux核心转储文件

引导时禁用的过程如下:
打开终端应用程序,使用ssh命令登录远程云服务器。然后编辑/etc/security/limits.conf文件。追加以下行:
* hard core 0
* soft core 0

具有提升权限(或setuid位)的进程可能仍然能够执行核心转储,这取决于它的设置。由于这些进程通常具有更多的访问权限,因此它们可能在内存中包含更敏感的数据段。可以使用sysctl或直接通过/proc文件系统更改行为。对于永久设置,通常使用sysctl命令和配置。要使用要转储的setuid位禁用程序,请将fs.suid_dumpable设置为零。确保阻止setuid和setgid程序将核心转储到,编辑以下文件:
/etc/sysctl.d/99999-disable-core-dump.conf或/etc/sysctl.conf

然后追加:
fs.suid_dumpable=0
kernel.core_pattern=|/bin/false

关闭并保存文件。最后运行sudo sysctl-p/etc/sysctl.d/99999-disable-core-dump.conf命令来激活更改。

false命令(/bin/false)退出,状态代码指示失败。换言之,什么也不做都不成功,这将导致禁用Linux转储。


了解Linux下的fs.suid_dumpable和kernel.core_pattern选项

kernel.core_pattern变量用于指定核心转储文件模式名称,要查看当前设置,请使用sysctl命令:
sysctl kernel.core_pattern

以下是所看到的:
kernel.core_pattern=
|/usr/share/apprt/apprt %p %s %c %d %p %E
|/usr/share/apport/apport %p %s %c %P

apport命令自动从崩溃的Linux进程中收集数据,并在/var/crash/中编译问题报告。对于GNOME桌面,为kde destkop提供了apport gtk和apport kde。

core_pattern的格式说明符
Table 1
OptionDescription
%<NUL>‘%’ is dropped
%%output one ‘%’
%ppid
%Pglobal pid (init PID namespace)
%itid
%Iglobal tid (init PID namespace)
%uuid (in initial user namespace)
%ggid (in initial user namespace)
%dDump mode, matches PR_SET_DUMPABLE and /proc/sys/fs/suid_dumpable
%sSignal number
%tUNIX time of dump
%hhostname
%eexecutable filename (may be shortened)
%Eexecutable path
%<OTHER>Both are dropped


要在运行时禁用,请运行:
sudo sysctl-w kernel.core_pattern=“|/bin/false”

要查询当前值,请使用sysctl命令:
sysctl fs.suid_dumpable

在运行时为setuid或其他受保护/受污染的二进制文件设置核心转储模式,如下所示:
sysctl -w fs.suid_dumpable=值

其中,值可以是以下任意一个:
0–这是默认和传统行为。任何更改了权限级别或仅执行的进程都不会被转储。

1–也称为调试模式。换句话说,所有进程都会在可能的情况下转储核心。当前用户拥有核心转储,并且不应用任何安全性。开发人员必须仅在系统或应用程序调试情况下使用此功能。进程跟踪(系统调用)也未选中。不要在生产Linux服务器和容器工作负载上启用此模式。它是不安全的,因为它允许普通用户检查特权进程的内存内容,并且可能包含敏感信息。

2–这种模式也称为自杀安全模式。任何通常不会转储的Linux程序都会被转储,但前提是“core_pattern”内核sysctl设置为管道处理程序或完全限定路径。当Linux系统管理员试图在特定环境中调试问题时,此模式非常合适。


使用systemd时如何禁用coredumps

systemd启动的服务将忽略limits.conf。因此需要有一个额外的配置。特别是一些发行版,如RHEL/CNTOS/Debian/Ubuuntu和其他发行版,systemd需要额外的配置来禁用核心转储。使用cat或more或less命令查找以下两个文件:

ls -l /usr/lib/sysctl.d/
more /usr/lib/sysctl.d/50-coredump.conf文件

ls -l /etc/systemd/*.conf文件
more /etc/systemd/coredump.conf

相关联的文件有:
/etc/systemd/coredump.conf
/etc/systemd/coredump.conf.d/*.conf
/run/systemd/coredump.conf.d/*.conf
/usr/lib/systemd/coredump.conf.d/*.conf

# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
#
# Entries in this file show the compile time defaults.
# You can change settings by editing this file.
# Defaults can be restored by simply deleting this file.
#
# See coredump.conf(5) for details.

[Coredump]
#Storage=external
#Compress=yes
#ProcessSizeMax=2G
#ExternalSizeMax=2G
#JournalSizeMax=767M
#MaxUse=
#KeepFree=

使用mkdir命令创建一个新的目录,运行:
mkdir/etc/systemd/coredump.conf.d/
vim/etc/systemd/coredump.conf.d/custom.conf

##或者使用nano文本编辑器命令##
nano /etc/systemd/coredump.conf.d/custom.conf

然后附加以下内容:
[Coredump]
Storage=none
ProcessSizeMax=0

设置Storage=none和ProcessSizeMax=0将禁用除systemd下的日志项之外的所有核心转储处理。然后使用systemctl命令重新加载systemd的配置,如下所示:
systemctl daemon-reload

编辑/etc/systemd/system.conf文件,确保DefaultLimitCORE已注释掉。例如:
#DefaultLimitCORE=infinity

然后运行以下命令:
systemctl daemon-reexec


使用ulimit方法

Bash或zsh提供了一个内置的ulimit命令,可以用来查看或设置shell的资源限制以及shell启动的进程。例如:

#设置创建的核心文件的最大大小
ulimit -c 0
ulimit -S -c 0

#验证更改生效与否#
ulimit -a

硬限制
ulimit -H -c

软限制
ulimit -S -c

可以将以下命令添加到shell启动文件中,如/etc/profile或~/.bash_profile或~/.profile,以便为当前用户永久禁用它:
echo'ulimit -S -c 0'>>~/.bash_profile

echo "ulimit -c 0 > /dev/null 2>&1" > /etc/profile.d/disable-coredumps.sh


如何在Linux中反向操作即启用coredumps

编辑/etc/security/limits.conf删除以下两行:
* hard core 0
* soft core 0

接下来,删除/etc/sysctl.d/99999-disable-core-dump.conf或编辑/etc/sysctl.conf:
rm /etc/sysctl.d/99999-disable-core-dump.conf

#通过创建新配置启用更改#
vim /etc/sysctl.d/99999-enable-core-dump.conf

然后附加以下内容以在Linux上启用核心转储:
#### A value of 1 permits core dumps that are readable by the owner of the dumping process only. ###
#### A value of 2 permits core dumps that are readable only by root. ####
fs.suid_dumpable=2
kernel.core_pattern='|/usr/share/apport/apport %p %s %c %d %P %E'

运行sysctl命令:
sysctl -p

接下来,编辑shell配置文件(全局或个人),如/etc/profile或~/.bash_profile或~/.profile,并删除ulimit命令行:
ulimit -c 0

#*注:如果只想为调试提供对foo应用程序的操作权限,请添加以下内容*#
ulimit -S -c unlimited foo

#适配到所有应用
ulimit -S -c unlimited

最后,删除systemd配置文件:
rm /etc/systemd/coredump.conf.d/custom.conf

让设定生效
systemctl daemon-reload

此外,编辑/etc/systemd/system.conf并确保DefaultLimitCORE设置如下:
DefaultLimitCORE=infinity

然后运行:
systemctl daemon-reexec


需要在不同的地方应用设置来禁用或启用Linux下的核心转储。随着systemd的引入,操作变得复杂起来。因此,除了sysctl命令(Linux内核)和PAM的limits.conf使用的配置文件之外,还需要编辑systemd的额外配置文件。

在systemd下,使用journalctl显示了相关的崩溃,所以这是一个开始。
Sep 06 15:19:21 hardening kernel: traps: crash[2232] trap divide error ip:4004e5 sp:7fff3c2fc651 error:0 in crash[400000+1000]


Core Dump 测试

选项1:创建一个不稳定的程序
创建一个简单的程序。它的主要目标是在执行时崩溃,然后有选择地创建一个核心转储。在系统上安装gcc,并在主目录中创建一个文件crash.c。
int main(){
    return 1/0;
}

该程序将启动主函数并返回一个整数值(数字)。但它将1除以0,这是不允许的,并且会崩溃。下一步是编译我们的小程序。
gcc -o crash crash.c

甚至编译器也显示程序包含严重问题并显示警告,现在运行它可看到是这样。
Floating point exception (core dumped)

从这句话中可知程序在退出时有一个异常,特别是指浮点。这是程序的十进制数字格式,所以它可能表示在做一些数学运算时发生了一些事情。另一个结论是,coredumps被生成;如果禁用了核心转储,则不会出现这种情况。

根据相关的Linux发行版,处理核心转储和默认设置的方式不同。最新的Linux发行版现在也使用systemd,规则也随之略有变化。

选项2:终止正在运行的进程
也可以终止现有进程,而不是使用测试程序。这是通过使用SIGSEGV来完成的,SIGSEGV是分割违规的缩写,也被称为分割错误。
kill -s SIGSEGV PID

如果将PID替换为“$$”,则当前程序(很可能是您的shell)将崩溃。

选项3:使用gdb
如果安装了开发人员调试工具gdb,则使用进程ID(PID)连接到所选的进程。
gdb -p 1234

然后在gdb提示符下,通过调用generate core file指令生成核心转储;使用此命令后,它应该会返回您的输出。
Saved corefile core.1234