ulimit -c unlimited
echo "/tmp/core-%e-%p" > /proc/sys/kernel/core_pattern
echo 2 > /proc/sys/fs/suid_dumpable
因为fedora不用init,而改用systemd,所以他下面的daemon默认不生成core。所以看似简单的问题,而不得不去研究源代码。用systemtap发现do_coredump确实被调到了,但就是不产生core。最后发现是__get_dumpable返回0。找到了几个关键字后(systemd prctl core dump)再在google里搜,就找到了答案。
crash> ps | grep systemd
1 0 13 ffff881038ed8000 IN 0.0 234456 13612 systemd
725 1 11 ffff88102e5c9d00 IN 0.1 131072 40944 systemd-journal
758 1 7 ffff8810317bab80 IN 0.0 87924 10792 systemd-udevd
1788 1 2 ffff880fd597c880 IN 0.0 71380 8468 systemd-logind
6161 1 8 ffff88101cfde580 IN 0.0 81948 8144 systemd
crash> task_struct.mm ffff881038ed8000
mm = 0xffff88103128bc00
crash> mm_struct.flags 0xffff88103128bc00
flags = 0x200cd
crash> ps |grep ovs-vswitchd
24934 1 8 ffff881014cf8e80 IN 0.2 1283740 151284 ovs-vswitchd
crash> task_struct.mm ffff881014cf8e80
mm = 0xffff880fe2431c00
crash> mm_struct.flags 0xffff880fe2431c00
flags = 0x200ce
ovs-vswitchd的父进程是systemd,mm.flags也继承自父进程。不过设置/proc/sys/fs/suid_dumpable为2后,flags就不一样了。
0xffffffff812ae300 : do_coredump+0x0/0xeb0 [kernel]
0xffffffff8109b95a : get_signal+0x29a/0x610 [kernel]
0xffffffff8102dd77 : do_signal+0x37/0x680 [kernel]
0xffffffff810035fe : exit_to_usermode_loop+0x6e/0xb0 [kernel]
0xffffffff81003a1b : prepare_exit_to_usermode+0x8b/0x90 [kernel]
0xffffffff818009b4 : swapgs_restore_regs_and_return_to_usermode+0x0/0x87 [kernel]
void do_coredump(const siginfo_t *siginfo)
{
struct core_state core_state;
struct core_name cn;
struct mm_struct *mm = current->mm;
struct linux_binfmt * binfmt;
const struct cred *old_cred;
struct cred *cred;
int retval = 0;
int ispipe;
struct files_struct *displaced;
/* require nonrelative corefile path and be extra careful */
bool need_suid_safe = false;
bool core_dumped = false;
static atomic_t core_dump_count = ATOMIC_INIT(0);
struct coredump_params cprm = {
.siginfo = siginfo,
.regs = signal_pt_regs(),
.limit = rlimit(RLIMIT_CORE),
/*
* We must use the same mm->flags while dumping core to avoid
* inconsistency of bit flags, since this flag is not protected
* by any locks.
*/
.mm_flags = mm->flags,
};
audit_core_dumps(siginfo->si_signo);
binfmt = mm->binfmt;
if (!binfmt || !binfmt->core_dump)
goto fail;
if (!__get_dumpable(cprm.mm_flags))
goto fail;
...
#define SUID_DUMP_DISABLE 0 /* No setuid dumping */
#define SUID_DUMP_USER 1 /* Dump as user of process */
#define SUID_DUMP_ROOT 2 /* Dump as root */
除了上述方法还可以在应用程序里面直接调用prctl:
+ prctl(PR_SET_DUMPABLE, 1);