Bug 60776
| Summary: | libnss-role: D-Bus падает при раннем старте, если Winbind ещё недоступен | ||||||||
|---|---|---|---|---|---|---|---|---|---|
| Product: | Sisyphus | Reporter: | Vladislav Glinkin <glinkinvd> | ||||||
| Component: | libnss-role | Assignee: | Evgeny Sinelnikov <sin> | ||||||
| Status: | CLOSED FIXED | QA Contact: | qa-sisyphus | ||||||
| Severity: | normal | ||||||||
| Priority: | P5 | CC: | lav, piastry, sin | ||||||
| Version: | unstable | ||||||||
| Hardware: | x86_64 | ||||||||
| OS: | Linux | ||||||||
| Attachments: |
|
||||||||
Created attachment 22327 [details]
libnss-role-winbind-enoent.patch
Спасибо за анализ, он подтверждается по коду: double free в parse_line() на ошибочной ветке для уже существующей роли. С частью про ENOENT в get_gid_by_groupname() есть две проблемы: 1. Регрессия в roleadd/roledel. getgrnam_r() возвращает ENOENT только когда последний модуль NSS вернул UNAVAIL. В этой конфигурации это значит, что имени нет в files, а winbind недоступен, то есть это доменные группы. Сейчас такая ошибка обрывает чтение /etc/role, и утилита завершается, не трогая файл. С патчем эти группы молча пропускаются при разборе, а roleadd/roledel затем перезаписывают /etc/role. В итоге роли и привилегии с доменными группами пропадают из файла, если утилиту запустить, пока winbind не работает. Для NSS-модуля пропуск правильный, для утилит, которые пишут файл, нет. 2. Исправление неполное. Числовые GID в /etc/role (например "1000:...") разрешаются через getgrgid_r() в librole_get_group_name(). Там ENOENT по-прежнему уходит в errno_to_result(), которая возвращает «сырое» ENOENT (2), а не код LIBROLE_*. Если такой GID не находится в files (например, доменный), одна такая строка при недоступном winbind обрывает разбор всего /etc/role. /etc/role.d при этом не читается, модуль возвращает NSS_STATUS_UNAVAIL, и служба теряет все ролевые группы. Падения уже нет, но результат неверный. Предлагаю обрабатывать ENOENT в одном месте, в errno_to_result(), и вернуть отдельный код «источник недоступен». NSS-модуль его пропускает, а roleadd/roledel на нём прерываются, не перезаписывая файл. При разборе кода нашлись и другие ошибки: запись за границу буфера в librole_get_group_name(), неработающая блокировка /etc/role, неатомарная запись файла, массивы long options без завершающего элемента и другие. Подготовлю исправления вместе с тестами в виде PR в https://github.com/Etersoft/libnss-role. libnss-role-0.6.0-alt1 -> sisyphus: Thu Oct 01 2026 Vitaly Lipatov <lav@altlinux.ru> 0.6.0-alt1 - new version 0.6.0 - fix double free in NSS module when winbind is not running yet (closes: #60776) - skip groups from unavailable group database (winbind) in NSS module, don't rewrite role files with such groups in roleadd/roledel - treat missing /etc/role as empty configuration - roledel: show the file in /etc/role.d defining the role - fix memory errors: buffer overflow in librole_get_group_name(), realloc() handling, long options, short role file names - fix /etc/role locking, replace role files atomically - add role(5) manpage, update documentation and help - extend unit tests, run them with ctest Исправлено в libnss-role-0.6.0-alt1 (задача #435056, уже в Sisyphus). Что сделано в upstream (https://github.com/Etersoft/libnss-role, релиз 0.6.0): - double free в parse_line() исправлен: список роли, уже добавленной в граф, на ошибочной ветке больше не освобождается (первая часть предложенного патча). - Недоступная база групп (ENOENT от winbind, пока winbindd не запущен) обрабатывается отдельно от отсутствующей группы: появился код LIBROLE_SOURCE_UNAVAIL, причём в errno_to_result(), так что он действует и для числовых GID через getgrgid_r(). NSS-модуль пропускает такие группы и выдаёт остальные роли. roleadd/roledel в этом случае отказываются перезаписывать /etc/role, чтобы не потерять записи с доменными группами (регрессия исходного варианта патча, см. комментарий выше). rolelst показывает, что удалось разрешить, и возвращает ошибку. Проверено в контейнере ALT Sisyphus с "group: files role winbind" при незапущенном winbindd: - на 0.5.6-alt4 падение воспроизводится: id и getent initgroups завершаются с "free(): double free detected"; - на 0.6.0-alt1 падения нет, роли разрешаются, valgrind чистый. Кроме того, в 0.6.0 исправлены ошибки работы с памятью, блокировка /etc/role (теперь файл заменяется атомарно), отсутствующий /etc/role считается пустым, добавлена man-страница role(5). |

Description
Vladislav Glinkin 2026-10-01 15:58:21 MSK