Bug 49446 - Программа не завершается и находится в бесконечном цикле
Summary: Программа не завершается и находится в бесконечном цикле
Status: CLOSED FIXED
Alias: None
Product: Sisyphus
Classification: Development
Component: osec (show other bugs)
Version: unstable
Hardware: x86_64 Linux
: P5 normal
Assignee: Alexey Gladkov
QA Contact: qa-sisyphus
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2024-02-19 09:18 MSK by Корытов Иван
Modified: 2024-02-24 21:23 MSK (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Корытов Иван 2024-02-19 09:18:46 MSK
При повреждении базы данных, программа пытается закрыть файл базы данных, который уже был ранее закрыт и входит в бесконечный цикл.

Команда, которая использовалась для запуска:
/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 не очищает передаваемый дескриптор при возникновении ошибки, т.к. он передается по значению, а не по ссылке.
Comment 1 obidinog@basealt.ru 2024-02-20 12:49:17 MSK
Стенд:
kworkstation-10.2.1-x86-64 Обновленный до Sisyphus
Пакет:
osec 1.3.1-alt3

Ошибка воспроизводится по вышеуказанным шагам
Comment 2 Alexey Gladkov 2024-02-23 17:47:19 MSK
Да, какой-то странный код. `goto end` у close вообще лишний.
Comment 3 Repository Robot 2024-02-24 21:23:57 MSK
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).