При повреждении базы данных, программа пытается закрыть файл базы данных, который уже был ранее закрыт и входит в бесконечный цикл. Команда, которая использовалась для запуска: /usr/bin/osec -X /etc/osec/exclude.conf -D /var/lib/osec -f /etc/osec/dirs.conf Версия: 1.3.1-alt2 Шаги для воспроизведения: 1. Установить osec и запустить, чтобы создать базы данных файлов 2. Намеренно повредить одну из баз данных dd if=/dev/zero of=/var/lib/osec/osec.cdb.%2Flib count=10K 3. Запустить программу повторно Ожидаемый результат: программа завершается успешно или с предупреждениями Полученный результат: программа не завершается и бесконечно выводит сообщение об ошибке > osec: file not look like osec database: /var/lib/osec/osec.cdb.%2Flib > osec: close: (null): Bad file descriptor > osec: close: /var/lib/osec/osec.cdb.%2Flib :Bad file descriptor > osec: close: /var/lib/osec/osec.cdb.%2Flib :Bad file descriptor > ... > osec: close: /var/lib/osec/osec.cdb.%2Flib :Bad file descriptor Почему изначально были повреждены базы данных - неизвестно. Один из файлов состоял полностью из нулей, другой - частично. Описание проблемы в файле src/osec.c: Программа проверяет, что открываемый файл является базой данных и из-за неверных данных переходит на метку end. > if (!compat_db_version(old_fd)) { > osec_error("file not look like osec database: %s", old_dbname); > goto end; > } На метке end она успешно закрывает файл с путем из переменной old_dbname и дескриптором old_fd: > if (old_fd != -1 && close(old_fd) == -1) { > osec_error("close: %s :%m", old_dbname); > goto end; > } Затем, программа пытается закрыть файл с путем из переменной new_dbname и дескриптором new_fd: > if (close(new_fd) == -1) { > osec_error("close: %s: %m", new_dbname); > goto end; > } Закрытие файла завершается с ошибкой, т.к. и дескриптор, и путь "new" заданы пустыми в начале функции: > new_fd = old_fd = -1; > new_dbname = NULL; После вывода сообщения программа переходит к метке end. Так как файл "old" уже успешно закрыт, а переменная old_fd не очищена, то функция close завершается с оибкой и выводится сообщение уже с путем old_dbname. И программа вновь переходит к метке end, не очищая переменные с дескрипторами, что приводит к бесконечному циклу (переходу к метке). Функция close не очищает передаваемый дескриптор при возникновении ошибки, т.к. он передается по значению, а не по ссылке.
Стенд: kworkstation-10.2.1-x86-64 Обновленный до Sisyphus Пакет: osec 1.3.1-alt3 Ошибка воспроизводится по вышеуказанным шагам
Да, какой-то странный код. `goto end` у close вообще лишний.
osec-1.3.2-alt1 -> sisyphus: Sat Feb 24 2024 Alexey Gladkov <legion@altlinux.ru> 1.3.2-alt1 - New version (1.3.2). - Fix infinite loop (ALT#49446).