Подробный гайд по устранению ошибки parsec_file_mprotect в Astra Linux SE
Ошибке связана с Astra Linux Special Edition и модулем безопасности PARSEC (не путать с приложением Parsec для удалённого доступа).
1. Что это за ошибка
Сообщение в журнале аудита выглядит так:
type=AVC msg=audit(1734413451.012:20444): parsec=denied fn=parsec_file_mprotect requested=x pid=9108 comm="a.out"
Эта ошибка означает, что модуль безопасности PARSEC, встроенный в ядро Astra Linux Special Edition, заблокировал попытку программы разрешить исполнение кода в области памяти, выделенной для стека. Другими словами, программа попыталась выполнить системный вызов mprotect() с флагом PROT_EXEC для стековой области, и получила отказ.
Часто сопровождается пользовательской ошибкой:
cannot enable executable stack as shared object requires: Permission denied
2. Почему это происходит
2.1. Механизм защиты
Начиная с оперативного обновления 1.7.6 (БЮЛЛЕТЕНЬ № 2024-0830SE17), в Astra Linux Special Edition был включён механизм защиты от исполнения областей памяти в стеке программ.
Этот механизм:
- Делает невозможным выполнение кода из разделяемых библиотек на страницах памяти, помеченных «только для данных», включая страницы стека.
- Не предотвращает размещение эксплойта в памяти, но не позволяет установить разрешение на исполнение кода эксплойта.
- Управляется параметром ядра
parsec.execstack, доступным начиная с обновления 1.7.6.
2.2. Что делает PARSEC
PARSEC — это модуль ядра, реализующий мандатное управление доступом (МРД) на уровне ядра. Он контролирует системные вызовы, включая mprotect(), и при обнаружении попытки сделать стек исполняемым — блокирует операцию и записывает событие в журнал аудита.
2.3. Какие программы подвержены
Ошибка возникает у ПО, которое:
- Скомпилировано с флагом компоновщика
-z execstack. - Использует JIT-компиляцию или динамическую генерацию кода.
- Содержит устаревшие библиотеки, требующие исполняемый стек.
- Примеры: некоторые версии Wine, старые игры, проприетарные драйверы, СКЗИ (например, «Континент-АП»), Guardant-защита.
3. Диагностика
3.1. Проверка журнала аудита
Убедитесь, что ошибка действительно связана с mprotect:
sudo /usr/sbin/ausearch -m AVC | grep mprotect
Ожидаемый вывод:
type=AVC msg=audit(...): parsec=denied fn=parsec_file_mprotect requested=x pid=XXXX comm="имя_программы"
3.2. Проверка текущего значения параметра
Посмотрите текущее значение параметра загруженного ядра:
cat /sys/module/parsec/parameters/execstack
0— защита включена (по умолчанию).1— защита выключена.
3.3. Трассировка системных вызовов
Для выявления конкретного вызова mprotect(), вызывающего ошибку, используйте strace:
strace -f -e trace=mprotect ./ваша_программа 2>&1 | grep -i denied
3.4. Проверка ELF-заголовков
Проверьте, требует ли бинарный файл исполняемый стек:
readelf -l /путь/к/бинарнику | grep GNU_STACK
Если вывод содержит RWE (Read, Write, Execute) — программа требует исполняемый стек.
# Проверка разделяемых библиотек
readelf -l /путь/к/библиотеке.so | grep GNU_STACK
4. Решения
Решение 1: Отключение контроля исполнения стека (временное)
ВНИМАНИЕ:
Данное изменение снижает защищённость операционной системы. Применяйте только при невозможности других решений и осознанно.
Шаг 1. Откройте конфигурацию GRUB:
sudo nano /etc/default/grub
Шаг 2. Найдите строку GRUB_CMDLINE_LINUX_DEFAULT и добавьте параметр parsec.execstack=1:
GRUB_CMDLINE_LINUX_DEFAULT="parsec.mac=1 quiet net.ifnames=0 parsec.execstack=1"
Примечание:
parsec.mac=0 полностью отключает мандатное управление доступом. Если вам нужна только разблокировка стека — оставьте parsec.mac=1.
Шаг 3. Обновите конфигурацию загрузчика:
sudo update-grub
Шаг 4. Перезагрузите компьютер:
sudo reboot
Шаг 5. После перезагрузки проверьте:
cat /sys/module/parsec/parameters/execstack
# Должно быть: 1
Решение 2: Перекомпиляция ПО без execstack (рекомендуемое)
Если вы разработчик или можете пересобрать ПО, уберите флаг -z execstack из параметров компоновщика:
# Вместо:
gcc -z execstack -o program program.c
# Используйте:
gcc -z noexecstack -o program program.c
Или просто не передавайте -z execstack — по умолчанию в современных инструментах стек неисполняемый.
Для проверки и исправления уже собранных ELF-файлов используйте execstack:
# Проверить
execstack -q /путь/к/бинарнику
# Очистить флаг исполняемого стека
sudo execstack -c /путь/к/бинарнику
Решение 3: Использование paxctl / patchelf (для отдельных бинарников)
Если нельзя пересобрать, но можно модифицировать бинарник:
# Установить утилиту
sudo apt install execstack
# Снять флаг исполняемого стека
sudo execstack -c /путь/к/проблемной_библиотеке.so
Решение 4: Обращение к разработчику ПО
Чек-лист действий от Astra Linux:
- Исключить использование ПО, генерирующего ошибку, как потенциально небезопасного.
- Обратиться к разработчикам для доработки ПО с целью устранения небезопасных вызовов
mprotect(). - Только при невозможности вышеуказанного — отключить контроль (Решение 1).
5. Рекомендации для разработчиков
При разработке ПО для Astra Linux Special Edition:
| Что делать | Что НЕ делать |
|---|---|
Компилировать без -z execstack |
Не использовать -z execstack при сборке |
Использовать mmap() с PROT_READ\|PROT_WRITE для данных |
Не вызывать mprotect() с PROT_EXEC для стека |
Для JIT — выделять память через mmap(PROT_READ\|PROT_WRITE\|PROT_EXEC) отдельно |
Не размещать исполняемый код в стеке |
Тестировать на Astra Linux с parsec.execstack=0 |
Не игнорировать предупреждения линкера |
Для JIT-компиляторов правильный паттерн:
// Выделяем отдельную область памяти для кода
void *code = mmap(NULL, size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
// Записываем код
memcpy(code, generated_code, size);
// Делаем исполняемым (это НЕ стек — PARSEC не блокирует)
mprotect(code, size, PROT_READ | PROT_EXEC);
6. Возврат к безопасной конфигурации
После обновления или замены проблемного ПО обязательно верните защиту:
Шаг 1. Откройте /etc/default/grub:
sudo nano /etc/default/grub
Шаг 2. Уберите parsec.execstack=1 или замените на 0:
GRUB_CMDLINE_LINUX_DEFAULT="parsec.mac=1 quiet net.ifnames=0 parsec.execstack=0"
Шаг 3. Обновите и перезагрузите:
sudo update-grub
sudo reboot
Шаг 4. Проверьте:
cat /sys/module/parsec/parameters/execstack
# Должно быть: 0
7. Сводная таблица параметров PARSEC
| Параметр | Назначение | Значения | По умолчанию |
|---|---|---|---|
parsec.execstack |
Защита от исполнения стека | 0 (вкл.) / 1 (выкл.) |
0 |
parsec.mac |
Мандатное управление доступом | 0 / 1 |
1 |
parsec.max_ilev |
Максимальный уровень целостности | 0–4294967295 | 63 |
parsec.enable_exec_on_fuse |
Запуск с FUSE-файловых систем | 0 / 1 |
0 |
Актуальные значения всех параметров доступны в /sys/module/parsec/parameters/
8. Связанные ошибки и дополнительные материалы
- Ошибка
Permission deniedпри работе с СКЗИ «Континент-АП» на Astra Linux 1.7.6+ — требуетparsec.execstack=1 - Ошибка
Permission deniedдляlibprotectstorage64.so(Guardant) — аналогичная причина - Ошибка
mprotect failed in ExecutableAllocator::makeExecutableв Qt/Chromium-приложениях на Red Hat 9 / Astra Linux - Полное описание параметров модуля PARSEC — wiki.astralinux.ru, pageId=27361844
- Описание механизма защиты — wiki.astralinux.ru, pageId=338008842
Информация предоставлена в ознакомительных целях. Применение описанных настроек в системах, должно осуществляться только после согласования с ответственными за информационную безопасность и в соответствии с требованиями ФСТЭК, ФСБ и иных уполномоченных органов.