Features/Core

Материал из ALT Linux Wiki

Что такое файлы core?

Любая программа, исполняемая в среде Linux с виртуальной памятью, может совершить с памятью своего процесса действие, приводящее к нарушению её ожиданий от железа, а точнее — взаимных обязательств с ОС и железом. Например:

  1. обратиться к адресу памяти, на который ничего не отображено;
  2. произвести попытку записи по адресу из страницы без прав на запись (или прыгнуть в страницу без прав на исполнение);
  3. получить аппаратный отказ при работе с памятью;

и так далее. Это может зависеть от программного кода в процессе (примеры 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.

Примечания