Содержание
KnHandleClose()
Функция объявлена в файле coresrv/handle/handle_api.h
.
Retcode KnHandleClose(Handle handle);
Функция удаляет дескриптор handle
.
В случае успеха функция возвращает rcOk, иначе возвращает код ошибки.
Удаление дескриптора не делает недействительными его предков и потомков (в отличие от отзыва дескриптора, который делает недействительными его потомков – см. KnHandleRevoke()
и KnHandleRevokeSubtree()
). Удаление дескриптора также не нарушает целостность дерева наследования дескрипторов. Место удаленного дескриптора занимает его предок – он становится непосредственным предком потомков удаленного дескриптора.
KnHandleCreateBadge()
Функция объявлена в файле coresrv/handle/handle_api.h
.
Retcode KnHandleCreateBadge(Notice notice, rtl_uintptr_t eventId,
void *context, Handle *handle);
Функция создает объект контекста передачи ресурса для контекста передачи ресурса context
и настраивает приемник уведомлений notice
на прием уведомлений об этом объекте. Приемник уведомлений настраивается на прием уведомлений о событиях, которые соответствуют флагам маски событий EVENT_OBJECT_DESTROYED
и EVENT_BADGE_CLOSED
.
Входной параметр eventId
задает идентификатор записи вида "ресурс – маска событий" в приемнике уведомлений.
Выходной параметр handle
содержит дескриптор объекта контекста передачи ресурса.
В случае успеха функция возвращает rcOk, иначе возвращает код ошибки.
В началоKnHandleCreateUserObject()
Функция объявлена в файле coresrv/handle/handle_api.h
.
Retcode KnHandleCreateUserObject(rtl_uint32_t type, rtl_uint32_t rights,
void *context, Handle *handle);
Функция создает дескриптор handle
типа type
с маской прав rights
.
Параметр type
может принимать значения от HANDLE_TYPE_USER_FIRST
до HANDLE_TYPE_USER_LAST
.
Макросы HANDLE_TYPE_USER_FIRST
и HANDLE_TYPE_USER_LAST
определены в заголовочном файле handle/handletype.h
.
Параметр context
задает контекст пользовательского ресурса. В случае успеха функция возвращает rcOk, иначе возвращает код ошибки.
Пример
Retcode ServerPortInit(ServerPort *serverPort)
{
Retcode rc = rcInvalidArgument;
Notice serverEventNotice;
rc = KnHandleCreateUserObject(HANDLE_TYPE_USER_FIRST, OCAP_HANDLE_SET_EVENT | OCAP_HANDLE_GET_EVENT,
serverPort, &serverPort->handle);
if (rc == rcOk) {
KosRefObject(serverPort);
rc = KnNoticeSubscribeToObject(serverEventNotice,
serverPort->handle,
EVENT_OBJECT_DESTROYED,
(rtl_uintptr_t) serverPort);
if (rc != rcOk) {
KosPutObject(serverPort);
KnHandleClose(serverPort->handle);
serverPort->handle = INVALID_HANDLE;
}
}
return rc;
}
KnHandleRevoke()
Функция объявлена в файле coresrv/handle/handle_api.h
.
Retcode KnHandleRevoke(Handle handle);
Функция удаляет дескриптор handle
и отзывает всех его потомков.
В случае успеха функция возвращает rcOk, иначе возвращает код ошибки.
Отзыв дескрипторов не удаляет их, но через отозванные дескрипторы невозможно обращаться к ресурсам. Любая функция, которая принимает дескриптор, завершается с ошибкой rcHandleRevoked, если эта функция вызывается с отозванным дескриптором.
KnHandleRevokeSubtree()
Функция объявлена в файле coresrv/handle/handle_api.h
.
Retcode KnHandleRevokeSubtree(Handle handle, Handle badge);
Функция отзывает дескрипторы, которые образуют поддерево наследования дескриптора handle
.
Корневым узлом поддерева наследования является дескриптор, который порожден передачей дескриптора handle
в ассоциации с объектом контекста передачи ресурса badge
.
В случае успеха функция возвращает rcOk, иначе возвращает код ошибки.
Отзыв дескрипторов не удаляет их, но через отозванные дескрипторы невозможно обращаться к ресурсам. Любая функция, которая принимает дескриптор, завершается с ошибкой rcHandleRevoked, если эта функция вызывается с отозванным дескриптором.
nk_get_badge_op()
Функция объявлена в файле nk/types.h
.
static inline
nk_err_t nk_get_badge_op(const nk_handle_desc_t *desc,
nk_rights_t operation,
nk_badge_t *badge);
Функция извлекает указатель на контекст передачи ресурса badge
из транспортного контейнера дескриптора desc
, если в маске прав, которая помещена в транспортном контейнере дескриптора desc
, установлены флаги operation
.
В случае успеха функция возвращает NK_EOK, иначе возвращает код ошибки.
В началоnk_is_handle_dereferenced()
Функция объявлена в файле nk/types.h
.
static inline
nk_bool_t nk_is_handle_dereferenced(const nk_handle_desc_t *desc);
Функция возвращает отличное от нуля значение, если дескриптор в транспортном контейнере дескриптора desc
получен в результате операции разыменования дескриптора.
Функция возвращает нуль, если дескриптор в транспортном контейнере дескриптора desc
получен в результате операции передачи дескриптора.
Управление дескрипторами
Для управления дескрипторами используются функции менеджера дескрипторов (Handle Manager) и подсистемы уведомлений (Notification Subsystem).
Менеджер дескрипторов представлен для пользователя следующими файлами:
coresrv/handle/handle_api.h
– заголовочный файл библиотекиlibkos
;services/handle/Handle.idl
– описание IPC-интерфейса менеджера дескрипторов на языке IDL.
Подсистема уведомлений представлена для пользователя следующими файлами:
coresrv/handle/notice_api.h
– заголовочный файл библиотекиlibkos
;services/handle/Notice.idl
– описание IPC-интерфейса подсистемы уведомлений на языке IDL.
Маска прав дескриптора
Маска прав дескриптора имеет размер 32 бита и состоит из общей и специальной части. Общая часть описывает права, неспецифичные для любых ресурсов (флаги этих прав определены в заголовочном файле services/ocap.h
). Например, в общей части находится флаг OCAP_HANDLE_TRANSFER
, который определяет право на передачу дескриптора. Специальная часть описывает права, специфичные для пользовательского или системного ресурса. Флаги прав специальной части для системных ресурсов определены в заголовочном файле services/ocap.h
. Структура специальной части для пользовательских ресурсов определяется поставщиком ресурсов с использованием макроса OCAP_HANDLE_SPEC()
, который определен в заголовочном файле services/ocap.h
. Поставщику ресурсов необходимо экспортировать публичные заголовочные файлы с описанием структуры специальной части.
При создании дескриптора системного ресурса маска прав задается ядром KasperskyOS, которое применяет маски прав из заголовочного файла services/ocap.h
. Применяются маски прав с именами вида OCAP_*_FULL
(например, OCAP_IOPORT_FULL
, OCAP_TASK_FULL
, OCAP_FILE_FULL
) и вида OCAP_IPC_*
(например, OCAP_IPC_SERVER
, OCAP_IPC_LISTENER
, OCAP_IPC_CLIENT
).
При создании дескриптора пользовательского ресурса маска прав задается пользователем.
При передаче дескриптора маска прав задается пользователем, но передаваемые права доступа не могут быть повышены относительно прав доступа, которые имеет процесс.
В началоСоздание дескрипторов
Дескрипторы пользовательских ресурсов создаются поставщиками ресурсов. Для создания дескрипторов пользовательских ресурсов используется функция KnHandleCreateUserObject()
, которая объявлена в заголовочном файле coresrv/handle/handle_api.h
.
handle_api.h (фрагмент)
/**
* Функция создает дескриптор handle типа type с маской прав rights.
* Параметр type может принимать значения от HANDLE_TYPE_USER_FIRST до
* HANDLE_TYPE_USER_LAST. Макросы HANDLE_TYPE_USER_FIRST и HANDLE_TYPE_USER_LAST
* определены в заголовочном файле handletype.h. Параметр context задает контекст
* пользовательского ресурса.
* В случае успеха функция возвращает rcOk, иначе возвращает код ошибки.
*/
Retcode KnHandleCreateUserObject(rtl_uint32_t type, rtl_uint32_t rights,
void *context, Handle *handle);
Контекст пользовательского ресурса – данные, позволяющие поставщику ресурса идентифицировать ресурс и его состояние, когда запрашивается доступ к ресурсу другими программами. В общем случае это набор разнотипных данных (структура). Например, для файла контекст может включать имя, путь, положение курсора. Контекст пользовательского ресурса используется в качестве контекста передачи ресурса или совместно с несколькими контекстами передачи ресурса.
Параметр type
функции KnHandleCreateUserObject()
зарезервирован для возможного использования в будущем и не влияет на ее поведение, но должен принимать значение из интервала, указанного в комментарии к функции.
О маске прав дескриптора см. "Маска прав дескриптора".
В началоПередача дескрипторов
Общие сведения
Передача дескрипторов между программами осуществляется для того, чтобы клиенты (программы, которые используют ресурсы) получали доступ к требуемым ресурсам. По причине локальности дескрипторов передача дескриптора инициирует на стороне принимающей программы создание дескриптора из ее пространства дескрипторов. Этот дескриптор регистрируется как потомок отправленного дескриптора и идентифицирует тот же ресурс.
Один дескриптор может быть передан многократно одной или нескольким программам. Каждая передача порождает нового потомка переданного дескриптора на стороне принимающей программы. Программа может передавать дескрипторы, которые она получила от других программ или ядра KasperskyOS (при создании дескрипторов системных ресурсов). Поэтому у дескриптора может быть несколько поколений потомков. Иерархия порождения дескрипторов для каждого ресурса хранится в ядре KasperskyOS в виде дерева наследования дескрипторов.
Программа может передавать дескрипторы как пользовательских, так и системных ресурсов, если права доступа этих дескрипторов разрешают выполнять передачу. У потомка может быть меньше прав доступа, чем у предка. Например, передающая программа имеет права доступа к файлу на чтение и запись, а передает права доступа только на чтение. Передающая программа также может запретить принимающей программе дальнейшую передачу дескриптора. Права доступа задаются в передаваемой маске прав дескриптора.
Условия для передачи дескрипторов
Чтобы программы могли передавать дескрипторы между собой, должны выполняться следующие условия:
- Между программами создан IPC-канал.
- Политика безопасности решения (
security.psl
) разрешает взаимодействие программ. - Реализованы интерфейсные методы для передачи дескрипторов.
- Программа-клиент получила идентификатор службы (RIID) программы-сервера с методами для передачи дескрипторов.
Интерфейсные методы для передачи дескрипторов объявляются в IDL-описании с входными (in
) и/или выходными (out
) параметрами типа Handle
. Методы с входными параметрами типа Handle
предназначены для передачи дескрипторов от программы-клиента программе-серверу. Методы с выходными параметрами типа Handle
предназначены для передачи дескрипторов от программы-сервера программе-клиенту. Для одного метода может быть объявлено не более семи входных и семи выходных параметров типа Handle
.
Пример IDL-описания, где объявлены интерфейсные методы для передачи дескрипторов:
package IpcTransfer
interface {
PublishResource1(in Handle handle, out UInt32 result);
PublishResource7(in Handle handle1, in Handle handle2,
in Handle handle3, in Handle handle4,
in Handle handle5, in Handle handle6,
in Handle handle7, out UInt32 result);
OpenResource(in UInt32 ID, out Handle handle);
}
Для каждого параметра типа Handle
компилятор NK генерирует в структурах запросов *_req
и/или ответов *_res
поле типа nk_handle_desc_t
(далее также транспортный контейнер дескриптора). Этот тип объявлен в заголовочном файле nk/types.h
и представляет собой структуру, состоящую из трех полей: поля дескриптора handle
, поля маски прав дескриптора rights
и поля контекста передачи ресурса badge
.
Контекст передачи ресурса
Контекст передачи ресурса – данные, позволяющие программе-серверу идентифицировать ресурс и его состояние, когда запрашивается доступ к ресурсу через потомков переданного дескриптора. В общем случае это набор разнотипных данных (структура). Например, для файла контекст передачи может включать имя, путь, положение курсора. Программа-сервер получает указатель на контекст передачи ресурса при разыменовании дескриптора.
Программа-сервер независимо от того, является ли она поставщиком ресурса или нет, может ассоциировать каждую передачу дескриптора с отдельным контекстом передачи ресурса. Этот контекст передачи ресурса связывается только с теми потомками дескриптора (поддеревом наследования дескриптора), которые порождены в результате конкретной его передачи. Это позволяет определять состояние ресурса по отношению к отдельной передаче дескриптора этого ресурса. Например, в случае множественного доступа к одному файлу контекст передачи файла позволяет определить, какому именно открытию этого файла соответствует полученный запрос.
Если программа-сервер является поставщиком ресурса, то по умолчанию каждая передача дескриптора этого ресурса ассоциируется с контекстом пользовательского ресурса. То есть контекст пользовательского ресурса используется в качестве контекста передачи ресурса для каждой передачи дескриптора, если эта передача не ассоциируется с отдельным контекстом передачи ресурса.
Программа-сервер, которая является поставщиком ресурса, может использовать совместно контекст пользовательского ресурса и контексты передачи ресурса. Например, имя, путь и размер файла хранятся в контексте пользовательского ресурса, а положение курсора хранится в нескольких контекстах передачи ресурса, так как каждый клиент может работать с разными частями файла. Технически совместное использование контекста пользовательского ресурса и контекстов передачи ресурса достигается тем, что контексты передачи ресурса хранят указатель на контекст пользовательского ресурса.
Если программа-клиент использует несколько разнотипных ресурсов программы-сервера, контексты передачи ресурсов (или контексты пользовательских ресурсов, если они используются в качестве контекстов передачи ресурсов) должны быть типизированными объектами KosObject
. Это нужно, чтобы программа-сервер могла проверить, что программа-клиент при использовании ресурса передала в интерфейсный метод дескриптор того ресурса, который соответствует этому методу. Такая проверка требуется, поскольку программа-клиент может ошибочно передать в интерфейсный метод дескриптор ресурса, который не соответствует этому методу. Например, программа-клиент получила дескриптор файла и передала его в интерфейсный метод для работы с томами.
Чтобы ассоциировать передачу дескриптора с контекстом передачи ресурса, программа-сервер помещает в поле badge
структуры nk_handle_desc_t
дескриптор объекта контекста передачи ресурса. Объект контекста передачи ресурса – объект, в котором хранится указатель на контекст передачи ресурса. Объект контекста передачи ресурса создается функцией KnHandleCreateBadge()
, которая объявлена в заголовочном файле coresrv/handle/handle_api.h
. Работа этой функции связана с подсистемой уведомлений о состоянии ресурсов, так как программе-серверу нужно знать, когда объект контекста передачи ресурса будет закрыт и прекратит свое существование. Эти сведения требуются программе-серверу, чтобы освободить или использовать повторно память, которая отведена для хранения контекста передачи ресурса.
Объект контекста передачи ресурса будет закрыт, когда будут удалены или отозваны потомки дескриптора (см. "Удаление дескрипторов", "Отзыв дескрипторов"), которые порождены его передачей в ассоциации с этим объектом. (Переданный дескриптор может быть удален не только целенаправленно, но и, например, при неожиданном завершении работы принимающей программы-клиента.) Получив уведомление о закрытии объекта контекста передачи ресурса, программа-сервер удаляет дескриптор этого объекта. После этого объект контекста передачи ресурса прекращает свое существование. Получив уведомление, что объект контекста передачи ресурса прекратил свое существование, программа-сервер освобождает или использует повторно память, которая отведена для хранения контекста передачи ресурса.
Один объект контекста передачи ресурса может быть ассоциирован только с одной передачей дескриптора.
handle_api.h (фрагмент)
/**
* Функция создает объект контекста передачи ресурса для
* контекста передачи ресурса context и настраивает
* приемник уведомлений notice на прием уведомлений об
* этом объекте. Приемник уведомлений настраивается на
* прием уведомлений о событиях, которые соответствуют
* флагам маски событий OBJECT_DESTROYED и EVENT_BADGE_CLOSED.
* Входной параметр eventId задает идентификатор записи
* вида "ресурс – маска событий" в приемнике уведомлений.
* Выходной параметр handle содержит дескриптор объекта
* контекста передачи ресурса.
* В случае успеха функция возвращает rcOk, иначе возвращает код ошибки.
*/
Retcode KnHandleCreateBadge(Notice notice, rtl_uintptr_t eventId,
void *context, Handle *handle);
Упаковка данных в транспортный контейнер дескриптора
Для упаковки дескриптора, маски прав дескриптора и дескриптора объекта контекста передачи ресурса в транспортный контейнер дескриптора используется макрос nk_handle_desc()
, который определен в заголовочном файле nk/types.h
. Этот макрос принимает переменное число аргументов.
Если не передавать макросу ни одного аргумента, то в поле дескриптора handle
структуры nk_handle_desc_t
будет записано значение NK_INVALID_HANDLE
.
Если передать макросу один аргумент, то этот аргумент интерпретируется как дескриптор.
Если передать макросу два аргумента, то первый аргумент интерпретируется как дескриптор, второй аргумент интерпретируется как маска прав дескриптора.
Если передать макросу три аргумента, то первый аргумент интерпретируется как дескриптор, второй аргумент интерпретируется как маска прав дескриптора, третий аргумент интерпретируется как дескриптор объекта контекста передачи ресурса.
Извлечение данных из транспортного контейнера дескриптора
Для извлечения дескриптора, маски прав дескриптора и указателя на контекст передачи ресурса из транспортного контейнера дескриптора используются соответственно функции nk_get_handle()
, nk_get_rights()
и nk_get_badge_op()
(или nk_get_badge()
), которые определены в заголовочном файле nk/types.h
. Функции nk_get_badge_op()
и nk_get_badge()
используются только при разыменовании дескрипторов.
Сценарии передачи дескрипторов
Сценарий передачи дескрипторов от программы-клиента программе-серверу включает следующие шаги:
- Передающая программа-клиент упаковывает дескрипторы и маски прав дескрипторов в поля структуры запросов
*_req
типаnk_handle_desc_t
. - Передающая программа-клиент вызывает интерфейсный метод для передачи дескрипторов программе-серверу. Этот метод выполняет системный вызов
Call()
. - Принимающая программа-сервер получает запрос, выполняя системный вызов
Recv()
. - Диспетчер на стороне принимающей программы-сервера вызывает метод, который соответствует запросу. Этот метод извлекает дескрипторы и маски прав дескрипторов из полей структуры запросов
*_req
типаnk_handle_desc_t
.
Сценарий передачи дескрипторов от программы-сервера программе-клиенту включает следующие шаги:
- Принимающая программа-клиент вызывает интерфейсный метод для получения дескрипторов от программы-сервера. Этот метод выполняет системный вызов
Call()
. - Передающая программа-сервер получает запрос, выполняя системный вызов
Recv()
. - Диспетчер на стороне передающей программы-сервера вызывает метод, который соответствует запросу. Этот метод упаковывает дескрипторы, маски прав дескрипторов и дескрипторы объектов контекстов передачи ресурсов в поля структуры ответов
*_res
типаnk_handle_desc_t
. - Передающая программа-сервер отвечает на запрос, выполняя системный вызов
Reply()
. - На стороне принимающей программы-клиента интерфейсный метод возвращает управление. После этого принимающая программа-клиент извлекает дескрипторы и маски прав дескрипторов из полей структуры ответов
*_res
типаnk_handle_desc_t
.
Если передающая программа задает в передаваемой маске прав дескриптора больше прав доступа, чем задано для передаваемого дескриптора (владельцем которого она является), то передача не осуществляется. В этом случае выполнение системного вызова Call()
передающей или принимающей программой-клиентом, а также выполнение системного вызова Reply()
передающей программой-сервером завершается с ошибкой rcSecurityDisallow
.
Разыменование дескрипторов
Разыменование дескриптора – это операция, при которой программа-клиент отправляет программе-серверу дескриптор, а программа-сервер получает указатель на контекст передачи ресурса, маску прав отправленного дескриптора и предка отправленного программой-клиентом дескриптора, которым программа-сервер уже владеет. Разыменование выполняется, когда программа-клиент, вызывая методы работы с ресурсом (например, чтения, записи, закрытия доступа), передает программе-серверу дескриптор, который был получен от этой программы-сервера при открытии доступа к ресурсу.
Разыменование дескрипторов требует выполнения тех же условий и использует те же механизмы и типы данных, что и передача дескрипторов. Сценарий разыменования дескриптора включает следующие шаги:
- Программа-клиент упаковывает дескриптор в поле структуры запросов
*_req
типаnk_handle_desc_t
. - Программа-клиент вызывает интерфейсный метод для отправки дескриптора программе-серверу с целью выполнения действий с ресурсом. Этот метод выполняет системный вызов
Call()
. - Программа-сервер принимает запрос, выполняя системный вызов
Recv()
. - Диспетчер на стороне программы-сервера вызывает метод, который соответствует запросу. Этот метод проверяет, что выполнена именно операция разыменования, а не передача дескриптора. Затем вызванный метод опционально проверяет, что права доступа разыменованного дескриптора (который отправлен программой-клиентом) разрешают запрашиваемые действия с ресурсом, и извлекает указатель на контекст передачи ресурса из поля структуры запросов
*_req
типаnk_handle_desc_t
.
Для выполнения проверок программа-сервер использует функции nk_is_handle_dereferenced()
и nk_get_badge_op()
, которые объявлены в заголовочном файле nk/types.h
.
types.h (фрагмент)
/**
* Функция возвращает отличное от нуля значение, если
* дескриптор в транспортном контейнере дескриптора
* desc получен в результате операции разыменования
* дескриптора. Функция возвращает нуль, если дескриптор
* в транспортном контейнере дескриптора desc получен
* в результате операции передачи дескриптора.
*/
static inline
nk_bool_t nk_is_handle_dereferenced(const nk_handle_desc_t *desc)
/**
* Функция извлекает указатель на контекст передачи ресурса
* badge из транспортного контейнера дескриптора desc,
* если в маске прав, которая помещена в транспортном
* контейнере дескриптора desc, установлены флаги operation.
* В случае успеха функция возвращает NK_EOK, иначе возвращает код ошибки.
*/
static inline
nk_err_t nk_get_badge_op(const nk_handle_desc_t *desc,
nk_rights_t operation,
nk_badge_t *badge)
В общем случае программе-серверу не требуется дескриптор, который получен в результате разыменования, поскольку программа-сервер, как правило, сохраняет дескрипторы, которыми владеет, например, в составе контекстов пользовательских ресурсов. Но при необходимости программа-сервер может извлечь этот дескриптор из транспортного контейнера дескриптора.
В началоОтзыв дескрипторов
Программа может отзывать потомков дескриптора, которым она владеет. Отзыв дескрипторов осуществляется согласно дереву наследования дескрипторов.
Отзыв дескрипторов не удаляет их, но через отозванные дескрипторы невозможно обращаться к ресурсам. Любая функция, которая принимает дескриптор, завершается с ошибкой rcHandleRevoked
, если эта функция вызывается с отозванным дескриптором.
Отзыв выполняется функциями KnHandleRevoke()
и KnHandleRevokeSubtree()
, которые объявлены в заголовочном файле coresrv/handle/handle_api.h
. Функция KnHandleRevokeSubtree()
использует объект контекста передачи ресурса, который создается при передаче дескрипторов.
handle_api.h (фрагмент)
/**
* Функция удаляет дескриптор handle и отзывает всех его потомков.
* В случае успеха функция возвращает rcOk, иначе возвращает код ошибки.
*/
Retcode KnHandleRevoke(Handle handle);
/**
* Функция отзывает дескрипторы, которые образуют поддерево
* наследования дескриптора handle. Корневым узлом поддерева
* наследования является дескриптор, который порожден передачей
* дескриптора handle в ассоциации с объектом контекста
* передачи ресурса badge.
* В случае успеха функция возвращает rcOk, иначе возвращает код ошибки.
*/
Retcode KnHandleRevokeSubtree(Handle handle, Handle badge);
Уведомление о состоянии ресурсов
Программы могут отслеживать события, которые происходят с ресурсами (как системными, так и пользовательскими), а также информировать о событиях с пользовательскими ресурсами другие программы.
Функции подсистемы уведомлений объявлены в заголовочном файле coresrv/handle/notice_api.h
. Подсистема уведомлений предусматривает использование масок событий.
Маска событий – значение, биты которого интерпретируются как события, которые должны отслеживаться или уже произошли. Маска событий имеет размер 32 бита и состоит из общей и специальной части. Общая часть описывает события, неспецифичные для любых ресурсов (флаги этих событий определены в заголовочном файле handle/event_descr.h
). Например, в общей части находится флаг EVENT_OBJECT_DESTROYED
, который определяет событие "прекращение существования ресурса". Специальная часть описывает события, специфичные для пользовательского ресурса. Структура специальной части определяется поставщиком ресурса с использованием макроса OBJECT_EVENT_SPEC()
, который определен в заголовочном файле handle/event_descr.h
. Поставщику ресурса необходимо экспортировать публичные заголовочные файлы с описанием структуры специальной части.
Сценарий получения уведомлений о событиях, которые происходят с ресурсом, включает следующие шаги:
- Функцией
KnNoticeCreate()
создается приемник уведомлений (объект, в котором накапливаются уведомления). - В приемник уведомлений функцией
KnNoticeSubscribeToObject()
добавляются записи вида "ресурс – маска событий", чтобы настроить его на прием уведомлений о событиях, которые происходят с интересующими ресурсами. Набор отслеживаемых событий задается для каждого ресурса маской событий. - Чтобы извлекать уведомления из приемника уведомлений, вызывается функция
KnNoticeGetEvent()
.
Чтобы уведомлять программы о событиях, которые происходят с пользовательским ресурсом, используется функция KnNoticeSetObjectEvent()
. Вызов этой функции инициирует появление соответствующих уведомлений в приемниках уведомлений, которые настроены на отслеживание этих событий с этим ресурсом.
notice_api.h (фрагмент)
/**
* Функция создает приемник уведомлений notice.
* В случае успеха функция возвращает rcOk, иначе возвращает код ошибки.
*/
Retcode Kn
NoticeCreate(Notice *notice);
/**
* Функция добавляет запись вида "ресурс – маска событий"
* в приемник уведомлений notice, чтобы он принимал уведомления о
* событиях, которые происходят с ресурсом object и соответствуют
* маске событий evMask. Входной параметр evId задает идентификатор
* записи, который назначается пользователем и используется, чтобы
* идентифицировать запись в полученных уведомлениях.
* В случае успеха функция возвращает rcOk, иначе возвращает код ошибки.
*/
Retcode Kn
NoticeSubscribeToObject(Notice notice,
Handle object,
rtl_uint32_t evMask,
rtl_uintptr_t evId);
/**
* Функция извлекает уведомления из приемника уведомлений notice,
* ожидая наступления событий в течение msec миллисекунд.
* Входной параметр countMax задает максимальное число
* уведомлений, которое может быть извлечено. Выходной параметр
* events содержит набор извлеченных уведомлений типа EventDesc.
* Выходной параметр count содержит число уведомлений, которые
* были извлечены.
* В случае успеха функция возвращает rcOk, иначе возвращает код ошибки.
*/
Retcode Kn
NoticeGetEvent(Notice notice,
rtl_uint64_t msec,
rtl_size_t countMax,
EventDesc *events,
rtl_size_t *count);
/* Структура уведомления */
typedef struct {
/* Идентификатор записи "ресурс – маска событий"
* в приемнике уведомлений */
rtl_uintptr_t eventId;
/* Маска событий, которые произошли. */
rtl_uint32_t eventMask;
} EventDesc;
/**
* Функция сигнализирует, что события из маски событий
* evMask произошли с пользовательским ресурсом object.
* Нельзя устанавливать флаги общей части маски событий,
* так как о событиях из общей части маски событий может
* сигнализировать только ядро KasperskyOS.
* В случае успеха функция возвращает rcOk, иначе возвращает код ошибки.
*/
Retcode Kn
NoticeSetObjectEvent(Handle object, rtl_uint32_t evMask);
Удаление дескрипторов
Программа может удалять дескрипторы, которыми она владеет. Удаление дескриптора не делает недействительными его предков и потомков (в отличие от отзыва дескриптора, который делает недействительными его потомков). То есть через предков и потомков удаленного дескриптора обеспечивается доступ к ресурсу, который они идентифицируют. Также удаление дескриптора не нарушает целостность дерева наследования дескрипторов, которое относится к ресурсу, идентифицируемому этим дескриптором. Место удаленного дескриптора занимает его предок. То есть предок удаленного дескриптора становится непосредственным предком потомков удаленного дескриптора.
Удаление дескрипторов выполняется функцией KnHandleClose()
, которая объявлена в заголовочном файле coresrv/handle/handle_api.h
.
handle_api.h (фрагмент)
/**
* Функция удаляет дескриптор handle.
* В случае успеха функция возвращает rcOk, иначе возвращает код ошибки.
*/
Retcode KnHandleClose(Handle handle);
Пример использования OCap
В этой статье приведен сценарий использования OCap, в котором программа-сервер предоставляет следующие методы доступа к своим ресурсам:
OpenResource()
– открытие доступа к ресурсу;UseResource()
– использование ресурса;CloseResource()
– закрытие доступа к ресурсу.
Программа-клиент использует эти методы.
IDL-описание интерфейсных методов:
package SimpleOCap
interface {
OpenResource(in UInt32 ID, out Handle handle);
UseResource(in Handle handle, in UInt8 param, out UInt8 result);
CloseResource(in Handle handle);
}
Сценарий включает следующие шаги:
- Поставщик ресурса создает контекст пользовательского ресурса и вызывает функцию
KnHandleCreateUserObject()
для создания дескриптора ресурса. Поставщик ресурса сохраняет дескриптор ресурса в контексте пользовательского ресурса. - Клиент вызывает метод открытия доступа к ресурсу
OpenResource()
.- Поставщик ресурса создает контекст передачи ресурса и вызывает функцию
KnHandleCreateBadge()
для создания объекта контекста передачи ресурса и настройки приемника уведомлений на прием уведомлений о закрытии и прекращении существования объекта контекста передачи ресурса. Поставщик ресурса сохраняет дескриптор объекта контекста передачи ресурса и указатель на контекст пользовательского ресурса в контексте передачи ресурса. - Поставщик ресурса, используя макрос
nk_handle_desc()
, упаковывает дескриптор ресурса, маску прав дескриптора и указатель на объект контекста передачи ресурса в транспортный контейнер дескриптора. - Выполняется передача дескриптора от поставщика ресурса клиенту, в результате которой клиент получает потомка дескриптора, которым владеет поставщик ресурса.
- Вызов метода
OpenResource()
завершается успешно. Клиент извлекает дескриптор и маску прав дескриптора из транспортного контейнера дескриптора функциямиnk_get_handle()
иnk_get_rights()
соответственно. Маска прав дескриптора не требуется клиенту для обращения к ресурсу и передается, чтобы клиент мог узнать свои права доступа к ресурсу.
- Поставщик ресурса создает контекст передачи ресурса и вызывает функцию
- Клиент вызывает метод использования ресурса
UseResource()
.- Дескриптор, который получен от поставщика ресурса на шаге 2, используется в качестве аргумента метода
UseResource()
. Перед вызовом этого метода клиент упаковывает дескриптор в транспортный контейнер дескриптора макросомnk_handle_desc()
. - Выполняется разыменование дескриптора, в результате которого поставщик ресурса получает указатель на контекст передачи ресурса.
- Поставщик ресурса, используя функцию
nk_is_handle_dereferenced()
, проверяет, что выполнена операция разыменования, а не передача дескриптора. - Поставщик ресурса проверяет, что права доступа разыменованного дескриптора (который отправлен клиентом) разрешают запрашиваемую операцию над ресурсом, и извлекает указатель на контекст передачи ресурса из транспортного контейнера дескриптора. Для этого поставщик ресурса использует функцию
nk_get_badge_op()
, которая извлекает указатель на контекст передачи ресурса из транспортного контейнера дескриптора, если в полученной маске прав установлены флаги, соответствующие запрашиваемой операции. - Поставщик ресурса, используя контекст передачи ресурса и контекст пользовательского ресурса, выполняет запрашиваемую клиентом операцию над ресурсом. Затем поставщик ресурса отправляет клиенту результат выполнения этой операции.
- Вызов метода
UseResource()
завершается успешно. Клиент получает результат выполнения операции над ресурсом.
- Дескриптор, который получен от поставщика ресурса на шаге 2, используется в качестве аргумента метода
- Клиент вызывает метод закрытия доступа к ресурсу
CloseResource()
.- Дескриптор, который получен от поставщика ресурса на шаге 2, используется в качестве аргумента метода
CloseResource()
. Перед вызовом этого метода клиент упаковывает дескриптор в транспортный контейнер дескриптора макросомnk_handle_desc()
. После вызова методаCloseResource()
клиент удаляет дескриптор функциейKnHandleClose()
. - Выполняется разыменование дескриптора, в результате которого поставщик ресурса получает указатель на контекст передачи ресурса.
- Поставщик ресурса, используя функцию
nk_is_handle_dereferenced()
, проверяет, что выполнена операция разыменования, а не передача дескриптора. - Поставщик ресурса, используя функцию
nk_get_badge()
, извлекает указатель на контекст передачи ресурса из транспортного контейнера дескриптора. - Поставщик ресурса отзывает дескриптор, которым владеет клиент, функцией
KnHandleRevokeSubtree()
. В качестве аргументов этой функции используются дескриптор ресурса, которым владеет поставщик ресурса, и дескриптор объекта контекста передачи ресурса. Поставщик ресурса получает доступ к этим дескрипторам через указатель на контекст передачи ресурса. (Технически не требуется отзывать дескриптор, которым владеет клиент, так как клиент его уже удалил. Но поставщик ресурса не может быть уверен в том, что клиент удалил дескриптор, поэтому выполняется отзыв). - Вызов метода
CloseResource()
завершается успешно.
- Дескриптор, который получен от поставщика ресурса на шаге 2, используется в качестве аргумента метода
- Поставщик ресурса освобождает память, которая была выделена под контекст передачи ресурса и контекст пользовательского ресурса.
- Поставщик ресурса вызовом функции
KnNoticeGetEvent()
получает уведомление, что объект контекста передачи ресурса закрыт, и удаляет дескриптор объекта контекста передачи ресурса функциейKnHandleClose()
. - Поставщик ресурса вызовом функции
KnNoticeGetEvent()
получает уведомление, что объект контекста передачи ресурса прекратил свое существование, и освобождает память, которая была выделена под контекст передачи ресурса. - Поставщик ресурса удаляет дескриптор ресурса функцией
KnHandleClose()
и освобождает память, которая была выделена под контекст пользовательского ресурса.
- Поставщик ресурса вызовом функции