Features/Core
Что такое файлы core?
Любая программа, исполняемая в среде Linux с виртуальной памятью, может совершить с памятью своего процесса действие, приводящее к нарушению её ожиданий от железа, а точнее — взаимных обязательств с ОС и железом. Например:
- обратиться к адресу памяти, на который ничего не отображено;
- произвести попытку записи по адресу из страницы без прав на запись (или прыгнуть в страницу без прав на исполнение);
- получить аппаратный отказ при работе с памятью;
и так далее. Это может зависеть от программного кода в процессе (примеры 1, 2) или от надёжности аппаратуры (пример 3).
Ядро Linux унаследовало от UNIX-систем следующий порядок действий в этой ситуации: процесс прекращает работу по некоторому сигналу (отражающему причину падения), а ядро формирует слепок резидентной памяти процесса (который и называется coredump или core-файлом, в простореч. корка) и помещает его либо в файловую систему, либо на стандартный ввод специальной свежезапущенной программе, задача которой — сохранить корку куда следует.
Core-файл имеет[1] формат ELF (тип объекта ET_CORE) и хранит информацию о:
- состоянии регистров аппаратуры на момент падения в корку;
- других метаданных каждого потока исполнения;
- отображениях страниц виртуальной памяти в файлы и анонимные сегменты, а также о содержимом страниц
- Информация в памяти процесса может быть и конфиденциальной, например, содержать пароли. Будьте осторожны при передаче корок третьим лицам.
Корки могут быть очень полезны, например, разработчикам упавшей программы, чтобы лучше понять причину падения и найти возможную ошибку в программе.
В Linux исторически сформировалось множество способов настроить сброс core-файлов небезопасным образом, что ведёт к возможности обхода ограничений безопасности и возникновению уязвимостей в настроенной системе. Чтобы этого избежать, при установке ALT мы выставляем настройки по умолчанию, описанные ниже.
Файлы core без systemd
По умолчанию в ALT Linux механизм coredump отключен для уменьшения уязвимости обычных систем (по причине неоднократных серьёзных проблем с ним; см. тж. altbug #9780). Это не касается современных дистрибутивов с systemd.
Предпринятые меры:
- kernel.core_pattern = / в /etc/sysctl.conf см. тж. altbug #32029
- * soft core 0 в /etc/security/limits.d/50-defaults.conf
- limited в ряде инитскриптов
- ulimit -Sc 0 >/dev/null 2>&1 в /etc/rc.d/rc.sysinit
- ulimit -Sc 0 >/dev/null 2>&1 в /etc/profile
Теперь осталось убрать лишние места выключения, чтобы была возможность включить.
Для появления корок (в процессах-наследниках того, в котором вызывается ulimit) надо как минимум:
- sysctl -w kernel.core_pattern=core
- ulimit -Sc unlimited
и, возможно, посмотреть /etc/sysconfig/limits да создать нужный /etc/sysconfig/limits.d/* (см. тж. это письмо насчёт apache2[2]).
Как включить сохранение coredump с systemd
Установить пакет systemd-coredump:
# apt-get install systemd-coredump
Включить coredump:
# systemctl start systemd-coredump.socket
Отключить soft limit на core dump size: закомментировать следующую строку в /etc/profile: 'ulimit -Sc 0 >/dev/null 2>&1', закомментрировать в файле /etc/security/limits.d/50-defaults.conf строку: '* soft core 0'
Перелогиниться, чтобы новый core limit вступил в силу для всех приложений по мере их запуска. ulimit -c должен после этого выдавать не 0, а unlimited. Для неграфической сессии можно вместо этого выполнить "ulimit -c unlimited".
После этого coredump-ы можно смотреть с помощью утилиты coredumpctl
$ coredumpctl list $ coredumpctl info
и сохранять с помощью
$ coredumpctl dump -o filename
Стоит учитывать, что coredump - это снимок всей доступной памяти процесса на момент его падения. Если в памяти приложения есть важная информация (например, пароли), то эта информация будет присутствовать и в coredump-файле.
Проверить, что всё настроено правильно, можно, например, с помощью следующей программы:
int main(int argc, char **argv) { char *r; do { r = *argv; } while (++argv); return 0; }
Собрав её
$ gcc segfault.c -g -o segfault
и запустив
$ ./segfault
В итоге, в coredumpctl должна появиться информация о сегфолте с доступным coredump'ом.
Пример вывода
$ coredumpctl TIME PID UID GID SIG COREFILE EXE Mon 2018-10-15 18:53:41 MSK 26285 500 500 11 present /home/test/segfault
$ coredumpctl info 26285 PID: 26285 (segfault) UID: 500 (test) GID: 500 (test) Signal: 11 (SEGV) Timestamp: Mon 2018-10-15 18:53:40 MSK (8s ago) Command Line: ./segfault Executable: /home/test/segfault Control Group: /user.slice/user-500.slice/session-4.scope Unit: session-4.scope Slice: user-500.slice Session: 4 Owner UID: 500 (test) Boot ID: d93a5fb5f9f44f25838f9d6d4e9486dc Machine ID: 30878809ed378edf3a2b36e25ad5fa70 Hostname: kwork-x86-64.localdomain Storage: /var/lib/systemd/coredump/core.segfault.500.d93a5fb5f9f44f25838f9d6d4e9486dc.26285.1539618820000000.lz4 Message: Process 26285 (segfault) of user 500 dumped core. Stack trace of thread 26285: #0 0x00000000004004e5 n/a (/home/test/segfault)
Как отключить сохранение coredump с systemd
Установить пакет systemd-settings-disable-dumpcore.