Использование санитайзера дескрипторов

30 сентября 2026

ID debugging_handle_sanitizer

Санитайзер дескрипторов позволяет обнаружить следующие проблемы:

  • использование недействительных дескрипторов (закрытых и несозданных);
  • утечку дескрипторов (наличие незакрытых дескрипторов, которые больше не требуются).

Санитайзер дескрипторов нужно активировать отдельно в каждом процессе, для которого требуется выполнить проверки на использование недействительных дескрипторов и/или утечку дескрипторов. Чтобы активировать санитайзер дескрипторов, нужно передать процессу переменную окружения KOS_HANDLE_SANITIZER со значением True.

Пример передачи процессу переменной окружения KOS_HANDLE_SANITIZER при упаковке в KPA-пакет с помощью переменной окружения в параметре RUN_CONFIGURATION->ENV CMake-команды add_kpa_component ():

add_kpa_component (${PACKAGE}

RUN_CONFIGURATION "default"

...

ENV "KOS_HANDLE_SANITIZER=True")

Сообщения санитайзера дескрипторов об обнаруженных проблемах передаются в систему журналирования, которая выводит диагностические данные, например, через UART или сохраняет в файл. Сведения о каждой обнаруженной проблеме содержат краткое описание проблемы, значение дескриптора, а также данные обратной трассировки стека, включающие сведения о последовательностях вызовов функций, в результате которых выполнены операции из следующего набора: создание дескриптора, закрытие дескриптора, использование недействительного дескриптора. Какие именно операции из этого набора отражаются в данных обратной трассировки стека зависит от того, какая проблема была обнаружена.

Анализ данных обратной трассировки стека

Данные обратной трассировки стека имеют следующий вид:

...

[2025-12-02T07:49:39.334][Error][Hello][22:22][HSAN] 0xbab42e80363 <KnHandleConnectEx+0xbab42cbc073> at helloe [relocBase] 0xbab42cbc000 [buildId] da0a1724ad9f32798ee18c46df9340d7e1bf2c5a

[2025-12-02T07:49:39.337][Error][Hello][22:22][HSAN] 0xbab42e803e3 <KnHandleConnect+0xbab42cbc043> at helloe [relocBase] 0xbab42cbc000 [buildId] da0a1724ad9f32798ee18c46df9340d7e1bf2c5a

[2025-12-02T07:49:39.341][Error][Hello][22:22][HSAN] 0xbab42e80c3e <KnHandleCreateListener+0xbab42cbc04e> at helloe [relocBase] 0xbab42cbc000 [buildId] da0a1724ad9f32798ee18c46df9340d7e1bf2c5a

...

Здесь код функции KnHandleCreateListener(), размещенный в памяти процесса по адресу 0xbab42e80c3e, вызвал функцию KnHandleConnect(), а код функции KnHandleConnect(), размещенный в памяти процесса по адресу 0xbab42e803e3, вызвал функцию KnHandleConnectEx(). (Запись вида <имя функции>+0x<смещение> означает адрес внутри кода функции. Например, запись KnHandleCreateListener+0xbab42cbc04e означает адрес внутри кода функции KnHandleCreateListener(), смещенный относительно адреса начала кода этой функции на 0xbab42cbc04e байт. Запись KnHandleCreateListener+0xbab42cbc04e соответствует адресу 0xbab42e80c3e.) В результате применения ASLR адреса памяти увеличены на значение смещения загрузки ELF-образа ([relocBase] 0xbab42cbc000).

Данные обратной трассировки стека не будут содержать имена тех функций, сведения о которых отсутствуют в таблице символов .symtab и таблице строк .strtab, загруженных в память процесса. Подробнее см. "Анализ данных обратной трассировки стека при аварийном завершении процесса".

Обнаружение использования недействительных дескрипторов

Обнаружение использования недействительных дескрипторов выполняется автоматически во всех процессах, в которых активирован санитайзер дескрипторов. Если обнаружено использование закрытого дескриптора, данные обратной трассировки стека включают сведения о последовательностях вызовов функций, в результате которых дескриптор был создан, закрыт и использовался после закрытия. Если обнаружено использование несозданного дескриптора, данные обратной трассировки стека включают сведение о последовательности вызовов функций, в результате которой использовался несозданный дескриптор.

Функциональность для обнаружения использования недействительных дескрипторов можно отключить, если задать параметр запуска ядра handle.disable_detect_invalid_access.

Обнаружение утечки дескрипторов

Для обнаружения утечки дескрипторов предназначен API, который определен в заголовочном файле sysroot-*-kos/include/hsan/leak_control.h из состава KasperskyOS SDK.

API позволяет обнаружить утечку дескрипторов как в процессе, вызывающем функции API, так и в процессах, внешних по отношению к этому процессу. В первом случае нужно активировать санитайзер дескрипторов в процессе, вызывающем функции API. Во втором случае требуется активировать санитайзер дескрипторов только во внешних процессах. Также во втором случае необходимо статически создать IPC-каналы от процесса, вызывающего функции API, и внешних процессов к процессу системной программы DCM.

Проверка внешних процессов на утечку дескрипторов может потребоваться, если эти процессы каким-либо образом связаны с процессом, вызывающим функции API. Например, если процесс, вызывающий функции API, взаимодействует со внешними процессами через IPC, и процесс, вызывающий функции API, является клиентским, а внешние процессы являются серверными, то может потребоваться проверить, что в серверных процессах закрыты все дескрипторы, созданные на определенной стадии исполнения программы в клиентском процессе.

Сведения о функциях API приведены в таблице ниже.

Для обнаружения утечки дескрипторов во внешних процессах предназначены функции HandleLeakControlExt*().

Типовой сценарий использования API включает следующие шаги:

  1. [Опционально] Сформировать набор внешних процессов, для которых требуется выполнить проверку на утечку дескрипторов.

    Этот шаг нужно выполнить, если необходима проверка внешних процессов.

    Чтобы добавить процесс в набор, нужно вызвать функцию HandleLeakControlExtAddTask().

  2. Запустить отслеживание создания и закрытия дескрипторов вызовом функции HandleLeakControlStart() или HandleLeakControlExtStart().

    Отслеживаются только те дескрипторы, которые были созданы после выполнения этого шага и до выполнения шага 4.

  3. Проверить наличие незакрытых отслеживаемых дескрипторов.

    Чтобы выполнить этот шаг, нужно использовать функции HandleLeakControlCheck*() или HandleLeakControlExtCheck*().

    Функция HandleLeakControlCheck() передает через выходной параметр leakDetected булевое значение, которое отражает, были ли обнаружены незакрытые отслеживаемые дескрипторы в вызывающем процессе на момент вызова этой функции. Если незакрытые отслеживаемые дескрипторы были обнаружены, то сообщения об утечке дескрипторов передаются в систему журналирования. Данные обратной трассировки включают сведения о последовательностях вызовов функций, в результате которых незакрытые отслеживаемые дескрипторы были созданы.

    Функция HandleLeakControlCheckNoPrint() отличается от функции HandleLeakControlCheck() только тем, что сообщения об утечке дескрипторов не передаются в систему журналирования.

    Функция HandleLeakControlCheckTimeouted() проверяет наличие незакрытых отслеживаемых дескрипторов в вызывающем процессе на момент вызова этой функции и в случае обнаружения не возвращает управление сразу, а запускает циклическую проверку, ожидая закрытия отслеживаемых дескрипторов не более заданного в параметре timeoutMs времени. Через выходной параметр leakDetected функция HandleLeakControlCheckTimeouted() передает булевое значение, которое отражает, были ли обнаружены незакрытые отслеживаемые дескрипторы в вызывающем процессе на момент выхода из функции. Если незакрытые отслеживаемые дескрипторы были обнаружены на момент выхода из функции, то в систему журналирования передаются сообщения с такими же сведениями, что и при использовании функции HandleLeakControlCheck().

    Функции HandleLeakControlExtCheck*() отличаются от функций HandleLeakControlCheck*() только тем, что выполняют проверку не в вызывающем процессе, а в одном или нескольких процессах, внешних для вызывающего.

  4. Остановить отслеживание создания и закрытия дескрипторов вызовом функции HandleLeakControlStop() или HandleLeakControlExtStop().
  5. [Опционально] Удалить процессы из набора внешних процессов, для которых выполнялась проверка на утечку дескрипторов.

    Этот шаг нужно выполнить, если выполнялась проверка внешних процессов.

    Чтобы удалить процесс из набора, нужно вызвать функцию HandleLeakControlExtRemoveTask().

    Функции leak_control.h

Использование вспомогательных инструментов для обработки диагностических данных

В составе KasperskyOS Community Edition SDK поставляется скрипт toolchain/bin/parse_hsan_dump.py, который выполняет следующие операции:

  • Отбор сообщений санитайзера дескрипторов из диагностических данных.
  • [Опционально] Преобразование данных обратной трассировки стека, а именно замену записей вида <имя функции>+0x<смещение> на записи вида <имя функции> at <абсолютный путь к файлу исходного кода>:<номер строки>:<отступ строки> с использованием утилиты toolchain/bin/llvm-symbolizer из состава KasperskyOS Community Edition SDK.

    Для выполнения этого преобразования нужно создать ELF-файлы (исполняемые файлы, динамические библиотеки) с отладочными данными либо ELF-файлы без отладочных данных, но ассоциированные со специальными файлами, в которых отдельно сохранены отладочные данные. (О файлах с отладочными данными см. "Отладка программ в решении на базе KasperskyOS".)

    После преобразования данные обратной трассировки стека содержат адреса вызовов функций, уменьшенные на значение смещения загрузки ELF-образа. (Это смещение появляется в результате применения ASLR.)

Синтаксис shell-команды для запуска скрипта parse_hsan_dump.py:

parse_hsan_dump.py [-s <PATH_TO_LLVM-SYMBOLIZER> -b <PATH_TO_ELF_FILES>]

Параметры:

  • -s <PATH_TO_LLVM-SYMBOLIZER> – абсолютный путь к исполняемому файлу утилиты llvm-symbolizer.
  • -b <PATH_TO_ELF_FILES> – путь к директории с исполняемыми файлами и динамическими библиотеками.

    В этом параметре нужно указать путь к директории, в которой находятся ELF-файлы с отладочными данными (либо ассоциированные с специальными файлами с отладочными данными). ELF-файлы могут находится в директориях, которые вложены в заданную. Например, можно указать путь к директории build из состава CMake-проекта решения.

    Можно указать абсолютный путь или путь относительно текущей директории.

Сценарий использования скрипта parse_hsan_dump.py включает следующие шаги:

  1. Сохранить диагностические данные в файл.

    Пример:

    cmake --build build --target sim | tee log.txt

  2. Передать диагностические данные скрипту parse_hsan_dump.py через стандартный поток ввода.

    Пример:

    cat log.txt | /opt/KasperskyOS-Community-Edition-<platform>-<version>/toolchain/bin/parse_hsan_dump.py -s /opt/KasperskyOS-Community-Edition-<platform>-<version>/toolchain/bin/llvm-symbolizer -b home/user/project/build

Вам помогла эта статья?
Что нам нужно улучшить?
Спасибо за ваш отзыв, вы помогаете нам становиться лучше!
Спасибо за ваш отзыв, вы помогаете нам становиться лучше!