#1 はじめに
systemdから起動されたプロセスのcoreファイル生成と、
systemdから起動されていないプロセスのcoreファイル生成方法について説明します。
#2 環境
VMware Workstation 12 Player上のゲストマシンを使っています。
[root@client ~]#cat /etc/redhat-release
CentOS Linux release 7.3.1611 (Core)
[root@client ~]# uname -r
3.10.0-514.el7.x86_64
#3 systemdが起動したプロセスのcoreファイル生成方法
下記手順に従っても、coreファイルが出力されない場合、SELinuxのポリシー違反の可能性があります。
そのような場合、文末の手順に従ってルールを作成することで、coreファイルが出力されるようになります。
##3.1 一時的な設定方法
[root@client ~]# mkdir /var/lib/coredumps
[root@client ~]# ls -ld /var/lib/coredumps
drwxr-xr-x 2 root root 31 1月 21 09:16 /var/lib/coredumps
[root@client ~]# sysctl -w kernel.core_pattern="/var/lib/coredumps/core.%e.%p"
kernel.core_pattern = /var/lib/coredumps/core.%e.%p
[root@client ~]# sysctl -n kernel.core_pattern
/var/lib/coredumps/core.%e.%p
[root@client ~]# sysctl -w fs.suid_dumpable=2
fs.suid_dumpable = 2
[root@client ~]# sysctl -n fs.suid_dumpable
2
ユニット定義ファイルのServiceセクションにLimitCORE=infinity(★)を追加する。
[root@client ~]# cp /usr/lib/systemd/system/chronyd.service /etc/systemd/system
[root@client ~]# vi /etc/systemd/system/chronyd.service
[root@client ~]# cat /etc/systemd/system/chronyd.service
-中略-
[Service]
Type=forking
PIDFile=/var/run/chronyd.pid
EnvironmentFile=-/etc/sysconfig/chronyd
ExecStart=/usr/sbin/chronyd $OPTIONS
ExecStartPost=/usr/libexec/chrony-helper update-daemon
LimitCORE=infinity ★
-以下、略-
ユニット定義ファイルの変更をsystemdに通知する。
[root@client ~]# systemctl daemon-reload
chronydを再起動する。
[root@client ~]# systemctl restart chronyd
[root@client ~]# ps -C chronyd
PID TTY TIME CMD
1302 ? 00:00:00 chronyd
[root@client ~]# pkill -SIGSEGV chronyd
[root@client ~]# ps -C chronyd
PID TTY TIME CMD
coreファイルを確認する。PID=1302のcoreファイルが生成されていることがわかる。
[root@client ~]# ls -la /var/lib/coredumps/core.chronyd.1302
-rw------- 1 root chrony 9093120 1月 21 09:16 /var/lib/coredumps/core.chronyd.1302
##3.2 恒久的な方法
ここでは、OSがリブートしても、設定が有効になったままにする方法について説明します。
coreファイルを保存するディレクトリを作成する。
[root@client ~]# mkdir /var/lib/coredumps
[root@client ~]# vi /etc/sysctl.d/core.conf
[root@client ~]# cat /etc/sysctl.d/core.conf
kernel.core_pattern = /var/lib/coredumps/core.%e.%p
fs.suid_dumpable = 2
[root@client ~]# sysctl --system
設定を確認する。
[root@client ~]# sysctl -n kernel.core_pattern
/var/lib/coredumps/core.%e.%p
設定を確認する。
[root@client ~]# sysctl -n fs.suid_dumpable
2
ユニット定義ファイルのServiceセクションにLimitCORE=infinity(★)を追加する。
[root@client ~]# cp /usr/lib/systemd/system/chronyd.service /etc/systemd/system
[root@client ~]# vi /etc/systemd/system/chronyd.service
[root@client ~]# cat /etc/systemd/system/chronyd.service
-中略-
[Service]
Type=forking
PIDFile=/var/run/chronyd.pid
EnvironmentFile=-/etc/sysconfig/chronyd
ExecStart=/usr/sbin/chronyd $OPTIONS
ExecStartPost=/usr/libexec/chrony-helper update-daemon
LimitCORE=infinity ★
-以下、略-
OSを再起動する。
[root@client ~]# shutdown -r now
OS再起動後のSELinuxのモードを確認する。
[root@client ~]# getenforce
Permissive
プロセスの状態を確認する。
[root@client ~]# ps -C chronyd
PID TTY TIME CMD
616 ? 00:00:00 chronyd
chronydプロセスにシグナル(SIGSEGV)を送信する。
[root@client ~]# pkill -SIGSEGV chronyd
[root@client ~]# ps -C chronyd
PID TTY TIME CMD
coreファイルを確認する。
[root@client ~]# ls -la /var/lib/coredumps/core.chronyd.613
-rw-------. 1 root chrony 9265152 5月 14 23:16 /var/lib/coredumps/core.chronyd.613
#4 systemdから起動しないプロセスのcoreファイル生成方法
##4.1 基本的な使い方
coreファイルのサイズを無制限に変更する。
[root@client core]# ulimit -c unlimited
[root@client core]# ulimit -c
unlimited
ここでは、core_patternをデフォルトのままで使用してみる。
デフォルトの場合、プログラムが実行されたディレクトリにcoreファイルが生成されます。
[root@client core]# cat /proc/sys/kernel/core_pattern
core
sleepプロセスを起動する。PIDは8783であることがわかる。
[root@client core]# sleep 300&
[1] 8783
sleepプロセスのulimitを確認する。coreファイルサイズが無制限(★)になっていることがわかる。
[root@client core]# cat /proc/8783/limits
Limit Soft Limit Hard Limit Units
Max core file size ★unlimited unlimited bytes
sleepプロセスにシグナル(SIGSEGV)を送信する。
[root@client core]# pkill -SIGSEGV sleep
ファイルを確認する。coreファイルが生成されたことがわかる。
[root@client core]# ls
core.8783
[1]+ Segmentation fault (コアダンプ) sleep 300
##4.2 coreファイルの格納場所や名前を変更する方法
coreファイルのサイズを無制限に変更する。
[root@client core]# ulimit -c unlimited
[root@client core]# ulimit -c
unlimited
coreファイルの格納場所を/tmp、coreファイルの名前はプロセス名(%e).プロセスID(%p)にする。
[root@client core]# echo '/tmp/core.%e.%p' > /proc/sys/kernel/core_pattern
[root@client core]# cat /proc/sys/kernel/core_pattern
/tmp/core.%e.%p
sleepプロセスを起動する。PIDは8861であることがわかる。
[root@client core]# sleep 300&
[1] 8861
sleepプロセスのulimitを確認する。coreファイルサイズが無制限(★)になっていることがわかる。
[root@client core]# cat /proc/8861/limits
Limit Soft Limit Hard Limit Units
Max core file size ★unlimited unlimited bytes
sleepプロセスにシグナル(SIGSEGV)を送信する。
[root@client core]# pkill -SIGSEGV sleep
ファイルを確認する。coreファイルが生成されたことがわかる。
[root@client core]# ls /tmp/core.sleep.8861
/tmp/core.sleep.8861
[1]+ Segmentation fault (コアダンプ) sleep 300
#5 coreファイルの参照方法
ここでは、生成したcoreファイルをgdbで参照する方法について説明します。
gdbでcoreファイルを参照するには、debuginfoパッケージをインストールする必要があります。
##5.1 chronyd
ここでは、chronydのcoreファイルをgdbで参照してみます。
chronyパッケージの版数を確認する。
[root@client ~]# rpm -qa|grep chrony
chrony-2.1.1-4.el7.centos.x86_64
chronyパッケージと同じ版数のdebuginfoパッケージをインストールする。
[root@client ~]# yum --disablerepo=* --enablerepo=base-debuginfo install chrony-debuginfo-2.1.1-4.el7.centos.x86_64
chronyのdebuginfoパッケージ(★)がインストールされたことがわかる。
[root@client ~]# rpm -qa|grep chrony
chrony-2.1.1-4.el7.centos.x86_64
chrony-debuginfo-2.1.1-4.el7.centos.x86_64 ★
[root@client ~]# gdb /var/lib/coredumps/core.chronyd.1302
-中略-
(gdb) set pagination off
(gdb) bt full
#0 0x00007fc672386ba3 in select () from /lib64/libc.so.6
No symbol table info available.
#1 0x00007fc6731aedf9 in SCH_MainLoop () at sched.c:650
rd = {fds_bits = {6, 0 <repeats 15 times>}}
status = <optimized out>
errsv = <optimized out>
tv = {tv_sec = 0, tv_usec = 127043}
saved_tv = {tv_sec = 0, tv_usec = 167708}
ptv = 0x7ffdc1a5ff40
now = {tv_sec = 1516493770, tv_usec = 715689}
saved_now = {tv_sec = 1516493770, tv_usec = 715689}
cooked = {tv_sec = 1516493770, tv_usec = 714225}
err = 0
__PRETTY_FUNCTION__ = "SCH_MainLoop"
__FUNCTION__ = "SCH_MainLoop"
#2 0x00007fc6731a48a4 in main (argc=0, argv=0x7ffdc1a60200) at main.c:534
conf_file = <optimized out>
progname = 0x7ffdc1a60f8c "/usr/sbin/chronyd"
user = 0x7fc674728460 "chrony"
debug = 0
nofork = 0
address_family = 0
do_init_rtc = 0
restarted = 0
other_pid = <optimized out>
lock_memory = 0
sched_priority = 0
system_log = 1
config_args = <optimized out>
__FUNCTION__ = "main"
##5.2 httpd
ここでは、httpdのcoreファイルをgdbで参照してみます。
httpdパッケージの版数を確認する。
[root@client ~]# rpm -qa|grep httpd
httpd-2.4.6-67.el7.centos.6.x86_64
httpd-tools-2.4.6-67.el7.centos.6.x86_64
[root@client ~]# yum --disablerepo=* --enablerepo=base-debuginfo install httpd-debuginfo-2.4.6-67.el7.centos.6.x86_64
httpdのdebuginfoパッケージ(★)がインストールされたことがわかる。
[root@client ~]# rpm -qa|grep httpd
httpd-2.4.6-67.el7.centos.6.x86_64
httpd-tools-2.4.6-67.el7.centos.6.x86_64
httpd-debuginfo-2.4.6-67.el7.centos.6.x86_64 ★
glibcパッケージの版数を確認する。
[root@client ~]# rpm -qa|grep glibc
glibc-common-2.17-157.el7.x86_64
glibc-2.17-157.el7.x86_64
glibc-devel-2.17-157.el7.x86_64
glibc-headers-2.17-157.el7.x86_64
[root@client ~]# yum --disablerepo=* --enablerepo=base-debuginfo install glibc-debuginfo-2.17-157.el7.x86_64
glibcのdebuginfoパッケージ(★)がインストールされたことがわかる。
[root@client ~]# rpm -qa|grep glibc
glibc-common-2.17-157.el7.x86_64
glibc-debuginfo-common-2.17-157.el7.x86_64
glibc-2.17-157.el7.x86_64
glibc-devel-2.17-157.el7.x86_64
glibc-debuginfo-2.17-157.el7.x86_64 ★
glibc-headers-2.17-157.el7.x86_64
[root@client ~]# ls -l /var/lib/coredumps/core.httpd.*
-rw------- 1 root root 2678784 1月 21 09:38 /var/lib/coredumps/core.httpd.1393
-rw------- 1 root apache 2678784 1月 21 09:38 /var/lib/coredumps/core.httpd.1394
-rw------- 1 root apache 2678784 1月 21 09:38 /var/lib/coredumps/core.httpd.1395
-rw------- 1 root apache 2678784 1月 21 09:38 /var/lib/coredumps/core.httpd.1396
-rw------- 1 root apache 2678784 1月 21 09:38 /var/lib/coredumps/core.httpd.1397
-rw------- 1 root apache 2678784 1月 21 09:38 /var/lib/coredumps/core.httpd.1398
[root@client ~]# gdb /var/lib/coredumps/core.httpd.1393
-中略-
(gdb) set pagination off
(gdb) bt full
#0 0x00007f85c9e88b83 in __select_nocancel () at ../sysdeps/unix/syscall-template.S:81
No locals.
#1 0x00007f85ca59f585 in apr_sleep () from /lib64/libapr-1.so.0
No symbol table info available.
#2 0x00007f85cb8c2971 in ap_wait_or_timeout (status=status@entry=0x7ffef45e7608, exitcode=exitcode@entry=0x7ffef45e760c, ret=ret@entry=0x7ffef45e7610, p=<optimized out>, s=<optimized out>) at mpm_common.c:195
rv = <optimized out>
#3 0x00007f85c14dc13e in prefork_run (_pconf=<optimized out>, plog=<optimized out>, s=<optimized out>) at prefork.c:1016
status = 32645
pid = {pid = -1, in = 0x7f8500000000, out = 0x7f85cc390450, err = 0x3}
child_slot = <optimized out>
exitwhy = (APR_PROC_SIGNAL_CORE | unknown: 3228138712)
processed_status = <optimized out>
index = <optimized out>
remaining_children_to_start = 0
rv = <optimized out>
#4 0x00007f85cb8c215e in ap_run_mpm (pconf=pconf@entry=0x7f85cc2f8138, plog=0x7f85cc325358, s=0x7f85cc31f310) at mpm_common.c:96
pHook = <optimized out>
n = 0
rv = -1
#5 0x00007f85cb8baed6 in main (argc=2, argv=0x7ffef45e7908) at main.c:783
c = 68 'D'
showcompile = 0
showdirectives = 0
confname = 0x7f85cb8f95cf "conf/httpd.conf"
def_server_root = 0x7f85cb8f95c4 "/etc/httpd"
temp_error_log = 0x0
error = <optimized out>
process = 0x7f85cc2f6218
pconf = 0x7f85cc2f8138
plog = 0x7f85cc325358
ptemp = 0x7f85cc323348
pcommands = 0x7f85cc31a248
opt = 0x7f85cc31a338
rv = <optimized out>
mod = 0x7f85cbb18098 <ap_prelinked_modules+24>
opt_arg = 0x7ffef45e7f7d "FOREGROUND"
signal_server = <optimized out>
#Y SELinuxのルール作成方法
##Y.1 ポリシー違反時のエラーメッセージ
coreファイルが出力されない原因の1つに、SELinuxのポリシーに違反している可能性があります。
そのような場合、/var/log/audit/audit.logに下記エラーメッセージが出力されます。
type=ANOM_ABEND msg=audit(1526305553.727:554): auid=4294967295 uid=998 gid=996 ses=4294967295 subj=system_u:system_r:chronyd_t:s0 pid=24252 comm="chronyd" reason="memory violation" sig=11
type=AVC msg=audit(1526305553.728:555): avc: denied { create } for pid=24252 comm="chronyd" name="core.chronyd.24252" scontext=system_u:system_r:chronyd_t:s0 tcontext=system_u:object_r:var_lib_t:s0 tclass=file
type=SERVICE_STOP msg=audit(1526305553.736:556): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:init_t:s0 msg='unit=chronyd comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=failed'
##Y.2 ルールの作成方法
[root@centos74 ~]# audit2allow -M test < /var/log/audit/audit.log
******************** IMPORTANT ***********************
To make this policy package active, execute:
semodule -i test.pp
[root@centos74 ~]# ls test.*
test.pp test.te
[root@centos74 ~]# cat test.te
module test 1.0;
require {
type chronyd_t;
type tmp_t;
type var_lib_t;
class file { create open read write };
class dir write;
}
#============= chronyd_t ==============
#!!!! WARNING: 'tmp_t' is a base type.
allow chronyd_t tmp_t:dir write;
#!!!! WARNING 'chronyd_t' is not allowed to write or create to var_lib_t. Change the label to chronyd_var_lib_t.
allow chronyd_t var_lib_t:file { create open read write };
[root@centos74 ~]# semodule -i test.pp
[root@centos74 ~]# semodule -l|grep -w test
test 1.0
#Z 参考
Enable Core Dump systemd
CentOS7の/etc/sysctl.d/以下の設定ファイルの反映方法
Enable core dumps for systemd services on CentOS 7