KasperskyOS Community Edition 1.3

Contents

libkos library

The libkos library is the basic KasperskyOS library that provides the set of APIs that allow programs and other libraries (for example, libc and kdf) to use core endpoints. The APIs provided by the libkos library enable solution developers to do the following:

  • Manage processes, threads, and virtual memory.
  • Control access to resources.
  • Perform input/output operations.
  • Create IPC channels.
  • Manage power.
  • Obtain statistical data on the system.
  • Use other capabilities supported by core endpoints.

On hardware platforms running an Arm processor architecture, input and output parameters of the libkos library API cannot be saved in "Device memory" because this could lead to unpredictable behavior. (Exceptions to this rule are the addr parameter of the KnVmQuery() function from the vmm_api.h API, the reg and baseReg parameters of functions from the mmio.h API, the va parameter of the KnHalFlushCache() function from the hal_api.h API, and the va parameter of the KosCpuCacheFlush() function from the cpucache.h API.) Parameters of the libkos library API must be saved in "Normal memory". To copy data from "Device memory" to "Normal memory" and vice versa, you must use the RtlPedanticMemcpy() function declared in the header file sysroot-*-kos/include/rtl/string_pedantic.h from the KasperskyOS SDK.

In this section

Managing handles (handle_api.h)

Managing virtual memory (vmm_api.h)

Allocating and freeing memory (alloc.h)

Using DMA (dma.h)

Memory-mapped I/O (mmio.h)

Managing interrupt processing (irq.h)

Managing threads (high-level API thread.h)

Managing threads (low-level API thread_api.h)

Managing processes (high-level API task.h)

Managing processes (low-level API task_api.h)

Initializing IPC transport for interprocess communication and managing IPC request processing (transport-kos.h, transport-kos-dispatch.h)

Initializing IPC transport for querying the security module (transport-kos-security.h)

Generating random numbers (random_api.h)

Getting and changing time values (time_api.h)

Using notifications (notice_api.h)

Dynamically creating IPC channels (cm_api.h, ns_api.h)

Using synchronization primitives (event.h, mutex.h, rwlock.h, semaphore.h, condvar.h)

Managing I/O memory isolation (iommu_api.h)

Using queues (queue.h)

Using memory barriers (barriers.h)

Executing system calls (syscalls.h)

IPC interrupt (ipc_api.h)

Using sessions (session.h)

Using KosObjects (objects.h)

Using KosObject containers (objcontainer.h)

Using KosStrings (strings.h)

KasperskyOS kernel XHCI DbC driver management (xhcidbg_api.h)

Receiving security audit data (vlog_api.h)

Using futexes (sync.h)

Getting IPC handles and RIIDs to use statically created IPC channels (sl_api.h)

Power management (pm_api.h)

Page top
[Topic libkos]

Managing handles (handle_api.h)

The API is defined in the sysroot-*-kos/include/coresrv/handle/handle_api.h header file from the KasperskyOS SDK.

The API is intended for performing operations with handles. Handles have the Handle type, which is defined in the header file sysroot-*-kos/include/handle/handletype.h from the KasperskyOS SDK.

Locality of handles

Each process receives handles from its own handle space irrespective of other processes. The handle spaces of different processes are absolutely identical in that they consist of the same set of values. Therefore, a handle is unique (has a unique value) only within the handle space of the single process that owns the particular handle. In other words, different processes may have identical handles that identify different resources, or may have different handles that identify the same resource.

In this section

Handle permissions mask

Creating handles

Transferring handles

Duplicating handles

Dereferencing handles

Revoking handles

Closing handles

Getting a security ID (SID)

OCap usage example

Page top
[Topic handles_manage]

Handle permissions mask

A handle permissions mask has a size of 32 bits and consists of a general part and a specialized part. The general part describes the general rights that are not specific to any particular resource (the flags of these rights are defined in the header file sysroot-*-kos/include/services/ocap.h from the KasperskyOS SDK). For example, the general part contains the OCAP_HANDLE_TRANSFER flag, which defines the permission to transfer the handle. The specialized part describes the rights that are specific to the particular user resource or system resource. The flags of the specialized part's permissions for system resources are defined in the ocap.h header file. The structure of the specialized part for user resources is defined by the resource provider by using the OCAP_HANDLE_SPEC() macro that is defined in the ocap.h header file. The resource provider must export the public header files describing the flags of the specialized part.

When the handle of a system resource is created, the permissions mask is defined by the KasperskyOS kernel, which applies permissions masks from the ocap.h header file. It applies permissions masks with names such as OCAP_*_FULL (for example, OCAP_IOPORT_FULL, OCAP_TASK_FULL, OCAP_FILE_FULL) and OCAP_IPC_* (for example, OCAP_IPC_SERVER, OCAP_IPC_LISTENER, OCAP_IPC_CLIENT).

When the handle of a user resource is created, the permissions mask is defined by the user.

When a handle is transferred, the permissions mask is defined by the user but the transferred access rights cannot be elevated above the access rights of the process.

Page top
[Topic libkos_handles_rights]

Creating handles

Information about API functions is provided in the table below.

Creating handles of system resources

Handles of system resources are created when these resources are created. For example, handles are created when an interrupt or MMIO memory region is registered, and when a DMA buffer, thread, or process is created.

Creating handles of user resources

Handles of user resources are created by the providers of these resources by using the KnHandleCreateUserObject() or KnHandleCreateUserObjectEx() function.

The context of a user resource must be defined through the context parameter. The user resource context consists of data that allows the resource provider to identify the resource and its state when access to the resource is requested by other processes. This normally consists of a data set with various types of data (structure). For example, the context of a file may include the name, path, and cursor position. The user resource context is used as the resource transfer context or is used together with multiple resource transfer contexts.

You must use the rights parameter to define the handle permissions mask.

Creating IPC handles

An IPC handle is a handle that identifies an IPC channel. IPC handles are used to execute system calls. A client IPC handle is necessary for executing a Call() system call. A server IPC handle is necessary for executing the Recv() and Reply() system calls. A listener handle is a server IPC handle that has extended rights allowing it to add IPC channels to the set of IPC channels identified by this handle. A callable handle is a client IPC handle that simultaneously identifies the IPC channel to a server and an endpoint of this server.

A server creates a callable handle and passes it to a client so that the client can use the server endpoint. The client initializes IPC transport by using the callable handle that it received. In addition, the client specifies the INVALID_RIID value as the Runtime Implementation Identifier (RIID) in the proxy object initialization function. To create a callable handle, call the KnHandleCreateUserObjectEx() function and specify the server IPC handle and the RIID in the ipcChannel and riid parameters, respectively. Use the context parameter to specify the data to be associated with the callable handle. The server will be able to receive the pointer to this data when dereferencing the callable handle. (Even though the callable handle is an IPC handle, the kernel puts it into the base_.self field of the constant part of an IPC request.)

To create the client IPC handle, server IPC handle, and listener IPC handle and associate them with each other, call the KnHandleConnect() or KnHandleConnectEx() function. These functions are used to statically create IPC channels. The KnHandleConnect() function creates IPC handles from the handle space of the calling process. However, the client IPC handle can be transferred to another process. The KnHandleConnectEx() function can create IPC handles from the handle space of the calling process or from the handle spaces of other processes, such as the client and server.

When calling the KnHandleConnect() or KnHandleConnectEx() function with the INVALID_HANDLE value in the parameter that defines the listener handle, a new listener handle is created. However, the server IPC handle and listener IPC handle in the output parameters are the same handle. If a listener handle is specified when calling the KnHandleConnect() or KnHandleConnectEx() function, the created server IPC handle will provide the capability to receive IPC requests over all IPC channels associated with this listener handle. In this case, the server IPC handle and listener IPC handle in the output parameters are different handles. (The first IPC channel associated with the listener handle is created when calling the KnHandleConnect() or KnHandleConnectEx() function with the INVALID_HANDLE value in the parameter that defines the listener handle. The second and subsequent IPC channels associated with the listener handle are created during the second and subsequent calls of the KnHandleConnect() or KnHandleConnectEx() function specifying the listener handle that was obtained during the first call.)

To call a listener handle that is not associated with a client IPC handle and server IPC handle, call the KnHandleCreateListener() function. (The KnHandleConnect() and KnHandleConnectEx() functions create a listener handle associated with a client IPC handle and server IPC handle.) The KnHandleCreateListener() function is convenient for creating a listener handle that will be subsequently bound to callable handles.

To create a client IPC handle for querying the Kaspersky Security Module through the security interface, call the KnHandleSecurityConnect() function. This function is called by the libkos library when initializing IPC transport for querying the security module.

Information about API functions

handle_api.h functions

Function

Information about the function

KnHandleCreateUserObject()

Purpose

Creates a handle.

Parameters

  • [in] type – handle type. Fictitious parameter that must take a value ranging from the HANDLE_TYPE_USER_FIRST constant to the HANDLE_TYPE_USER_LAST constant as defined in the header file sysroot-*-kos/include/handle/handletype.h from the KasperskyOS SDK.
  • [in] rights – handle permissions mask.
  • [in,optional] context – pointer to the data that should be associated with the handle, or RTL_NULL if this association is not required.
  • [out] handle – pointer to the handle.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnHandleCreateUserObjectEx()

Purpose

Creates a handle.

Parameters

  • [in] type – handle type. Fictitious parameter that must take a value ranging from the HANDLE_TYPE_USER_FIRST constant to the HANDLE_TYPE_USER_LAST constant as defined in the header file sysroot-*-kos/include/handle/handletype.h from the KasperskyOS SDK.
  • [in] rights – handle permissions mask.
  • [in,optional] context – pointer to the data that should be associated with the handle, or RTL_NULL if this association is not required.
  • [in,optional] ipcChannel – server IPC handle, or INVALID_HANDLE if you do not need to create a callable handle.
  • [in,optional] riid – Runtime Implementation Identifier (RIID), or INVALID_RIID if you do not need to create a callable handle.
  • [out] handle – pointer to the handle.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnHandleConnect()

Purpose

Creates and connects the client, server, and listener IPC handles.

Parameters

  • [in,optional] ls – listener handle, or INVALID_HANDLE if you need to create it.
  • [out,optional] outLs – pointer to the listener handle. You can specify RTL_NULL if the ls parameter is used to define the listener handle.
  • [out,optional] outSr – pointer to the server IPC handle, or RTL_NULL to not create a server IPC handle if the ls parameter is used to define the listener handle.
  • [out] outCl – pointer to the client IPC handle.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnHandleConnectEx()

Purpose

Creates and connects the client, server, and listener IPC handles.

Parameters

  • [in] server – handle of the server process.
  • [in,optional] srListener – listener handle from the handle space of the server process, or INVALID_HANDLE if you need to create it.
  • [in] client – handle of the client process.
  • [out,optional] outSrListener – pointer to the listener handle from the handle space of the server process. You can specify RTL_NULL if the srListener parameter is used to define the listener handle.
  • [out,optional] outSrEndpoint – pointer to the server IPC handle from the handle space of the server process, or RTL_NULL to not create a server IPC handle if the srListener parameter is used to define the listener handle.
  • [out] outClEndpoint – pointer to the client IPC handle from the handle space of the client process.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnHandleSecurityConnect()

Purpose

Creates a client IPC handle for querying the Kaspersky Security Module through the security interface.

Parameters

  • [out] client – pointer to the handle.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnHandleCreateListener()

Purpose

Creates a listener handle that is not associated with a client IPC handle and server IPC handle.

Parameters

  • [out] listener – pointer to the listener handle.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Page top
[Topic libkos_handles_create]

Transferring handles

Information about API functions is provided in the table below.

Overview of handle transfers

Handles are transferred between processes so that resource consumers can gain access to required resources. Due to the specific locality of handles, a handle transfer initiates the creation of a handle from the handle space of the recipient process. This handle is registered as a descendant of the transferred handle and identifies the same resource.

One handle can be transferred multiple times to one or more processes. Each transfer initiates the creation of a new descendant of the transferred handle on the recipient process side. A process can transfer handles that it received from other processes or the KasperskyOS kernel. For this reason, a handle may have multiple generations of descendants. The generation hierarchy of handles for each resource is stored in the KasperskyOS kernel in the form of a handle inheritance tree.

A process can transfer handles for user resources and system resources if the access rights of these handles permit such a transfer (the OCAP_HANDLE_TRANSFER flag is set in the permissions mask). A descendant may have less access rights than an ancestor. For example, a transferring process with read-and-write permissions for a file can transfer read-only permissions. The transferring process can also prohibit the recipient process from further transferring the handle. Access rights are defined in the transferred permissions mask for the handle.

Conditions for transferring handles

To enable processes to transfer handles to other processes, the following conditions must be met:

  1. An IPC channel is created between the processes.
  2. The solution security policy (security.psl) allows interaction between process classes.
  3. Interface methods are implemented for transferring handles.

The API task.h enables a parent process to pass handles to a child process that is not yet running.

In an IDL description, signatures of interface methods for transferring handles have input (in) and/or output (out) parameters of the Handle type or array type with elements of the Handle type. Up to 255 handles can be passed through the input parameters of one method. This same number of handles can be received through output parameters.

Example IDL description that defines the signatures of interface methods for transferring handles:

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); }

For each parameter of the Handle type, the NK compiler generates a field of the nk_handle_desc_t type (hereinafter also referred to as the transport container of the handle) in the *_req IPC request structure and/or *_res IPC response structure. This type is declared in the header file sysroot-*-kos/include/nk/types.h from the KasperskyOS SDK and comprises a structure consisting of the following three fields: handle field for the handle, rights field for the handle permissions mask, and the badge field for the resource transfer context.

Resource transfer context

The resource transfer context consists of data that allows the server to identify the resource and its state when access to the resource is requested via descendants of the transferred handle. This normally consists of a data set with various types of data (structure). For example, the transfer context of a file may include the name, path, and cursor position. The server receives a pointer to the resource transfer context when dereferencing a handle.

Regardless of whether or not the server is the resource provider, the server can associate each handle transfer with a separate resource transfer context. This resource transfer context is bound only to the handle descendants (handle inheritance subtree) that were generated as a result of a specific transfer of the handle. This lets you define the state of a resource in relation to a separate transfer of the handle of this resource. For example, for cases when one file may be accessed multiple times, the file transfer context lets you define which specific opening of this file corresponds to a received IPC request.

If the server is the resource provider, each transfer of the handle of this resource is associated with the user resource context by default. In other words, the user resource context is used as the resource transfer context for each handle transfer if the particular transfer is not associated with a separate resource transfer context.

A server that is the resource provider can use both the user resource context and the resource transfer context together. For example, the name, path and size of a file is stored in the user resource context while the cursor position can be stored in multiple resource transfer contexts because each client can work with different parts of the file. Technically, joint use of the user resource context and resource transfer contexts is possible because the resource transfer contexts store a pointer to the user resource context.

If the client uses multiple various-type resources of the server, the resource transfer contexts (or contexts of user resources if they are used as resource transfer contexts) must be typified objects of the KosObject type (for details about KosObjects, see Using KosObjects (objects.h)). This is necessary so that the server can verify that the client using a resource has sent the interface method the handle of the specific resource that corresponds to this method. This verification is required because the client could mistakenly send the interface method a resource handle that does not correspond to this method. For example, a client may have received a file handle and sent it to an interface method for working with volumes.

To associate a handle transfer with a resource transfer context, the server puts the handle of the resource transfer context object into the badge field of the nk_handle_desc_t structure. The resource transfer context object is the kernel object that stores the pointer to the resource transfer context. To create a resource transfer context object, call the KnHandleCreateBadge() function. This function is bound to the notification mechanism because a server needs to know when a resource transfer context object will be closed and deleted. The server needs this information to free up or re-use memory that was allotted for storing the resource transfer context.

The resource transfer context object will be closed upon the closure or revocation of the handle descendants that comprise the handle inheritance subtree whose root node was generated by the transfer of this handle in association with this object. (A transferred handle may be closed intentionally or unintentionally, such as when a recipient client is unexpectedly terminated.) After receiving a notification regarding the closure of a resource transfer context object, the server closes the handle of this object. After this, the resource transfer context object will be deleted. After receiving a notification regarding the deletion of the resource transfer context object, the server frees up or re-uses the memory that was allotted for storing the resource transfer context.

One resource transfer context object can be associated with only one handle transfer.

Packaging data into the transport container of a handle

To package a handle, handle permissions mask, and resource transfer context object handle into a handle transport container, use the nk_handle_desc() macro that is defined in the header file sysroot-*-kos/include/nk/types.h from the KasperskyOS SDK. This macro receives a variable number of parameters.

If no parameter is passed to the macro, the NK_INVALID_HANDLE value will be written to the handle field of the nk_handle_desc_t structure. If one parameter is passed to the macro, this parameter is interpreted as the handle. If two parameters are passed to the macro, the first parameter is interpreted as the handle and the second parameter is interpreted as the handle permissions mask. If three parameters are passed to the macro, the first parameter is interpreted as the handle, the second parameter is interpreted as the handle permissions mask, and the third parameter is interpreted as the resource transfer context object handle.

Extracting data from the transport container of a handle

To extract the handle, handle permissions mask, and pointer to the resource transfer context from the transport container of a handle, use the nk_get_handle(), nk_get_rights() and nk_get_badge_op() (or nk_get_badge()) functions, respectively, which are declared in the header file sysroot-*-kos/include/nk/types.h from the KasperskyOS SDK. The nk_get_badge_op() and nk_get_badge() functions should be used only when dereferencing handles.

Handle transfer scenarios

The scenario for transferring handles from a client to the server includes the following steps:

  1. The client packages the handles and handle permissions masks into fields of the *_req IPC requests structure of the nk_handle_desc_t type.
  2. The client calls the interface method for transferring handles to the server. The Call() system call is executed when this method is called.
  3. The server receives an IPC request by executing the Recv() system call.
  4. The dispatcher on the server side calls the method corresponding to the IPC request. This method extracts the handles and handle permissions masks from fields of the *_req IPC request structure of the nk_handle_desc_t type.

The scenario for transferring handles from the server to a client includes the following steps:

  1. The client calls the interface method for receiving handles from the server. The Call() system call is executed when this method is called.
  2. The server receives an IPC request by executing the Recv() system call.
  3. The dispatcher on the server side calls the method corresponding to the IPC request. This method packages the handles, handle permissions masks and resource transfer context object handles into fields of the *_res IPC response structure of the nk_handle_desc_t type.
  4. The server responds to the IPC request by executing the Reply() system call.
  5. On the client side, the interface method returns control. After this, the client extracts the handles and handle permissions masks from fields of the *_res IPC response structure of the nk_handle_desc_t type.

If the transferring process defines more access rights in the transferred handle permissions mask than the access rights defined for the transferred handle (which it owns), the transfer is not completed. In this case, the Call() system call executed by the transferring or recipient client or the Reply() system call executed by the transferring server ends with the rcSecurityDisallow error.

Information about API functions

handle_api.h functions

Function

Information about the function

KnHandleCreateBadge()

Purpose

Creates a resource transfer context object and configures a notification mechanism for monitoring the life cycle of this object.

Parameters

  • [in] notice – identifier of the notification receiver.
  • [in] eventId – identifier of the "resource–event mask" entry in the notification receiver.
  • [in,optional] context – pointer to the data that should be associated with the handle transfer, or RTL_NULL if this association is not required.
  • [out] handle – pointer to the handle of the resource transfer context object.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

The notification receiver is configured to receive notifications about events that match the EVENT_OBJECT_DESTROYED and EVENT_BADGE_CLOSED flags of the event mask.

Page top
[Topic libkos_handles_transfer]

Duplicating handles

Handle duplication is similar to a handle transfer, but duplication is performed within a process. A handle descendant is created in the same process and from the same handle space. The rights of the handle descendant may be less than or equal to the rights of the original handle. Handle duplication can be associated with a resource transfer context object. This lets you use the notification mechanism to track the closure or revocation of all handle descendants that form the handle inheritance subtree whose root node was generated by the duplication operation. It also provides the capability to revoke these descendants.

To duplicate a handle, call the KnHandleCopy() function. To do so, the OCAP_HANDLE_COPY flag must be set in the handle permissions mask.

Information about API functions is provided in the table below.

handle_api.h functions

Function

Information about the function

KnHandleCopy()

Purpose

Duplicates a handle.

As a result of duplication, the calling process receives the handle descendant.

Parameters

  • [in] inHandle – original handle.
  • [in] newRightsMask – permissions mask of the handle descendant.
  • [in,optional] copyBadge – handle of the resource transfer context object, or INVALID_HANDLE if you do not need to associate handle duplication with this object.
  • [out] outHandle – pointer to the handle descendant.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Page top
[Topic libkos_handle_copy]

Dereferencing handles

When dereferencing a handle, the client sends the handle to the server, and the server receives a pointer to the resource transfer context, the permissions mask of the sent handle, and the ancestor of the handle sent by the client and already owned by the server. Dereferencing occurs when a resource consumer that called methods for working with a resource (such as read/write or access closure) sends the resource provider the handle that was received from this resource provider when access to the resource was opened.

Dereferencing handles requires fulfillment of the same conditions and utilizes the same mechanisms and data types as when transferring handles. A handle dereferencing scenario includes the following steps:

  1. The client packages the handle into a field of the *_req IPC request structure of the nk_handle_desc_t type.
  2. The client calls the interface method for sending the handle to the server for the purpose of performing operations with the resource. The Call() system call is executed when this method is called.
  3. The server receives the IPC request by executing the Recv() system call.
  4. The dispatcher on the server side calls the method corresponding to the IPC request. This method verifies that the dereferencing operation was specifically executed instead of a handle transfer. Then the called method has the option to verify that the access rights of the dereferenced handle (that was sent by the client) permit the requested actions with the resource, and extracts the pointer to the resource transfer context from the field of the *_req request structure of the nk_handle_desc_t type.

To perform verification, the server uses the nk_is_handle_dereferenced() and nk_get_badge_op() functions that are declared in the header file sysroot-*-kos/include/nk/types.h from the KasperskyOS SDK.

types.h (fragment)

/** * Returns a value different from null if * the handle in the transport container of * "desc" is received as a result of dereferencing * the handle.Returns null if the handle * in the transport container of "desc" is received * as a result of a handle transfer. */ static inline nk_bool_t nk_is_handle_dereferenced(const nk_handle_desc_t *desc) /** * Extracts the pointer to the resource transfer context * "badge" from the transport container of "desc" * if the permissions mask that was put in the transport * container of the desc handle has the operation flags set. * If successful, the function returns NK_EOK, otherwise it returns an error code. */ static inline nk_err_t nk_get_badge_op(const nk_handle_desc_t *desc, nk_rights_t operation, nk_badge_t *badge)

Generally, the server does not require the handle that was received from dereferencing because the server normally retains the handles that it owns, for example, within the contexts of user resources. However, the server can extract this handle from the handle transport container if necessary.

Page top
[Topic libkos_handles_dereference]

Revoking handles

A process can revoke descendants of a handle that it owns. Handles are revoked according to the handle inheritance tree.

Revoked handles are not closed. However, you cannot query resources via revoked handles. Any function that receives the handle will end with the rcHandleRevoked error if the function is called with a revoked handle.

To revoke handle descendants, call the KnHandleRevoke() or KnHandleRevokeSubtree() function. The KnHandleRevokeSubtree() function uses the resource transfer context object that is created when transferring handles.

If each handle of a system resource in all processes that own these handles are closed (see Closing handles) or revoked, this system resource will be deleted.

Information about API functions is provided in the table below.

handle_api.h functions

Function

Information about the function

KnHandleRevoke()

Purpose

Closes a handle and revokes its descendants.

Parameters

  • [in] handle – a handle.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnHandleRevokeSubtree()

Purpose

Revokes the handles that make up the inheritance subtree of the specified handle.

Parameters

  • [in] handle – a handle. The handles forming the inheritance subtree of this handle are revoked.
  • [in] badge – handle that identifies the resource transfer context object, which defines the inheritance subtree of the handles to revoke. The root node of this subtree is the handle that was generated by the transfer or duplication of the handle that is defined through the handle parameter and is associated with the resource transfer context object.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Page top
[Topic libkos_handles_revoke]

Closing handles

A process can close the handles that it owns. Closing a handle terminates the association between an ID and a resource, thereby releasing the ID. Closing a handle does not invalidate its ancestors and descendants (in contrast to revoking a handle, which actually invalidates the descendants of the handle). In other words, the ancestors and descendants of a closed handle can still be used to provide access to the resource that they identify. Also, closing a handle does not disrupt the handle inheritance tree associated with the resource identified by the particular handle. The place of a closed handle is occupied by its ancestor. In other words, the ancestor of a closed handle becomes the direct ancestor of the descendants of the closed handle.

To close the handle, call the KnHandleClose() function.

If each handle of a system resource in all processes that own these handles are revoked (see Revoking handles) or closed, this system resource will be deleted.

Information about API functions is provided in the table below.

handle_api.h functions

Function

Information about the function

KnHandleClose()

Purpose

Closes a handle.

Parameters

  • [in] handle – a handle.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Page top
[Topic libkos_handles_delete]

Getting a security ID (SID)

By getting the SID values for different handles, you can determine whether these handles identify different resources or the same resource.

To get a security ID for a handle, call the KnHandleGetSidByHandle() function. To do so, the OCAP_HANDLE_GET_SID flag must be set in the handle permissions mask.

Information about API functions is provided in the table below.

handle_api.h functions

Function

Information about the function

KnHandleGetSidByHandle()

Purpose

Receives a security ID (SID) based on a handle.

Parameters

  • [in] handle – a handle.
  • [out] sid – pointer to the security ID (SID).

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Page top
[Topic libkos_handle_get_sid]

OCap usage example

This example describes an OCap usage scenario in which the resource provider provides the following methods for accessing its resources:

  • OpenResource() – opens access to the resource.
  • UseResource() – uses the resource.
  • CloseResource() – closes access to the resource.

The resource consumer uses these methods.

IDL description:

package SimpleOCap interface { OpenResource(in UInt32 ID, out Handle handle); UseResource(in Handle handle, in UInt8 param, out UInt8 result); CloseResource(in Handle handle); }

The scenario includes the following steps:

  1. The resource provider creates the user resource context and calls the KnHandleCreateUserObject() function to create the resource handle. The resource provider saves the resource handle in the user resource context.
  2. The resource consumer calls the OpenResource() method to open access to the resource.
    1. The resource provider creates the resource transfer context and calls the KnHandleCreateBadge() function to create a resource transfer context object and configure the notification receiver to receive notifications regarding the closure and deletion of the resource transfer context object. The resource provider saves the handle of the resource transfer context object and the pointer to the user resource context in the resource transfer context.
    2. The resource provider uses the nk_handle_desc() macro to package the resource handle, permissions mask of the handle, and pointer to the resource transfer context object into the handle transport container.
    3. The handle is transferred from the resource provider to the resource consumer, which means that the resource consumer receives a descendant of the handle owned by the resource provider.
    4. The OpenResource() method call completes successfully. The resource consumer extracts the handle and permissions mask of the handle from the handle transport container by using the nk_get_handle() and nk_get_rights() functions, respectively. The handle permissions mask is not required by the resource consumer to query the resource, but is transferred so that the resource consumer can find out its permissions for accessing the resource.
  3. The resource consumer calls the UseResource() method to utilize the resource.
    1. The handle that was received from the resource provider at step 2 is used as a parameter of the UseResource() method. Before calling this method, the resource consumer uses the nk_handle_desc() macro to package the handle into the handle transport container.
    2. The handle is dereferenced, after which the resource provider receives the pointer to the resource transfer context.
    3. The resource provider uses the nk_is_handle_dereferenced() function to verify that the dereferencing operation was completed instead of a handle transfer.
    4. The resource provider verifies that the access rights of the dereferenced handle (that was sent by the resource consumer) allows the requested operation with the resource, and extracts the pointer to the resource transfer context from the handle transport container. To do so, the resource provider uses the nk_get_badge_op() function, which extracts the pointer to the resource transfer context from the handle transport container if the received permissions mask has the corresponding flags set for the requested operation.
    5. The resource provider uses the resource transfer context and the user resource context to perform the corresponding operation with the resource as requested by the resource consumer. Then the resource provider sends the results of this operation to the resource consumer.
    6. The UseResource() method call completes successfully. The resource consumer receives the results of the operation performed with the resource.
  4. The resource consumer calls the CloseResource() method to close access to the resource.
    1. The handle that was received from the resource provider at step 2 is used as a parameter of the CloseResource() method. Before calling this method, the resource consumer uses the nk_handle_desc() macro to package the handle into the handle transport container. After the CloseResource() method is called, the resource consumer uses the KnHandleClose() function to close the handle.
    2. The handle is dereferenced, after which the resource provider receives the pointer to the resource transfer context.
    3. The resource provider uses the nk_is_handle_dereferenced() function to verify that the dereferencing operation was completed instead of a handle transfer.
    4. The resource provider uses the nk_get_badge() function to extract the pointer to the resource transfer context from the handle transport container.
    5. The resource provider uses the KnHandleRevokeSubtree() function to revoke the handle owned by the resource consumer. The resource handle owned by the resource provider and the handle of the resource transfer context object are used as parameters of this function. The resource provider obtains access to these handles through the pointer to the resource transfer context. (Technically, the handle owned by the resource consumer does not have to be revoked because the resource consumer already closed it. However, the revoke operation is performed in case the resource provider is not sure if the resource consumer actually closed the handle).
    6. The CloseResource() method call completes successfully.
  5. The resource provider frees up the memory that was allocated for the resource transfer context and user resource context.
    1. The resource provider calls the KnNoticeGetEvent() function to receive a notification that the resource transfer context object was closed, and uses the KnHandleClose() function to close the handle of the resource transfer context object.
    2. The resource provider calls the KnNoticeGetEvent() function to receive a notification that the resource transfer context object was deleted, and frees up the memory that was allocated for the resource transfer context.
    3. The resource provider uses the KnHandleClose() function to close the resource handle and free up the memory that was allocated for the user resource context.
Page top
[Topic libkos_handles_simple_scenario]

Managing virtual memory (vmm_api.h)

The API is defined in the header file sysroot-*-kos/include/coresrv/vmm/vmm_api.h from the KasperskyOS SDK.

The API is designed to allocate and free memory, create shared memory, and prepare ELF image segments to be loaded into process memory.

In this section

Allocating and freeing memory

Creating shared memory

Preparing ELF image segments to be loaded into process memory

Page top
[Topic libkos_vmm_api]

Allocating and freeing memory

Information about API functions is provided in the table below.

Using the API

Virtual memory pages may be free, reserved, or committed. Free pages that are used to allocate a virtual memory region become reserved pages. Reserved pages may or may not be mapped to physical memory. Reserved pages that are mapped to physical memory are committed pages.

Pages of a virtual memory region that are allocated by the KnVmAllocate() function call can be committed in three different ways:

  1. Fully committed when the region is allocated.
  2. Fully or partially committed after allocation of the region (by calling the KnVmCommit() function).
  3. Committed whenever virtual addresses are queried (so-called "lazy" mode).

When the first option is used, the entire required volume of physical memory is allocated immediately after the virtual memory region is reserved. When the second or third option is used, the virtual memory region is reserved without allocating physical memory. This lets you conserve physical memory if a reserved virtual memory region will not actually be required or will only be partially used. In addition, a virtual memory region can be allocated faster if its allocation does not include commitment.

When in "lazy" mode, physical memory is allocated only when the virtual memory region is actually queried. In this case, the page containing the queried address and several pages before and after this address are committed.

If you call the KnVmAllocate() function with the VMM_FLAG_COMMIT and VMM_FLAG_LOCKED flags, the virtual memory region will be reserved and fully committed. If you call the KnVmAllocate() function with the VMM_FLAG_COMMIT flag but without the VMM_FLAG_LOCKED flag, the virtual memory region will be reserved and committed only in "lazy" mode. If you call the KnVmAllocate() function with the VMM_FLAG_LOCKED flag but without the VMM_FLAG_COMMIT flag, the virtual memory region will be reserved without commitment and a subsequent call of the KnVmCommit() function will fully commit this region. If you call the KnVmAllocate() function without the VMM_FLAG_COMMIT and VMM_FLAG_LOCKED flags, the virtual memory region will be reserved without commitment and a subsequent call of the KnVmCommit() function will commit this region in "lazy" mode.

A virtual memory region is allocated when the MDL buffer, DMA buffer or MMIO memory region is mapped to process memory. This region is allocated by the mapping function.

A protected page may reside at the beginning and/or end of the virtual memory region. This page is never committed. Any query of this page will result in an exception signaling that the region boundaries have been exceeded.

To change the access rights to the virtual memory region, call the KnVmProtect() function. You can fully close and then re-open access to a region while retaining is contents.

To free physical memory while retaining the reservation of virtual addresses, call the KnVmDecommit() or KnVmReset() function. In this case, the contents of the virtual memory region will be lost. After freeing physical memory by calling the KnVmDecommit() function, you must call the KnVmCommit() function to subsequently use the virtual memory region. After freeing physical memory by calling the KnVmReset() function, the virtual memory region can be used without any additional actions required. This virtual memory region will correspond to memory allocated by calling the KnVmAllocate() function with the VMM_FLAG_COMMIT flag but without the VMM_FLAG_LOCKED flag.

The KnVmProtect(), KnVmDecommit(), and KnVmReset() functions cannot be used if the MDL buffer, DMA buffer or MMIO memory region is mapped to the virtual memory region.

To free the virtual memory region, call the KnVmUnmap() function. When this function is called, the reserved pages will become free regardless of whether or not they were committed, and the physical memory mapped to committed pages is also freed.

The KnVmUnmap() function frees the virtual addresses of a region mapped to the MDL buffer, but does not delete the MDL buffer. In addition, this function cannot be used if the DMA buffer or MMIO memory region is mapped to the virtual memory region.

The KnVmCommit(), KnVmProtect(), KnVmDecommit(), KnVmReset(), and KnVmUnmap() functions can be applied for the entire allocated virtual memory region or for a portion of it.

The functions presented in this section provide the basis for implementing memory allocation/deallocation functions of the libkos library, and functions of POSIX interfaces such as malloc(), calloc(), realloc(), free(), mmap(), and munmap().

Information about API functions

vmm_api.h functions

Function

Information about the function

KnVmAllocate()

Purpose

Allocates (reserves and optionally commits) a virtual memory region.

Parameters

  • [in,optional] addr – page-aligned, preferred base address of the virtual memory region, or 0 to select this address automatically.
  • [in] size – size of the virtual memory region in bytes. It must be a multiple of the memory page size.
  • [in] flags – flags defining the parameters of the virtual memory region. The flags are defined in the header file sysroot-*-kos/include/vmm/flags.h from the KasperskyOS SDK.

Returned values

If successful, the function returns the base address of the allocated virtual memory region, otherwise it returns RTL_NULL.

Additional information

In the flags parameter, you can specify the following flags:

  • VMM_FLAG_COMMIT – commits the virtual memory region in "lazy" mode, whereby the physical memory pages are allocated as virtual addresses are queried.
  • VMM_FLAG_LOCKED – commits the virtual memory region while allocating the entire required volume of physical memory.
  • VMM_FLAG_READ, VMM_FLAG_WRITE, VMM_FLAG_EXECUTE and VMM_FLAG_RWX_MASK – flags defining the access rights to the virtual memory region.
  • VMM_FLAG_LOW_GUARD, VMM_FLAG_HIGH_GUARD – adds a protected page to the beginning and end of the virtual memory region, respectively. The size of the protected page is not included in the size of the virtual memory region.
  • VMM_FLAG_GROW_DOWN – defines the direction in which the virtual memory is mapped to physical memory when "lazy" commitment mode is applied. If this flag is set, the virtual memory page containing the queried address and several preceding pages are mapped to physical memory. If this flag is not set, the virtual memory page containing the queried address and several subsequent pages are mapped to physical memory.

Permissible combinations of flags defining the access rights to the virtual memory region:

  • VMM_FLAG_READ – read access.
  • VMM_FLAG_READ | VMM_FLAG_WRITE – read-and-write access.
  • VMM_FLAG_READ | VMM_FLAG_EXECUTE – read-and-execute access.
  • VMM_FLAG_RWX_MASK or VMM_FLAG_READ | VMM_FLAG_WRITE | VMM_FLAG_EXECUTE – read/write/execute access.

KnVmCommit()

Purpose

Commits a virtual memory region.

Parameters

  • [in] addr – page-aligned base address of the virtual memory region.
  • [in] size – size of the virtual memory region in bytes. It must be a multiple of the memory page size.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnVmDecommit()

Purpose

Decommits a virtual memory region.

Parameters

  • [in] addr – page-aligned base address of the virtual memory region.
  • [in] size – size of the virtual memory region in bytes. It must be a multiple of the memory page size.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnVmProtect()

Purpose

Modifies the access rights to the virtual memory region.

Parameters

  • [in] addr – page-aligned base address of the virtual memory region.
  • [in] size – size of the virtual memory region in bytes. It must be a multiple of the memory page size.
  • [in] newFlags – flags defining the access rights to the virtual memory region. The flags are defined in the header file sysroot-*-kos/include/vmm/flags.h from the KasperskyOS SDK.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

In the newFlags parameter, you can specify the following combinations of flags:

  • VMM_FLAG_READ – read access.
  • VMM_FLAG_READ | VMM_FLAG_WRITE – read-and-write access.
  • VMM_FLAG_READ | VMM_FLAG_EXECUTE – read-and-execute access.
  • VMM_FLAG_RWX_MASK or VMM_FLAG_READ | VMM_FLAG_WRITE | VMM_FLAG_EXECUTE – read/write/execute access.
  • 0 – access denied.

KnVmUnmap()

Purpose

Frees up the virtual memory region.

Parameters

  • [in] addr – page-aligned base address of the virtual memory region.
  • [in] size – size of the virtual memory region in bytes. It must be a multiple of the memory page size.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnVmQuery()

Purpose

Gets information about a virtual memory page.

Parameters

  • [in] addr – address included in the virtual memory page.
  • [out] info – pointer to the structure containing information about the virtual memory page. The type of structure is defined in the header file sysroot-*-kos/include/vmm/info.h from the KasperskyOS SDK.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnVmReset()

Purpose

Decommits a virtual memory region.

Parameters

  • [in] addr – page-aligned base address of the virtual memory region.
  • [in] size – size of the virtual memory region in bytes. It must be a multiple of the memory page size.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Page top
[Topic libkos_vmm_api_base]

Creating shared memory

Information about API functions is provided in the table below.

Using the API

An MDL buffer is used to create shared memory. An MDL buffer consists of one or more physical memory regions that can be mapped to the memory of multiple processes at the same time. A kernel object known as a memory descriptor list is used to map the MDL buffer to process memory. A memory descriptor list (MDL) is a data structure containing the addresses and sizes of physical memory regions comprising the MDL buffer. The MDL buffer handle identifies the memory descriptor list.

To create shared memory, a process needs to create an MDL buffer, map it to its own memory, and pass the MDL buffer handle via IPC to other processes that also need to map this MDL buffer to their own memory.

To create an MDL buffer, call the KnPmmMdlCreate(), KnPmmMdlCreateFromBuf() or KnPmmMdlCreateFromVm() function. The KnPmmMdlCreateFromBuf() function creates an MDL buffer and copies data to it. The KnPmmMdlCreateFromVm() function creates an MDL buffer and maps it to the memory of the calling process.

To reserve a virtual memory region and map the MDL buffer to it, call the KnPmmMdlMap() function. An MDL buffer can be mapped to multiple virtual memory regions of the same process.

An MDL buffer can be used to transfer large volumes of data between processes without creating shared memory. In this case, you must make sure that the MDL buffer is not mapped to the memory of multiple processes at the same time. Interacting processes must take turns mapping the MDL buffer to their own memory, reading and/or writing data and then freeing the virtual memory region that is mapped to this MDL buffer.

The Kaspersky Security Module cannot control data that is transferred between processes via the MDL buffer.

Deleting an MDL buffer

To delete an MDL buffer, complete the following steps:

  1. Free the virtual memory regions mapped to the MDL buffer in all processes that are using this MDL buffer.

    To complete this step, use the KnVmUnmap() function.

  2. Close or revoke each MDL buffer handle in all processes that own these handles.

    To complete this step, use the KnHandleClose() and/or KnHandleRevoke() functions that are declared in the header file sysroot-*-kos/include/coresrv/handle/handle_api.h from the KasperskyOS SDK.

Information about API functions

vmm_api.h functions

Function

Information about the function

KnPmmMdlCreate()

Purpose

Creates an MDL buffer.

Parameters

  • [in] size – size of the MDL buffer in bytes. It must be a multiple of the memory page size.
  • [in] flags – flags defining the access rights to the MDL buffer. The parameter type and flags are defined in the header file sysroot-*-kos/include/vmm/flags.h from the KasperskyOS SDK.
  • [out] outHandle – pointer to the MDL buffer handle.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

In the flags parameter, you can specify the following combinations of flags:

  • VMM_FLAG_READ – read access.
  • VMM_FLAG_READ | VMM_FLAG_WRITE – read-and-write access.
  • VMM_FLAG_READ | VMM_FLAG_EXECUTE – read-and-execute access.
  • VMM_FLAG_RWX_MASK or VMM_FLAG_READ | VMM_FLAG_WRITE | VMM_FLAG_EXECUTE – read/write/execute access.

KnPmmMdlCreateFromVm()

Purpose

Creates an MDL buffer from physical memory that is mapped to the defined virtual memory region and maps the created MDL buffer to this region.

Parameters

  • [in] addr – page-aligned base address of the virtual memory region.
  • [in] size – size of the virtual memory region in bytes. It must be a multiple of the memory page size.
  • [in] flags – flags defining the access rights to the MDL buffer. The parameter type and flags are defined in the header file sysroot-*-kos/include/vmm/flags.h from the KasperskyOS SDK.
  • [out] outHandle – pointer to the MDL buffer handle.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

This function can be used if the defined virtual memory region is allocated with commitment.

In the flags parameter, you can specify the following combinations of flags:

  • VMM_FLAG_READ – read access.
  • VMM_FLAG_READ | VMM_FLAG_WRITE – read-and-write access.
  • VMM_FLAG_READ | VMM_FLAG_EXECUTE – read-and-execute access.
  • VMM_FLAG_RWX_MASK or VMM_FLAG_READ | VMM_FLAG_WRITE | VMM_FLAG_EXECUTE – read/write/execute access.

KnPmmMdlCreateFromBuf()

Purpose

Creates an MDL buffer and copies data from the defined buffer to the MDL buffer.

Parameters

  • [in] offset – offset (in bytes) in the MDL buffer where the data write operation must start.
  • [in] size – size of the MDL buffer in bytes. It must be a multiple of the memory page size. The following condition must also be fulfilled: size>=bufSize+offset.
  • [in] flags – flags defining the access rights to the MDL buffer. The parameter type and flags are defined in the header file sysroot-*-kos/include/vmm/flags.h from the KasperskyOS SDK.
  • [in] buf – pointer to the buffer containing the data.
  • [in] bufSize – size (in bytes) of the buffer containing the data.
  • [out] outHandle – pointer to the MDL buffer handle.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

In the flags parameter, you can specify the following combinations of flags:

  • VMM_FLAG_READ – read access.
  • VMM_FLAG_READ | VMM_FLAG_WRITE – read-and-write access.
  • VMM_FLAG_READ | VMM_FLAG_EXECUTE – read-and-execute access.
  • VMM_FLAG_RWX_MASK or VMM_FLAG_READ | VMM_FLAG_WRITE | VMM_FLAG_EXECUTE – read/write/execute access.

KnPmmMdlGetSize()

Purpose

Gets the size of the MDL buffer.

Parameters

  • [in] handle – MDL buffer handle.
  • [out] size – size (in bytes) of the MDL buffer.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnPmmMdlMap()

Purpose

Reserves a virtual memory region and maps the MDL buffer to it.

Parameters

  • [in] handle – MDL buffer handle.
  • [in] offset – offset (in bytes) in the MDL buffer where mapping should start. It must be a multiple of the memory page size.
  • [in] length – size (in bytes) of the part of the MDL buffer that needs to be mapped. It must be a multiple of the memory page size. The following condition must also be fulfilled: length<=size of MDL buffer-offset.
  • [in,optional] hint – page-aligned, preferred base address of the virtual memory region, or 0 to select this address automatically.
  • [in] prots – flags defining the parameters of the virtual memory region. The flags are defined in the header file sysroot-*-kos/include/vmm/flags.h from the KasperskyOS SDK.
  • [out] addr – pointer to the base address of the virtual memory region.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

In the prots parameter, you can specify the following flags:

  • VMM_FLAG_READ, VMM_FLAG_WRITE, VMM_FLAG_EXECUTE and VMM_FLAG_RWX_MASK – flags defining the access rights to the virtual memory region.
  • VMM_FLAG_LOW_GUARD, VMM_FLAG_HIGH_GUARD – adds a protected page to the beginning and end of the virtual memory region, respectively.

Permissible combinations of flags defining the access rights to the virtual memory region:

  • VMM_FLAG_READ – read access.
  • VMM_FLAG_READ | VMM_FLAG_WRITE – read-and-write access.
  • VMM_FLAG_READ | VMM_FLAG_EXECUTE – read-and-execute access.
  • VMM_FLAG_RWX_MASK or VMM_FLAG_READ | VMM_FLAG_WRITE | VMM_FLAG_EXECUTE – read/write/execute access.

KnPmmMdlClone()

Purpose

Creates an MDL buffer based on an existing one.

The MDL buffer is created from the same regions of physical memory as the original buffer.

Parameters

  • [in] origin – handle of the original MDL buffer.
  • [in] offset – offset (in bytes) in the original MDL buffer where duplication should start. It must be a multiple of the memory page size.
  • [in] length – size (in bytes) of the part of the original MDL buffer that needs to be duplicated. It must be a multiple of the memory page size. The following condition must also be fulfilled: length<=size of original MDL buffer-offset.
  • [out] clone – pointer to the handle of the created MDL buffer.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Page top
[Topic libkos_vmm_api_mdl]

Preparing ELF image segments to be loaded into process memory

Information about API functions is provided in the table below.

Using the API

MDL buffers are used not only to create shared memory, but also to load ELF image segments into the memory of a new process. (ELF image segments are loaded by the Einit initializing program, for example.)

The KnVmSegInitFromVm() and KnVmSegInitFromBuf() functions create an MDL buffer and put the ELF image segment into it so that this segment can then be loaded into the memory of a new process.

Deleting MDL buffers containing ELF image segments

To delete MDL buffers containing ELF image segments, you must terminate the new process whose memory is mapped to these MDL buffers. You also need to complete the following steps before or after termination of this process:

  1. Free the virtual memory regions that are mapped to the MDL buffers in the process that created these MDL buffers.

    This step is required only for MDL buffers that were created using the KnVmSegInitFromVm() function.

    To complete this step, use the KnVmUnmap() function.

  2. Close the handles of MDL buffers in the process that created these MDL buffers.

    To complete this step, use the KnHandleClose() function, which is declared in the header file sysroot-*-kos/include/coresrv/handle/handle_api.h from the KasperskyOS SDK.

Information about API functions

vmm_api.h functions

Function

Information about the function

KnVmSegInitFromVm()

Purpose

Creates an MDL buffer from physical memory that is mapped to the defined virtual memory region containing the ELF image segment.

Parameters

  • [out] seg – pointer to the structure describing the ELF image segment. This structure contains the handle of the MDL buffer (the h field) and is used to load an ELF image segment into process memory. The type of structure is defined in the header file sysroot-*-kos/include/coresrv/vmm/vmm_types.h from the KasperskyOS SDK.
  • [in,optional] loadAddr – page-aligned address for loading the ELF image segment into process memory, or 0 to select this address automatically.
  • [in] addr – page-aligned base address of the virtual memory region.
  • [in] size – size of the virtual memory region in bytes. It must be a multiple of the memory page size.
  • [in] flags – flags defining the access rights to the MDL buffer. The parameter type and flags are defined in the header file sysroot-*-kos/include/vmm/flags.h from the KasperskyOS SDK.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

This function can be used if the defined virtual memory region is allocated with commitment.

In the flags parameter, you can specify the following combinations of flags:

  • VMM_FLAG_READ – read access.
  • VMM_FLAG_READ | VMM_FLAG_WRITE – read-and-write access.
  • VMM_FLAG_READ | VMM_FLAG_EXECUTE – read-and-execute access.
  • VMM_FLAG_RWX_MASK or VMM_FLAG_READ | VMM_FLAG_WRITE | VMM_FLAG_EXECUTE – read/write/execute access.

KnVmSegInitFromBuf()

Purpose

Creates an MDL buffer and copies the ELF image segment from the defined buffer to the MDL buffer.

Parameters

  • [out] seg – pointer to the structure describing the ELF image segment. This structure contains the handle of the MDL buffer (the h field) and is used to load an ELF image segment into process memory. The type of structure is defined in the header file sysroot-*-kos/include/coresrv/vmm/vmm_types.h from the KasperskyOS SDK.
  • [in,optional] loadAddr – page-aligned address for loading the ELF image segment into process memory, or 0 to select this address automatically.
  • [in] offset – offset (in bytes) in the MDL buffer where writing of the ELF image segment must start.
  • [in] size – size (in bytes) of the ELF image segment. It must be a multiple of the memory page size.
  • [in] flags – flags defining the access rights to the MDL buffer. The parameter type and flags are defined in the header file sysroot-*-kos/include/vmm/flags.h from the KasperskyOS SDK.
  • [in] fileOffset – offset (in bytes) of the segment in the ELF image.
  • [in] buildId – pointer to the build ID. The linker writes this ID to the ELF image.
  • [in] buildIdSize – size (in bytes) of the build ID.
  • [in] buf – pointer to the buffer containing the ELF image segment.
  • [in] bufSize – size (in bytes) of the buffer containing the ELF image segment.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

In the flags parameter, you can specify the following combinations of flags:

  • VMM_FLAG_READ – read access.
  • VMM_FLAG_READ | VMM_FLAG_WRITE – read-and-write access.
  • VMM_FLAG_READ | VMM_FLAG_EXECUTE – read-and-execute access.
  • VMM_FLAG_RWX_MASK or VMM_FLAG_READ | VMM_FLAG_WRITE | VMM_FLAG_EXECUTE – read/write/execute access.

Page top
[Topic libkos_vmm_api_elf]

Allocating and freeing memory (alloc.h)

The API is defined in the header file sysroot-*-kos/include/kos/alloc.h from the KasperskyOS SDK.

The API is intended for allocating and freeing memory. Allocated memory is a committed virtual memory region that can be accessed for read-and-write operations.

Information about API functions is provided in the table below.

alloc.h functions

Function

Information about the function

KosMemAllocEx()

Purpose

Allocates memory.

Parameters

  • [in] size – size (in bytes) of the allocated memory. If you specify a size of zero, the function returns a pointer that can be passed to the KosMemFree() function.
  • [in] align – value defining the alignment of the allocated memory. It must be a power of two. The address of allocated memory can be unaligned (align=1) or aligned (align=2,4,...,2^N) to the boundary of a 2^N-byte sequence (for example, two-byte or four-byte).
  • [in] zeroed – value defining the initialization of the allocated memory (1 – initialize with zeros, 0 – do not initialize).

Returned values

If successful, the function returns the pointer to the allocated memory, otherwise it returns RTL_NULL.

KosMemAlloc()

Purpose

Allocates memory.

Parameters

  • [in] size – size (in bytes) of the allocated memory. If you specify a size of zero, the function returns a pointer that can be passed to the KosMemFree() function.

Returned values

If successful, the function returns the pointer to the allocated memory, otherwise it returns RTL_NULL.

KosMemZalloc()

Purpose

Allocates memory and initializes it with zeros.

Parameters

  • [in] size – size (in bytes) of the allocated memory. If you specify a size of zero, the function returns a pointer that can be passed to the KosMemFree() function.

Returned values

If successful, the function returns the pointer to the allocated memory, otherwise it returns RTL_NULL.

KosMemFree()

Purpose

Deallocates memory.

Parameters

  • [in] ptr – pointer to the freed memory. If you specify RTL_NULL, the function does not perform any actions.

Returned values

N/A

KosMemRealloc()

Purpose

Allocates memory and (optionally) copies the contents of previously allocated memory to the newly allocated memory and frees the previously allocated memory after the copy operation is complete.

Parameters

  • [in,optional] ptr – pointer to the previously allocated memory, or RTL_NULL if you only need to allocate memory without copying the contents of previously allocated memory.
  • [in] size – size (in bytes) of the newly allocated memory. The contents of previously allocated memory are copied to the newly allocated memory in whatever amount that can be accommodated in the newly allocated memory. If you specify a size of zero, the function returns a pointer that can be passed to the KosMemFree() function.

Returned values

If successful, the function returns the pointer to the allocated memory, otherwise it returns RTL_NULL.

KosMemReallocEx()

Purpose

Allocates memory and (optionally) copies the contents of previously allocated memory to the newly allocated memory and frees the previously allocated memory after the copy operation is complete.

Parameters

  • [in,optional] ptr – pointer to the previously allocated memory, or RTL_NULL if you only need to allocate memory without copying the contents of previously allocated memory.
  • [in] size – size (in bytes) of the newly allocated memory. The contents of previously allocated memory are copied to the newly allocated memory in whatever amount that can be accommodated in the newly allocated memory. If you specify a size of zero, the function returns a pointer that can be passed to the KosMemFree() function.
  • [in] zeroed – value defining the initialization of the allocated memory (1 – initialize with zeros, 0 – do not initialize). If the ptr parameter is used to pass RTL_NULL and the zeroed parameter is set to 1, the allocated memory will be initialized with zeros. If the size of the newly allocated memory is less than or equal to the size of the previously allocated memory, the value of the zeroed parameter does not affect the contents of the newly allocated memory. If the size of the newly allocated memory is greater than the size of the previously allocated memory, and the zeroed parameter is set to 1, the fragment of newly allocated memory that is not occupied by the contents copied from the previously allocated memory may be initialized with zeros. To ensure that this fragment is initialized with zeros, you must do the following. The memory must be initially allocated by using either the KosMemZalloc() function, the KosMemAllocEx() function with the zeroed parameter set to 1, or the KosMemReallocEx() function with the zeroed parameter set to 1 and the ptr parameter set to RTL_NULL. All subsequent KosMemReallocEx() calls must have the zeroed parameter set to 1.

Returned values

If successful, the function returns the pointer to the allocated memory, otherwise it returns RTL_NULL.

Page top
[Topic libkos_alloc_api]

Using DMA (dma.h)

The API is defined in the header file sysroot-*-kos/include/coresrv/io/dma.h from the KasperskyOS SDK.

The API is designed to set up data exchange between devices and RAM in direct memory access (DMA) mode in which the processor is not used.

Information about API functions is provided in the table below.

Using the API

The standard scenario for API usage includes the following steps:

  1. Creating a DMA buffer.

    DMA buffer consists of one or more physical memory regions (blocks) that are used for DMA. A DMA buffer consisting of multiple blocks can be used if the device supports "scatter/gather DMA" mode. A DMA buffer consisting of one block can be used only if the device supports "scatter/gather DMA" or "continuous DMA" mode. The likelihood of creating a DMA buffer consisting of one large block is lower than the likelihood of creating a DMA buffer consisting of multiple small blocks. This is especially relevant when physical memory is highly fragmented.

    If the device supports only "continuous DMA" mode, you must use a DMA buffer consisting of one block even if IOMMU is enabled.

    To complete this step, call the KnIoDmaCreate() or KnIoDmaCreateContinuous() function. The KnIoDmaCreateContinuous() function creates a DMA buffer consisting of one block. The KnIoDmaCreate() function creates a DMA buffer consisting of one block if the 2^order value is equal to the memory page size value, or if the 2^order value is the next largest value of the memory page size in the ascending ordered set {2^(order-1);memory page size;2^order}. If the value of the memory page size is greater than the 2^order value, the KnIoDmaCreate() function can create a DMA buffer consisting of multiple blocks.

    The DMA buffer handle can be transferred to another process via IPC.

  2. Mapping the DMA buffer to the memory of processes.

    One DMA buffer can be mapped to multiple virtual memory regions of one or more processes that own the handle of this DMA buffer. Mapping allows processes to receive read-and/or-write access to the DMA buffer.

    To reserve a virtual memory region and map the DMA buffer to it, call the KnIoDmaMap() function.

    A handle received when calling the KnIoDmaMap() function cannot be transferred to another process via IPC.

  3. Opening access to the DMA buffer for a device via the KnIoDmaBegin() or KnIoDmaBeginEx() function call.

    The KnIoDmaBegin() or KnIoDmaBeginEx() function must be called to create a kernel object containing the addresses and sizes of blocks comprising the DMA buffer. A device needs this information to use the DMA buffer. A device can work with physical addresses and/or virtual addresses depending on whether IOMMU is enabled. If IOMMU is enabled, you must use the KnIoDmaBegin() or KnIoDmaBeginEx() function, and the object will contain virtual and physical addresses of blocks. If IOMMU is not enabled, you must use the KnIoDmaBegin() function, and the object will contain physical addresses of blocks only.

    When IOMMU is enabled, the device must be attached to an IOMMU domain.

    A handle received when calling the KnIoDmaBegin() or KnIoDmaBeginEx() function cannot be transferred to another process via IPC.

  4. Information about the DMA buffer is received.

    At this step, get the addresses and sizes of blocks from the kernel object that was created by calling the KnIoDmaBegin() or KnIoDmaBeginEx() function. The received addresses and sizes will need to be passed to the device by using MMIO, for example. After receiving this information, the device can write to the DMA buffer and/or read from it.

    To complete this step, call one of the following functions:

    • KnIoDmaGetInfo()
    • KnIoDmaGetPhysInfo()
    • KnIoDmaContinuousGetDmaAddr()
    • KnIoDmaContinuousGetPhysAddr()

    The KnIoDmaGetInfo() and KnIoDmaGetPhysInfo() functions get the memory page number (frame) and the order for each block. (The memory page number multiplied by the memory page size results in the block address. The 2^order value is the block size in memory pages.) These functions use the output parameter outInfo to pass the KosObject that contains the structure with information about the DMA buffer (for details about KosObjects, see Using KosObjects (objects.h)). The type of structure is defined in the header file sysroot-*-kos/include/io/io_dma.h from the KasperskyOS SDK. The KnIoDmaGetInfo() function inserts data into all fields of the structure, while the KnIoDmaGetPhysInfo() function inserts data only into the count and descriptors fields while writing zeros to all other fields. When using the KnIoDmaGetInfo() function, the descriptors array contains virtual memory page numbers if IOMMU is enabled, and it contains physical memory page numbers if IOMMU is not enabled. When using the KnIoDmaGetPhysInfo() function, the descriptors array contains physical memory page numbers regardless of whether or not IOMMU is enabled.

    The KnIoDmaContinuousGetDmaAddr() and KnIoDmaContinuousGetPhysAddr() functions can be used if the DMA buffer consists of one block. These functions let you get the block address. (The accepted block size should be the DMA buffer size that was defined when it was created.) The KnIoDmaContinuousGetDmaAddr() function uses the output parameter addr to pass the virtual address if IOMMU is enabled or the physical address if IOMMU is not enabled. The KnIoDmaContinuousGetPhysAddr() function uses the output parameter addr to pass the physical address, regardless of whether or not IOMMU is enabled.

    On Raspberry Pi 4 B, the KnIoDmaGetPhysInfo() function lets you get the actual physical page numbers, while the KnIoDmaGetInfo() function lets you get the offset physical page numbers because some devices use Visual Processing Unit (VPU) translation for DMA. Similarly, the KnIoDmaContinuousGetPhysAddr() and KnIoDmaContinuousGetDmaAddr() functions let you get the actual and offset physical address, respectively.

Closing access to the DMA buffer for a device

Access to the DMA buffer can be closed only if IOMMU is enabled. If you delete the kernel object that was created when the KnIoDmaBegin() or KnIoDmaBeginEx() function was called, device access to the DMA buffer will be closed. To delete this object, you must close its handle.

Deleting a DMA buffer

To delete a DMA buffer, complete the following steps:

  1. Free the virtual memory regions that were reserved during KnIoDmaMap() function calls.

    To complete this step, you must close the handles that were received from KnIoDmaMap() function calls.

    This step must be completed for all processes whose memory is mapped to the DMA buffer.

  2. Delete the kernel object that was created by the KnIoDmaBegin() or KnIoDmaBeginEx() function call.

    To complete this step, you must close the handle that was received when the KnIoDmaBegin() or KnIoDmaBeginEx() function was called.

  3. Close or revoke each DMA buffer handle in all processes that own these handles.

Information about API functions

dma.h functions

Function

Information about the function

KnIoDmaCreate()

Purpose

Creates a DMA buffer.

Parameters

  • [in] order – parameter defining the minimum number of memory pages (2^order) in a block.
  • [in] size – size (in bytes) of the DMA buffer. It must be a multiple of the memory page size.
  • [in] flags – flags defining the DMA buffer parameters. The parameter type and flags are defined in the header file sysroot-*-kos/include/io/io_dma.h from the KasperskyOS SDK.
  • [out] outRid – pointer to the DMA buffer handle.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

In the flags parameter, you can specify the following flags:

  • DMA_DIR_TO_DEVICE – the device has read-access to the DMA buffer.
  • DMA_DIR_FROM_DEVICE – the device has write-access to the DMA buffer.
  • DMA_DIR_BIDIR – the device has read-and-write access to the DMA buffer.
  • DMA_ZONE_DMA32 – only the first four gigabytes of physical memory can be used to create a DMA buffer.
  • DMA_ATTR_WRITE_BACK, DMA_ATTR_WRITE_THROUGH, DMA_ATTR_CACHE_DISABLE, DMA_ATTR_WRITE_COMBINE, DMA_RULE_CACHE_VOLATILE, DMA_RULE_CACHE_FIXED – cache management.

KnIoDmaCreateContinuous()

Purpose

Creates a DMA buffer consisting of one block.

Parameters

  • [in] size – size (in bytes) of the DMA buffer. It must be a multiple of the memory page size.
  • [in] flags – flags defining the DMA buffer parameters. The parameter type and flags are defined in the header file sysroot-*-kos/include/io/io_dma.h from the KasperskyOS SDK.
  • [out] outRid – pointer to the DMA buffer handle.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

In the flags parameter, you can specify the following flags:

  • DMA_DIR_TO_DEVICE – the device has read-access to the DMA buffer.
  • DMA_DIR_FROM_DEVICE – the device has write-access to the DMA buffer.
  • DMA_DIR_BIDIR – the device has read-and-write access to the DMA buffer.
  • DMA_ZONE_DMA32 – only the first four gigabytes of physical memory can be used to create a DMA buffer.
  • DMA_ATTR_WRITE_BACK, DMA_ATTR_WRITE_THROUGH, DMA_ATTR_CACHE_DISABLE, DMA_ATTR_WRITE_COMBINE, DMA_RULE_CACHE_VOLATILE, DMA_RULE_CACHE_FIXED – cache management.

KnIoDmaMap()

Purpose

Reserves a virtual memory region and maps the DMA buffer to it.

Parameters

  • [in] rid – DMA buffer handle.
  • [in] offset – offset (in bytes) in the DMA buffer where mapping should start. It must be a multiple of the memory page size.
  • [in] length – size (in bytes) of the part of the DMA buffer that needs to be mapped. It must be a multiple of the memory page size. The following condition must also be fulfilled: length<=size of DMA buffer-offset.
  • [in,optional] hint – page-aligned, preferred base address of the virtual memory region, or 0 to select this address automatically.
  • [in] vmflags – flags defining the access rights to the virtual memory region. The flags are defined in the header file sysroot-*-kos/include/vmm/flags.h from the KasperskyOS SDK.
  • [out] addr – pointer to the base address of the virtual memory region.
  • [out] handle – pointer to the handle that is used to free the virtual memory region.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

In the vmflags parameter, you can specify the following flags:

  • VMM_FLAG_READ – read access.
  • VMM_FLAG_WRITE – write access.

KnIoDmaModify()

Purpose

Modifies the DMA buffer cache settings.

Parameters

  • [in] rid – DMA buffer handle.
  • [in] newAttr – flags defining the DMA buffer caching parameters. The flags are defined in the header file sysroot-*-kos/include/io/io_dma.h from the KasperskyOS SDK.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

This function can be used if the following conditions are fulfilled:

  1. The DMA_RULE_CACHE_VOLATILE flag was specified when the DMA buffer was created.
  2. The DMA buffer is not mapped to virtual memory.
  3. The DMA_RULE_CACHE_VOLATILE flag was specified during the previous function call (if completed).

In the newAttr parameter, you can specify the following flags:

  • DMA_ATTR_WRITE_BACK, DMA_ATTR_WRITE_THROUGH, DMA_ATTR_CACHE_DISABLE, DMA_ATTR_WRITE_COMBINE, DMA_RULE_CACHE_VOLATILE – cache management.

KnIoDmaGetInfo()

Purpose

Gets information about a DMA buffer.

This information includes the addresses and sizes of blocks.

Parameters

  • [in] rid – DMA buffer handle.
  • [out] outInfo – pointer to the address of the object containing the structure with information about the DMA buffer. The type of structure is defined in the header file sysroot-*-kos/include/io/io_dma.h from the KasperskyOS SDK.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

To delete an object that was received via the outInfo parameter, you must use the KosPutObject() function from the objects.h API.

KnIoDmaGetPhysInfo()

Purpose

Gets the physical addresses and sizes of DMA buffer blocks.

Parameters

  • [in] rid – DMA buffer handle.
  • [out] outInfo – pointer to the address of the object containing the structure with information about the DMA buffer. The type of structure is defined in the header file sysroot-*-kos/include/io/io_dma.h from the KasperskyOS SDK.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

To delete an object that was received via the outInfo parameter, you must use the KosPutObject() function from the objects.h API.

KnIoDmaContinuousGetDmaAddr()

Purpose

Gets the block address for a DMA buffer consisting of one block.

Parameters

  • [in] rid – DMA buffer handle.
  • [out] addr – pointer to the block address. The type of address is defined in the header file sysroot-*-kos/include/hal/mtypes.h from the KasperskyOS SDK.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnIoDmaContinuousGetPhysAddr()

Purpose

Gets the block physical address for a DMA buffer consisting of one block.

Parameters

  • [in] rid – DMA buffer handle.
  • [out] addr – pointer to the physical block address. The type of address is defined in the header file sysroot-*-kos/include/hal/mtypes.h from the KasperskyOS SDK.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnIoDmaBegin()

Purpose

Opens access to a DMA buffer for a device.

Parameters

  • [in] rid – DMA buffer handle.
  • [out] handle – pointer to the handle of the kernel object containing the addresses and sizes of blocks that were required for the device to use the DMA buffer.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnIoDmaBeginEx()

Purpose

Opens access to a DMA buffer for a device.

Parameters

  • [in] rid – DMA buffer handle.
  • [in] domain – IOMMU domain handle.
  • [out] handle – pointer to the handle of the kernel object containing the addresses and sizes of blocks that were required for the device to use the DMA buffer.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Page top
[Topic libkos_dma_api]

Memory-mapped I/O (mmio.h)

The API is defined in the header file sysroot-*-kos/include/coresrv/io/mmio.h from the KasperskyOS SDK.

The API is intended for working with MMIO memory. MMIO memory consists of physical addresses that are mapped to registers and memory of devices. (Portions of one physical address space are used for physical memory addressing and access to registers and memory of devices.)

Information about API functions is provided in the table below.

Using the API

The standard scenario for API usage includes the following steps:

  1. The MMIO memory region corresponding to the relevant device is registered.

    To complete this step, call the KnRegisterPhyMem() function.

    The handle of an MMIO memory region can be transferred to another process via IPC.

  2. Mapping the MMIO memory region to the memory of a process.

    An MMIO memory region can only be mapped to one virtual memory region of only one process at one time. (However, an MMIO memory region may be mapped to the virtual memory of different processes that own the handle of this region at different times.) Mapping allows the process to receive read-and/or-write access to the MMIO memory region.

    To reserve a virtual memory region and map the MMIO memory region to it, call the KnIoMapMem() function.

    A handle received when calling the KnIoMapMem() function cannot be transferred to another process via IPC.

  3. Reading data from the MMIO memory region and writing data to it via process memory.

    The 8-, 16- and 32-bit words that are read from the MMIO memory region or written to it are values of device registers or contents of device memory.

    To complete this step, use the IoReadMmReg8|16|32(), IoReadMmBuffer8|16|32(), IoWriteMmReg8|16|32(), and IoWriteMmBuffer8|16|32() functions.

Deregistering an MMIO memory region

To deregister an MMIO memory region, complete the following steps:

  1. Free the virtual memory region that was allocated when the KnIoMapMem() function was called.

    To complete this step, call the KnHandleClose() function and specify the handle that was received when the KnIoMapMem() function was called. (The KnHandleClose() function is declared in the header file sysroot-*-kos/include/coresrv/handle/handle_api.h from the KasperskyOS SDK.)

  2. Close or revoke each MMIO memory region handle in all processes that own these handles.

    To complete this step, use the KnHandleClose() and/or KnHandleRevoke() functions that are declared in the header file sysroot-*-kos/include/coresrv/handle/handle_api.h from the KasperskyOS SDK.

Information about API functions

mmio.h functions

Function(s)

Information about the function(s)

KnRegisterPhyMem()

Purpose

Registers an MMIO memory region.

Parameters

  • [in] addr – page-aligned base address of the MMIO memory region.
  • [in] size – size of the MMIO memory region. It must be a multiple of the memory page size.
  • [out] outRid – pointer to the handle of the MMIO memory region.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnIoMapMem()

Purpose

Reserves the virtual memory region and maps the MMIO memory region to it.

Parameters

  • [in] rid – handle of the MMIO memory region.
  • [in] prot – flags defining the access rights to the virtual memory region. The flags are defined in the header file sysroot-*-kos/include/vmm/flags.h from the KasperskyOS SDK.
  • [in] attr – flags defining the cache settings. The flags are defined in the header file sysroot-*-kos/include/vmm/flags.h from the KasperskyOS SDK.
  • [out] addr – pointer to the base address of the virtual memory region.
  • [out] handle – pointer to the handle that is used to free the virtual memory region.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

In the prot parameter, you can specify the following flags:

  • VMM_FLAG_READ – read access.
  • VMM_FLAG_WRITE – write access.

In the attr parameter, you can specify the following flags:

  • VMM_FLAG_WRITE_BACK, VMM_FLAG_WRITE_THROUGH, VMM_FLAG_WRITE_COMBINE, VMM_FLAG_CACHE_DISABLE – cache management.

    It is recommended to specify the VMM_FLAG_CACHE_DISABLE flag.

IoReadMmReg8()

IoReadMmReg16()

IoReadMmReg32()

Purpose

Get an 8-, 16- or 32-bit word from an MMIO memory region.

Parameters

  • [in] reg – virtual address for reading the word.

Returned values

8-, 16- or 32-bit word from the MMIO memory region.

IoReadMmBuffer8()

IoReadMmBuffer16()

IoReadMmBuffer32()

Purpose

Save a sequence of 8-, 16- or 32-bit words from the MMIO memory region to the buffer.

Parameters

  • [in] baseReg – virtual address of the first word in the sequence.
  • [out] dst – pointer to the buffer used to store the sequence of words.
  • [in] cnt – number of words in the sequence.

Returned values

N/A

Additional information

The functions can be used if the processor has an x86 or x86-64 architecture.

IoWriteMmReg8()

IoWriteMmReg16()

IoWriteMmReg32()

Purpose

Write an 8-, 16- or 32-bit word to an MMIO memory region.

Parameters

  • [in] reg – virtual address for writing the word.
  • [in] data – word to write.

Returned values

N/A

IoWriteMmBuffer8()

IoWriteMmBuffer16()

IoWriteMmBuffer32()

Purpose

Write a sequence of 8-, 16- or 32-bit words from the buffer to an MMIO memory region.

Parameters

  • [in] baseReg – virtual address for writing the sequence of words.
  • [in] src – pointer to the buffer containing the sequence of words.
  • [in] cnt – number of words in the sequence.

Returned values

N/A

Additional information

The functions can be used if the processor has an x86 or x86-64 architecture.

Page top
[Topic libkos_mmio_api]

Managing interrupt processing (irq.h)

The API is defined in the header file sysroot-*-kos/include/coresrv/io/irq.h from the KasperskyOS SDK.

The API manages the handling of hardware interrupts. A hardware interrupt is a signal sent from a device to direct the processor to immediately pause execution of the current program and instead handle an event related to this device. For example, pressing a key on the keyboard invokes a hardware interrupt that ensures the required response to this pressed key (for example, input of a character).

A hardware interrupt occurs when the device queries the interrupt controller. This query can be transmitted through a hardware interrupt line between the device and the interrupt controller or through MMIO memory. In the second case, the device writes to MMIO memory by calling the Message Signaled Interrupt (MSI).

At present, no functions for managing the handling of MSI interrupts have been implemented.

Each hardware interrupt line corresponds to one interrupt with a unique number.

Information about API functions is provided in the table below.

Using the API

To attach an interrupt to its handler, complete the following steps:

  1. Registering an interrupt by calling the KnRegisterIrq() function.

    One interrupt can be registered multiple times in one or more processes.

    The handle of an interrupt can be transferred to another process via IPC.

  2. Attaching a thread to an interrupt by calling the KnIoAttachIrq() function.

    This step is performed by the thread in whose context the interrupt will be handled.

    When using the handle received from the KnRegisterIrq() function call, you can attach only one thread to an interrupt. To attach multiple threads in one or more processes to an interrupt, use different handles for this interrupt received from separate KnRegisterIrq() function calls. In this case, the KnIoAttachIrq() function must be called with the same flags in the flags parameter.

    A handle received when calling the KnIoAttachIrq() function cannot be transferred to another process via IPC.

To deny (mask) an interrupt, call the KnIoDisableIrq() function. To allow (unmask) an interrupt, call the KnIoEnableIrq() function. Even though these functions receive an interrupt handle that is used to attach only one thread to the interrupt, their action is applied to all threads that are attached to this interrupt. These functions must be called outside of the threads attached to the interrupt. After an interrupt is registered and a thread is attached to it, this interrupt does not require unmasking.

To initiate detachment of a thread from an interrupt, call the KnIoDetachIrq() function outside of the thread that is attached to the interrupt. Detachment is performed by the thread attached to the interrupt by calling the KnThreadDetachIrq() function declared in the header file sysroot-*-kos/include/coresrv/thread/thread_api.h from the KasperskyOS SDK.

Handling an interrupt

After attaching to an interrupt, a thread calls the Call() function declared in the header file sysroot-*-kos/include/coresrv/syscalls.h from the KasperskyOS SDK. The thread is locked as a result of this call. When an interrupt occurs or the KnIoDetachIrq() function is called, the KasperskyOS kernel sends an IPC message to the process that contains this thread. This IPC message contains a request to handle the interrupt or a request to detach the thread from the interrupt. When a process receives an IPC message, the Call() function in the thread attached to the interrupt returns control and provides the contents of the IPC message to the thread. The thread extracts the request from the IPC message and either processes the interrupt or detaches from the interrupt. If the interrupt is processed, information about its failure or success upon completion is added to the response IPC message that is sent to the kernel by the next Call() function call in the loop.

When processing an interrupt, use the IoGetIrqRequest() and IoSetIrqAnswer() functions that are declared in the header file sysroot-*-kos/include/io/io_irq.h from the KasperskyOS SDK. These functions let you extract data from IPC messages and add data to IPC messages for data exchange between the kernel and the thread attached to the interrupt.

The standard interrupt processing loop includes the following steps:

  1. Adding information about the failure or success of interrupt processing to an IPC message by calling the IoSetIrqAnswer() function.
  2. Sending the IPC message to the kernel and receiving an IPC message from the kernel.

    To complete this step, call the Call() functions. In the handle parameter, you must specify the handle that was received when the KnIoAttachIrq() function was called. You must use the msgOut parameter to define the IPC message that will be sent to the kernel, and use the msgIn parameter to define the IPC message that will be received from the kernel.

  3. Extracting a request from the IPC message received from the kernel by calling the IoGetIrqRequest() function.
  4. Processing the interrupt or detaching from the interrupt depending on the request.

    If the request requires detachment from the interrupt, exit the interrupt processing loop and call the KnThreadDetachIrq() function.

Deregistering an interrupt

To deregister an interrupt, complete the following steps:

  1. Detach the thread from the interrupt.

    To complete this step, call the KnThreadDetachIrq() function.

  2. Close the handle that was received when the KnIoAttachIrq() function was called.

    To complete this step, call the KnHandleClose() function. (The KnHandleClose() function is declared in the header file sysroot-*-kos/include/coresrv/handle/handle_api.h from the KasperskyOS SDK.)

  3. Close or revoke each interrupt handle in all processes that own these handles.

    To complete this step, use the KnHandleClose() and/or KnHandleRevoke() functions that are declared in the header file sysroot-*-kos/include/coresrv/handle/handle_api.h from the KasperskyOS SDK.

One interrupt can be registered multiple times, but completion of these steps cancels only one registration. The other registrations will remain active. Each registration of one interrupt must be canceled separately.

Information about API functions

irq.h functions

Function

Information about the function

KnRegisterIrq()

Purpose

Registers an interrupt.

Parameters

  • [in] irq – interrupt number.
  • [out] outRid – pointer to the interrupt handle.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnIoAttachIrq()

Purpose

Attaches the calling thread to an interrupt.

Parameters

  • [in] rid – interrupt handle.
  • [in] flags – flags defining the interrupt parameters. Flags are defined in the header files sysroot-*-kos/include/io/io_irq.h and sysroot-*-kos/include/hal/irqmode.h from the KasperskyOS SDK.
  • [out] handle – pointer to the client IPC handle that is used by the interrupt handler.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

In the flags parameter, you can specify the following flags:

  • IRQ_LEVEL_LOW – the interrupt occurs when the signal level is low.
  • IRQ_LEVEL_HIGH – the interrupt occurs when the signal level is high.
  • IRQ_EDGE_RAISE – the interrupt occurs when the signal level increases.
  • IRQ_EDGE_FALL – the interrupt occurs when the signal level decreases.
  • IRQ_PRIO_LOW – the interrupt has low priority.
  • IRQ_PRIO_NORMAL – the interrupt has medium priority.
  • IRQ_PRIO_HIGH – the interrupt has high priority.
  • IRQ_PRIO_RT – the interrupt has the highest priority.

KnIoDetachIrq()

Purpose

Sends a request to a thread. When this request is fulfilled, the thread must detach from the interrupt.

Parameters

  • [in] rid – interrupt handle.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnIoEnableIrq()

Purpose

Allows (unmasks) an interrupt.

Parameters

  • [in] rid – interrupt handle.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnIoDisableIrq()

Purpose

Denies (masks) an interrupt.

Parameters

  • [in] rid – interrupt handle.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Page top
[Topic libkos_irq_api]

Managing threads (high-level API thread.h)

The API is defined in the header file sysroot-*-kos/include/kos/thread.h from the KasperskyOS SDK.

Main capabilities of the API:

  • Create, terminate, and lock threads.
  • Resume execution of locked threads.
  • Register functions that are called when creating and terminating threads.

Information about API functions is provided in the table below.

The libkos library also provides a low-level API for thread management. This API is defined in the header file sysroot-*-kos/include/coresrv/thread/thread_api.h from the KasperskyOS SDK. The low-level API should be used only if the high-level API does not have sufficient capabilities.

Creating threads

To create a thread, call the KosThreadCreate() or KosThreadCreateDetached() function. These functions create a standard thread with priority ranging from 0–15. (For details about standard threads, see Managing threads (low-level API thread_api.h)).

Terminating threads

When a thread is terminated, it is permanently deleted from the scheduler. A thread is terminated in the following cases:

  • The function executed by the thread is exited.

    The root function (not a nested function) performed by the thread must be exited by the return operator.

  • The KosThreadTerminate() or KosThreadExit() function is called.

    The KosThreadExit() function terminates the thread even if the function is called from a nested function instead of the root function executed by the thread.

  • The process was terminated or switched to the "frozen" state.

    For details about the "frozen" state, see Managing processes (low-level API task_api.h).

Thread exit codes are defined by the developer of the KasperskyOS-based solution. These codes should be specified in the exitCode parameter of the KosThreadTerminate() and KosThreadExit() functions, and when calling the return operator in the function executed by the thread. To get the thread exit code, call the KosThreadWait() function. If successful, this function returns the thread exit code. Otherwise, it returns -1. Therefore, thread exit codes must differ from -1 to avoid ambiguity.

Registering functions that are called when creating and terminating threads

To register a function that is called when threads of a process are created and terminated, call the KosThreadCallbackRegister() function from this process.

The registered function is called in the following cases:

  • A thread is created by calling the KosThreadCreate() function.
  • The thread that was created by calling the KosThreadCreate() function is terminated as a result of exiting a function executed by this thread.
  • The thread is terminated by calling the KosThreadExit() function.

You can register multiple functions, and each of them will be called when a thread is created and terminated. When a thread is created, the registered function is called with the KosThreadCallbackReasonCreate argument in the reason parameter. When the thread is terminated, the registered function is called with the KosThreadCallbackReasonDestroy argument in the reason parameter.

Guaranteeing that a function can only be called once

The callback function defined through the initRoutine parameter is called only when the KosThreadOnce() function is called for the first time. This does not occur on repeated calls of the KosThreadOnce() function (even from other threads), and the KosThreadOnce() function simply returns control. For example, this ensures that a driver is initialized only once when multiple software components use this driver and start its initialization irrespective of each other.

Special considerations for threads attached to interrupts

After a thread is attached to an interrupt, the thread becomes a real-time thread with a FIFO scheduler class and a priority higher than 31. (For details about attaching a thread to an interrupt, see Managing interrupt processing (irq.h). For details about the FIFO real-time thread scheduler class, see Managing threads (low-level API thread_api.h)).

Many API functions cannot be applied for threads that are attached to interrupts. These functions include KosThreadCreate(), KosThreadSuspend(), KosThreadResume(), KosThreadTerminate(), KosThreadWait(), KosThreadSleep(), and KosThreadYield().

Defining and getting the base address of the TLS for threads

A thread local storage (TLS) is process memory in which a thread can store data in isolation from other threads. The base address for TLS is defined and received by the KosThreadTlsSet() and KosThreadTlsGet() functions, respectively. These functions are intended for use by the libc library.

Getting the base address and stack limit of threads

The KosThreadGetStack() function gets the base address and stack limit of the thread. This function is intended for use by the libc library.

Freeing resources of terminated threads

Resources of a thread include its stack, context, and TCB (for details about a TCB, see Managing threads (low-level API thread_api.h)). To release thread resources after the thread terminates, call the KosThreadWait() function to wait for completion of the thread. (Exceptions to this case are the initial thread of a process and a thread created by the KosThreadCreateDetached() function.) Thread resources are also released upon termination of the process that includes these threads.

Information about API functions

thread.h functions

Function

Information about the function

KosThreadCallbackRegister()

Purpose

Registers the function that is called when creating and terminating threads of the calling process.

Parameters

  • [in] callback – pointer to the function.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosThreadCallbackUnregister()

Purpose

Deregisters the function that is called when creating and terminating threads of the calling process.

Parameters

  • [in] callback – pointer to the function.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosThreadCreate()

Purpose

Creates a thread.

Parameters

  • [out] handle – pointer to the thread handle.
  • [in] priority – thread priority.
  • [in,optional] stackSize – thread stack limit (in bytes), or 0 to use the default size that was defined when the process was created.
  • [in] routine – pointer to the function executed by the thread. The parameter type is defined in the header file sysroot-*-kos/include/coresrv/thread/thread_api.h from the KasperskyOS SDK.
  • [in,optional] context – pointer to the parameters passed to the function defined through the routine parameter, or RTL_NULL if parameters do not need to be passed to this function.
  • [in] suspended – value defining whether the thread will be created in a locked state (1) or unlocked state (0).

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosThreadCreateDetached()

Purpose

Creates an unlocked thread and closes its handle.

Parameters

  • [in] priority – thread priority.
  • [in,optional] stackSize – thread stack limit (in bytes), or 0 to use the default size that was defined when the process was created.
  • [in] routine – pointer to the function executed by the thread. The parameter type is defined in the header file sysroot-*-kos/include/coresrv/thread/thread_api.h from the KasperskyOS SDK.
  • [in,optional] context – pointer to the parameters passed to the function defined through the routine parameter, or RTL_NULL if parameters do not need to be passed to this function.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosThreadCurrentId()

Purpose

Gets the ID (TID) of the calling thread.

Parameters

N/A

Returned values

Thread ID. The ID type is defined in the header file sysroot-*-kos/include/thread/tidtype.h from the KasperskyOS SDK.

KosThreadSuspend()

Purpose

Locks the calling thread.

Parameters

  • [in] handle – thread handle.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosThreadResume()

Purpose

Resumes execution of a locked thread.

Parameters

  • [in] handle – thread handle.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosThreadExit()

Purpose

Terminates the calling thread.

Parameters

  • [in] exitCode – thread exit code.

Returned values

N/A

KosThreadWait()

Purpose

Locks the calling thread until the defined thread is terminated.

Parameters

  • [in] handle – thread handle.
  • [in] timeout – timeout (in milliseconds) for the termination of a thread, or INFINITE_TIMEOUT to define an unlimited timeout.

Returned values

If successful, the function returns the thread exit code, otherwise it returns -1.

KosThreadSleep()

Purpose

Locks the calling thread for the specified duration.

Parameters

  • [in] mdelay – thread lockout duration (in milliseconds).

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosThreadYield()

Purpose

Gives up the time slice of the calling thread to the next thread in the queue.

Parameters

N/A

Returned values

N/A

Additional information

The KosThreadYield() function call is identical to the KosThreadSleep() function call with a zero value for the mdelay parameter.

KosThreadTerminate()

Purpose

Terminates a thread.

Parameters

  • [in] handle – thread handle.
  • [in] exitCode – thread exit code.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosThreadTlsGet()

Purpose

Gets the base address of the thread local storage (TLS) for the calling thread.

Parameters

N/A

Returned values

Pointer to the TLS, or RTL_NULL if the thread does not have a TLS.

KosThreadTlsSet()

Purpose

Defines the base address of the thread local storage (TLS) for the calling thread.

Parameters

  • [in] tls – pointer to the TLS.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosThreadGetStack()

Purpose

Gets the base address and stack limit of the thread.

Parameters

  • [in] handle – thread handle.
  • [out] size – pointer to the stack limit (in bytes).

Returned values

Pointer to the thread stack.

KosThreadOnce()

Purpose

Guarantees that the defined function will be called only once.

Parameters

  • [in] onceControl – pointer to the variable that indicates whether or not the defined function was already called. This variable must be initialized with the KOS_THREAD_ONCE_INIT value.
  • [in] initRoutine – pointer to the function that must be called only one time.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Page top
[Topic libkos_thread_high_api]

Managing threads (low-level API thread_api.h)

The API is defined in the header file sysroot-*-kos/include/coresrv/thread/thread_api.h from the KasperskyOS SDK.

Main capabilities of the API:

  • Create, terminate, and lock threads.
  • Resume execution of locked threads.
  • Change the priorities and scheduler classes of threads.
  • Handle exceptions.
  • Detach threads from interrupts.
  • Attach threads to processors (processor cores).

API functions that take the thread ID (TID) as input or return it are obsolete and will be removed in the future. These functions are not described in this section.

Information about API functions is provided in the table below.

The libkos library also provides a high-level API for thread management. This API is defined in the header file sysroot-*-kos/include/kos/thread.h from the KasperskyOS SDK. It is recommended to use this specific API. The low-level API should be used only if the high-level API does not have sufficient capabilities.

Creating threads. Thread scheduler classes

To create a thread, call the KnThreadCreateByHandle() function. You can use the flags parameter of this function for the created thread to define the following scheduler classes:

  • Class for scheduling standard threads.
  • Class for scheduling FIFO real-time threads (First In, First Out).
  • Class for scheduling RR real-time threads Round-Robin).

The priority of a standard thread can take values ranging from 0 to 15. The higher the priority of a standard thread, the larger the time slice allocated to this thread and the more frequently these time slices are allocated. One standard thread with a high priority can occupy multiple consecutive places in the thread queue. Standard threads cannot supersede other standard threads or real-time threads, regardless of their respective priorities. If a real-time thread appears in the queue, the current standard thread immediately transfers control to the real-time thread. If there are no real-time threads in the queue, the current standard thread transfers control to the next standard thread if the current one is terminated, becomes locked, uses up its time slice or gives it up to the next standard thread.

The priority of a real-time thread can take values ranging from 0 to 31. Higher-priority real-time threads supersede lower-priority real-time threads. Real-time threads also supersede standard threads, regardless of their respective priorities. Control is transferred from the current real-time thread to the next real-time thread in the queue in the following cases:

  • The current real-time thread with a FIFO scheduler class is terminated or locked, or a real-time thread with a higher priority appears in the queue.

    Until the real-time thread with a FIFO scheduler class is terminated, locked, or superseded by a real-time thread with a higher priority, it can retain control indefinitely and not transfer control to the next real-time thread.

  • The current real-time thread with an RR scheduler class is terminated, locked or uses up its time slice, or a real-time thread with a higher priority appears in the queue.

    A real-time thread with an RR scheduler class that is not terminated, locked, or superseded by a higher-priority real-time thread transfers control to the next one upon expiry of its time slice if the next one is a real-time thread with the same priority. Otherwise, it transfers control to itself again.

  • The current real-time thread has given up its time slice to the next real-time thread with the same priority in the queue.

    A real-time thread can give up its time slice to the next one in the queue if the next one is a real-time thread with the same priority. Otherwise, it transfers control to itself again.

Execution of lower-priority real-time threads begins only after each of the real-time threads with a higher priority is terminated or locked. Real-time threads with the same priority form a queue based on the FIFO principle.

The thread scheduler class can be changed by calling the KnThreadSetSchedPolicyByHandle() function. This function also changes the size of the time slice allocated to a real-time thread with an RR scheduler class. This value is the only parameter of a real-time thread RR scheduler class that has a default value of 10 ms but can take values ranging from 2 ms to 100 ms. The scheduler class of standard threads and the scheduler class of FIFO real-time threads do not have parameters.

The priority of a thread can be changed by calling the KnThreadSetSchedPolicyByHandle() or KnThreadSetPriorityByHandle() function.

After a thread is attached to an interrupt, the thread becomes a real-time thread with a FIFO scheduler class and a priority higher than 31, irrespective of the specific scheduler class and priority this thread had before it was attached to the interrupt. Managing interrupt processing (irq.h).)

Many API functions cannot be applied for threads that are attached to interrupts. These functions include KnThreadCreateByHandle(), KnThreadSetPriorityByHandle(), KnThreadSuspendCurrent(), KnThreadResumeByHandle(), KnThreadTerminateByHandle(), KnThreadWaitByHandle(), KnSleep(), and KnThreadSetSchedPolicyByHandle().

Creating thread handles

A thread handle is created whenever a thread is created by the KnThreadCreateByHandle() function call. A thread (including the initial thread) can also create its own handle by calling the KnThreadOpenCurrent() function.

A thread handle cannot be transferred to another process via IPC.

Handling exceptions

To register an exception handling function for a thread, call the KnThreadSetExceptionHandler() function. This function deregisters the previous exception handling function and returns its ID. By saving this ID, you can subsequently register the previous exception handling function again.

To get information about the last exception of a thread, call the KnThreadGetLastException() function in the exception handler.

Detaching threads from interrupts

To detach a thread from an interrupt, call the KnThreadDetachIrq() function. (For more details about using the KnThreadDetachIrq() function, see Managing interrupt processing (irq.h).)

After a thread is detached from an interrupt, the thread receives the scheduler class and priority that it had before it was attached to the interrupt.

Attaching threads to processors (processor cores)

To restrict the set of processors (processor cores) that can be used to execute a thread, define an affinity mask for this thread. An affinity mask is a bit mask indicating which specific processors or processor cores must execute the thread.

To create, adjust, and perform other operations with affinity masks, use the API that is defined in the header file sysroot-*-kos/include/rtl/cpuset.h from the KasperskyOS SDK.

To define a thread affinity mask, call the KnThreadSetAffinityByHandle() function.

Terminating threads

When a thread is terminated, it is permanently deleted from the scheduler. A thread is terminated in the following cases:

  • The function executed by the thread is exited.

    The root function (not a nested function) performed by the thread must be exited by the return operator.

  • The KnThreadTerminateByHandle() or KnThreadExit() function is called.

    The KnThreadExit() function terminates the thread even if the function is called from a nested function instead of the root function executed by the thread.

  • The process was terminated or switched to the "frozen" state.

    For details about the "frozen" state, see Managing processes (low-level API task_api.h).

Thread exit codes are defined by the developer of the KasperskyOS-based solution. These codes should be specified in the code parameter of the KnThreadTerminateByHandle() and KnThreadExit() functions, and when calling the return operator in the function executed by the thread. To get the thread exit code, call the KnThreadWaitByHandle() function.

Getting the address of the TCB and defining the base address of a TLS for threads

A thread control block (TCB) is a structure containing thread information that is used by the kernel to manage this specific thread. The type of structure is defined in the header file sysroot-*-kos/include/thread/tcbpage.h from the KasperskyOS SDK. A TCB contains the base address of the thread local storage (TLS). The KnThreadGetTcb() function gets the TCB address. The KnThreadSetTls() function defines the base address of the TLS. These functions are intended for use by the libc library.

Getting thread information

The KnThreadGetInfoByHandle() function gets the base address and stack limit of the thread, and the thread identifier (TID). This function is intended for use by the libc library.

Freeing resources of terminated threads

Resources of a thread include its stack, context, and TCB. To free the resources of a thread after the thread is terminated, you need to close its handle before or after termination of this thread by calling the KnHandleClose() function, which is declared in the header file sysroot-*-kos/include/coresrv/handle/handle_api.h from the KasperskyOS SDK (an exception to this case is the initial thread of a process whose resources are freed without calling the KnHandleClose() function if the initial thread did not create its own handle by calling the KnThreadOpenCurrent() function). Resources of threads are also freed upon termination of the process that includes these threads.

Information about API functions

thread_api.h functions

Function

Information about the function

KnThreadCreateByHandle()

Purpose

Creates a thread.

Parameters

  • [out,optional] thread – pointer to the thread handle. Specifying RTL_NULL closes the handle automatically after the thread is created.
  • [in] priority – thread priority.
  • [in,optional] stackSize – thread stack limit (in bytes), or 0 to use the default size that was defined when the process was created.
  • [in] startRoutine – parameter that must have the value RTL_NULL.
  • [in] routine – pointer to the function executed by the thread.
  • [in,optional] context – pointer to the parameters passed to the function defined through the routine parameter, or RTL_NULL if parameters do not need to be passed to this function.
  • [in] flags – flags defining the parameters for creating the thread.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

In the flags parameter, you can specify the following flags:

  • ThreadFlagCreateSuspended – creates a thread in the locked state.
  • ThreadFlagCreateSchedOther – creates a standard thread.
  • ThreadFlagCreateSchedFifo – creates a real-time thread with a FIFO scheduler class.
  • ThreadFlagCreateSchedRR – creates a real-time thread with an RR scheduler class.

A standard thread is created by default.

Handles of threads cannot be transferred between processes via IPC.

KnThreadOpenCurrent()

Purpose

Creates the handle of the calling thread.

Parameters

  • [out] thread – pointer to the thread handle.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnThreadGetPriorityByHandle()

Purpose

Gets the priority of a thread.

Parameters

  • [in] thread – thread handle.
  • [out] priority – pointer to the thread priority.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnThreadSetPriorityByHandle()

Purpose

Defines the priority of a thread.

Parameters

  • [in] thread – thread handle.
  • [in] priority – thread priority.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnThreadSuspendCurrent()

Purpose

Locks the calling thread.

Parameters

N/A

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnThreadResumeByHandle()

Purpose

Resumes execution of a locked thread.

Parameters

  • [in] thread – thread handle.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnThreadTerminateByHandle()

Purpose

Terminates a thread.

Parameters

  • [in] thread – thread handle.
  • [in] code – thread exit code.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnThreadExit()

Purpose

Terminates the calling thread.

Parameters

  • [in] code – thread exit code.

Returned values

Error code.

KnThreadGetInfoByHandle()

Purpose

Gets information about a thread.

Parameters

  • [in] thread – thread handle.
  • [out] info – pointer to the structure containing the base address of the thread stack and its size (in bytes), and the thread identifier (TID).

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnThreadWaitByHandle()

Purpose

Locks the calling thread until the defined thread is terminated.

Parameters

  • [in] thread – thread handle.
  • [in] msDelay – timeout (in milliseconds) for the termination of a thread, or INFINITE_TIMEOUT to define an unlimited timeout.
  • [out] exitCode – pointer to the thread exit code.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnSleep()

Purpose

Locks the calling thread for the specified duration.

Parameters

  • [in] mdelay – thread lockout duration (in milliseconds).

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnThreadGetTcb()

Purpose

Gets the address of the thread control block (TCB) for the calling thread.

Parameters

N/A

Returned values

Pointer to the TCB. The data type for TCB storage is defined in the header file sysroot-*-kos/include/thread/tcbpage.h from the KasperskyOS SDK.

KnThreadSetTls()

Purpose

Defines the base address of the thread local storage (TLS) for the calling thread.

Parameters

  • [in] tls – pointer to the TLS.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnThreadDetachIrq()

Purpose

Detaches the calling thread from the interrupt handled in its context.

Parameters

N/A

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnThreadSetExceptionHandler()

Purpose

Registers the exception handling function for the calling thread.

Parameters

  • [in,optional] handler – ID of the exception handling function, or RTL_NULL to deregister the previously registered exception handling function without registering a new one. The parameter type is defined in the header file sysroot-*-kos/include/thread/tcbpage.h from the KasperskyOS SDK.

Returned values

ID of the previously registered exception handling function if one exists, otherwise RTL_NULL. The type of returned value is defined in the header file sysroot-*-kos/include/thread/tcbpage.h from the KasperskyOS SDK.

KnThreadGetLastException()

Purpose

Gets information about the last exception of the calling thread.

Parameters

  • [out] exception – pointer to the structure containing information about the exception. The type of structure is defined in the header file sysroot-*-kos/include/thread/tcbpage.h from the KasperskyOS SDK.

Returned values

N/A

KnThreadGetAffinityByHandle()

Purpose

Gets a thread affinity mask.

Parameters

  • [in] thread – thread handle.
  • [out] mask – pointer to the structure containing the thread affinity mask. The type of structure is defined in the header file sysroot-*-kos/include/rtl/cpuset.h from the KasperskyOS SDK.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnThreadSetAffinityByHandle()

Purpose

Defines a thread affinity mask.

Parameters

  • [in] thread – thread handle.
  • [in] mask – pointer to the structure containing the thread affinity mask. The type of structure is defined in the header file sysroot-*-kos/include/rtl/cpuset.h from the KasperskyOS SDK.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnThreadGetSchedPolicyByHandle()

Purpose

Gets information about the thread scheduler class.

Parameters

  • [in] thread – thread handle.
  • [out] policy – pointer to the thread scheduler class. The data type for storing the thread scheduler class is defined in the header file sysroot-*-kos/include/thread/tidtype.h from the KasperskyOS SDK.
  • [out,optional] param – pointer to the parameters of the thread scheduler class, or RTL_NULL.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

In the param parameter, you can specify RTL_NULL if you do not need to get the thread scheduler class parameters.

In the param parameter, you must specify RTL_NULL if the thread scheduler class does not have any parameters.

KnThreadSetSchedPolicyByHandle()

Purpose

Defines the scheduler class and priority of the thread.

Parameters

  • [in] thread – thread handle.
  • [in] policy – thread scheduler class. The parameter type is defined in the header file sysroot-*-kos/include/thread/tidtype.h from the KasperskyOS SDK.
  • [in] prio – thread priority.
  • [in,optional] param – pointer to the parameters of the thread scheduler class, or RTL_NULL.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

In the param parameter, you can specify RTL_NULL if you need to define the thread scheduler class parameters that are applied by default.

In the param parameter, you must specify RTL_NULL if the thread scheduler class does not have any parameters.

Page top
[Topic libkos_thread_low_api]

Managing processes (high-level API task.h)

The API is defined in the header file sysroot-*-kos/include/kos/task.h from the KasperskyOS SDK.

The API lets you create, start and terminate processes, and statically create IPC channels and pass handles.

Information about API functions is provided in the table below.

The libkos library also provides a low-level API for process management. This API is defined in the header file sysroot-*-kos/include/coresrv/task/task_api.h from the KasperskyOS SDK. The low-level API should be used only if the high-level API does not have sufficient capabilities.

Creating processes

To create a process, call one of the following functions:

  • KosTaskInitEx()
  • KosTaskInit()
  • KosTaskInitFromSegEx()
  • KosTaskInitFromSeg()
  • KosTaskLaunch()

Using the params parameter, these functions receive parameters of the created process via a structure containing the following fields:

  • eiid – pointer to the process class name.
  • endpointsCount – number of provided endpoints.

    The field can have a zero value if the process does not provide endpoints.

  • endpoints – pointer to the array of structures containing the characteristics of provided endpoints (names and RIIDs of endpoints, names of interfaces).

    The type of structure is defined in the header file sysroot-*-kos/include/services/handle/if_connection.h from the KasperskyOS SDK.

    The field can have the RTL_NULL value if the process does not provide endpoints.

  • args – pointer to the array of program startup parameters.

    The RTL_NULL value must be the last element of the array.

  • envs – pointer to the array of environment variables of the program.

    The RTL_NULL value must be the last element of the array.

  • flags:
    • KOS_TASK_FLAGS_NONE – no flags.
    • KOS_TASK_FLAG_DUMPABLE – the process switches to the "frozen" state as a result of an unhandled exception.

      For details about the "frozen" state, see Managing processes (low-level API task_api.h).

  • componentTree – pointer to the structure containing information from the formal specification of the solution component.

    The type of structure is defined in the header file sysroot-*-kos/include/nk/types.h from the KasperskyOS SDK. This structure is an element of automatically generated transport code.

    If the field has a value other than RTL_NULL, the values in the eiid, endpointsCount and endpoints fields will be ignored, and the process class name and parameters of the provided endpoints (including the parameters of endpoints of embedded components) will be taken from the formal specification of the solution component.

The KosTaskInitEx(), KosTaskInit(), KosTaskInitFromSegEx() and KosTaskInitFromSeg() functions use the outTask output parameter to pass the pointer to the address of the object describing the child process. This object is a structure that is created in the memory of the parent process and the child process. The developer of a KasperskyOS-based solution does not need to perform operations with the fields of this structure. However, the pointer to this structure must be used as the process ID when calling API functions. A child process can get the address of the object describing it by calling the KosTaskGetSelf() function.

If statically created IPC channels are used for access to endpoints provided by a server process, the object describing this server process must be linked to the structures containing information about endpoints from the formal specification of the solution component. This is necessary so that client processes can receive information about endpoints provided by the server process when creating a static IPC channel. To link an object describing a child server process to structures containing information about endpoints from the formal specification of the solution component, this information must be passed through the componentTree field of the params parameter when calling the KosTaskInit*() functions or KosTaskLaunch() function. A server process that is already running can link the object describing it to structures containing information about endpoints from the formal specification of the solution component by calling the KosTaskSetComponentTree() function. This is required if the running server process does not have a parent process.

When the KosTaskInitEx(), KosTaskInit() or KosTaskLaunch() function is called, the ELF image from the defined executable file in ROMFS is loaded into the memory of the created process. If the ELF image contains the symbol table .symtab and string table .strtab, they are loaded into process memory. Using these tables, the kernel receives the names of functions for generating stack backtrace data (call stack information).

To get information about the ELF image loaded into process memory, call the KosTaskGetElfSegs() function.

When the KosTaskInit() or KosTaskLaunch() function is called, one of the following values is used as the process name and executable file name:

  • Value of the eiid field, if the value of the componentTree field is equal to RTL_NULL.
  • Name of the process class from the formal specification of the solution component, if the componentTree field value is different from RTL_NULL.

Likewise, these values are applied as the process name and/or executable file name if you call the KosTaskInitEx() or KosTaskInitFromSegEx() function with the RTL_NULL value in the name parameter and/or the path parameter. These values are also applied as the process name if you call the KosTaskInitFromSeg() function with the RTL_NULL value in the name parameter.

To use the KosTaskInitFromSegEx() and KosTaskInitFromSeg() functions, MDL buffers containing the ELF image segments must be created in advance. You must use the segs parameter to define the ELF image segments to be loaded into the memory of the created process.

You must use the entry and relocBase parameters of the KosTaskInitFromSegEx() function to define the program entry point and the ELF image load offset, respectively. The program entry point is the sum of the address specified in the e_entry field of the ELF image header and the ELF image load offset. The KnElfCreateVmSegEx() function declared in the header file sysroot-*-kos/include/coresrv/elf/elf_api.h from the KasperskyOS SDK generates a random offset for loading the ELF image and calculates the address of the program entry point according to this offset. (The ELF image load offset must be a random value to ensure ASLR support. For details about ASLR, see Managing processes (low-level API task_api.h).)

You can use the KosTaskInitFromSegEx() function to load the symbol table .symtab, string table .strtab and ELF image header into the memory of the created process. The ELF image header should be loaded if data from this header must be available in the created process.

Data passed to the KosTaskInitFromSegEx() function via the segs, entry, and relocBase parameters and the parameters associated with loading the symbol table .symtab and string table .strtab are prepared by the KnElfCreateVmSegEx() function declared in the header file sysroot-*-kos/include/coresrv/elf/elf_api.h from the KasperskyOS SDK.

The KosTaskInitFromSeg() function is a simplified version of the KosTaskInitFromSegEx() function and does not let you load the symbol table .symtab, string table .strtab and ELF image header into process memory, and does not let you define the ELF image load offset (instead, it sets a null offset).

The KosTaskLaunch() function creates and immediately starts a process without the capability to statically create IPC channels.

Statically created IPC channels

Before starting processes, you can create IPC channels between them. You can create multiple IPC channels with different names between one client process and one server process. You can create IPC channels with the same name between one server process and multiple client processes.

To create an IPC channel with a name matching the name of a server process class, call the KosTaskConnect() function.

To create an IPC channel with a defined name, call the KosTaskConnectToService() function.

To use the created IPC channel, you need to get the client IPC handle on the client process side by calling the ServiceLocatorConnect() function. On the server process side, you need to get the server IPC handle by calling the ServiceLocatorRegister() function. These functions use the channelName parameter to receive the name of the IPC channel. (The ServiceLocatorConnect() and ServiceLocatorRegister() functions are declared in the header file sysroot-*-kos/include/coresrv/sl/sl_api.h from the KasperskyOS SDK.)

Transferring handles

A parent process can transfer one or more handles to a child process that is not yet running. (General information about transferring handles is provided in the Transferring handles section.)

To pass a handle to a child process, call the KosTaskTransferResource() function while specifying the handle of the resource transfer context object, the permissions mask, and the conditional name of the descendant of the transferred handle in addition to the other parameters.

To find the descendant of a handle transferred by a parent process, call the KosTaskLookupResource() function while specifying the conditional name of the descendant of the handle that was defined by the parent process when calling the KosTaskTransferResource() function.

Starting processes

To create and immediately start a process without statically creating IPC channels, call the KosTaskLaunch() function.

To start an already created process for which you can create the necessary IPC channels before starting this process, call the KosTaskRunEx() or KosTaskRun() function.

Use the fsBackend parameter of the KosTaskRunEx() function to specify whether to use the kernel or the system program fsusr to support the ROMFS file system for the started process. Use of the fsusr program ensures that the ROMFS image resides in the user space. The user space can host a significantly larger ROMFS image than the kernel space.

To enable the use of a ROMFS file system residing in the user space, include the fsusr program into the KasperskyOS-based solution and create an IPC channel named kl.core.FSUsr from the process that needs to use this file system to the process named kl.core.FSUsr. (The client portion of the fsusr program is included in the libkos library.) To check whether the fsusr program is included in your KasperskyOS SDK, verify that the sysroot-*-kos/bin/fsusr executable file is available.

To specify how to support the file system in an already running process, call the KosTaskSetSelfFSBackend() function. This function can be used as follows. The parent process indicates that the fsusr program supports its ROMFS file system, and loads the required ROMFS image by calling the KnFsChange() function. (The KnFsChange() function is declared in the header file sysroot-*-kos/include/coresrv/fs/fs_api.h from the KasperskyOS SDK.) Then the parent process starts the child process by calling the KosTaskRunEx() function and specifies that the ROMFS file system for the child process is supported by the fsusr program. As a result, the child process will use the ROMFS image that is placed in the user space by the parent process by default.

If the parent process does not need to terminate the child process or wait for its termination, the object describing the child process must be deleted and the counter for links to it must be reset by using the KosTaskPut() function after the child process is started. The KosTaskLaunch() function calls the KosTaskPut() function after the child process is started.

Terminating processes

The API terminates and waits for termination of child processes.

To terminate a child process, call the KosTaskStop() or KosTaskStopAndWait() function.

To wait for a child process to terminate on its own initiative, call the KosTaskWait() function.

To ensure that the kernel object describing a child process is deleted after this process is terminated, its handle in the parent process must be closed before or after termination of the child process. The handle of the child process is closed when the object describing the child process is deleted from the memory of the parent process. To delete an object describing a child process, reset the counter for links to this object by using the KosTaskPut() function. The KosTaskLaunch() function calls the KosTaskPut() function after the child process is started.

For details about terminating processes, see Managing processes (low-level API task_api.h).

Information about API functions

task.h functions

Function

Information about the function

KosTaskInitEx()

Purpose

Creates a process.

Parameters

  • [in] params – pointer to the structure containing process parameters.
  • [in] name – pointer to the process name.
  • [in] path – pointer to the name of the executable file in ROMFS.
  • [out] outTask – pointer to the address of the object describing the process.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosTaskInit()

Purpose

Creates a process.

Parameters

  • [in] params – pointer to the structure containing process parameters.
  • [out] outTask – pointer to the address of the object describing the process.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosTaskInitFromSegEx()

Purpose

Creates a process.

Parameters

  • [in] params – pointer to the structure containing process parameters.
  • [in] name – pointer to the process name.
  • [in] path – pointer to the name of the executable file in ROMFS.
  • [in] count – number of loaded ELF image segments.
  • [in] relocBase – ELF image load offset (in bytes).
  • [in] entry – address of the program entry point.
  • [in,out] segs – pointer to the array of structures describing ELF image segments. The type of structure is defined in the header file sysroot-*-kos/include/coresrv/vmm/vmm_types.h from the KasperskyOS SDK. If the loadAddr field of this structure is set equal to 0, the load address of the ELF image segment will be selected automatically and written to the loadAddr field.
  • [in] symTabIndex – index of the ELF image segment containing the symbol table .symtab. Enumeration starts with zero.
  • [in] symTabSize – size of the symbol table .symtab (in bytes).
  • [in] strTabIndex – index of the ELF image segment containing the string table .strtab. Enumeration starts with zero.
  • [in] strTabSize – size of the string table .strtab (in bytes).
  • [in] elfHdrData – pointer to the buffer containing the ELF image header.
  • [in] elfHdrSize – size of the ELF image header (in bytes).
  • [out] outTask – pointer to the address of the object describing the process.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosTaskInitFromSeg()

Purpose

Creates a process.

Parameters

  • [in] params – pointer to the structure containing process parameters.
  • [in] name – pointer to the process name.
  • [in] count – number of loaded ELF image segments.
  • [in] entry – address of the program entry point.
  • [in,out] segs – pointer to the array of structures describing ELF image segments. The type of structure is defined in the header file sysroot-*-kos/include/coresrv/vmm/vmm_types.h from the KasperskyOS SDK. If the loadAddr field of this structure is set equal to 0, the load address of the ELF image segment will be selected automatically and written to the loadAddr field.
  • [out] outTask – pointer to the address of the object describing the process.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosTaskGetElfSegs()

Purpose

Gets information about the ELF image loaded in process memory.

Parameters

  • [in] task – pointer to the object that describes the process.
  • [out] segsBuf – pointer to the array used to save structures describing ELF image segments. The type of structure is defined in the header file sysroot-*-kos/include/coresrv/vmm/vmm_types.h from the KasperskyOS SDK.
  • [in] segsBufSize – size (in bytes) of the buffer used to store the array of structures that describe the ELF image segments.
  • [out] segsCount – pointer to the number of loaded ELF image segments.
  • [out] symTabIndex – pointer to the index of the ELF image segment containing the symbol table .symtab. Enumeration starts with zero.
  • [out] symTabSize – pointer to the size of the symbol table .symtab (in bytes).
  • [out] strTabIndex – pointer to the index of the ELF image segment containing the string table .strtab. Enumeration starts with zero.
  • [out] strTabSize – pointer to the size of the string table .strtab (in bytes).
  • [out] hdrBuf – pointer to the buffer used to store the ELF image header.
  • [in] hdrBufSize – size (in bytes) of the buffer used to store the ELF image header.
  • [out] hdrSize – size (in bytes) of the ELF image header.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosTaskConnect()

Purpose

Creates an IPC channel.

Parameters

  • [in] cl – pointer to the object that describes the client process.
  • [in] sr – pointer to the object that describes the server process.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosTaskConnectToService()

Purpose

Creates an IPC channel with the defined name.

Parameters

  • [in] cl – pointer to the object that describes the client process.
  • [in] sr – pointer to the object that describes the server process.
  • [in] name – pointer to the name of the IPC channel.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosTaskSetArgs()

Purpose

Defines the program startup parameters.

Parameters

  • [in] task – pointer to the object that describes the process.
  • [in] args – pointer to the array of program startup parameters. The RTL_NULL value must be the last element of the array.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

The function is used by the libkos library when creating processes.

KosTaskGetArgsList()

Purpose

Gets the program startup parameters.

Parameters

  • [in] task – pointer to the object that describes the process.
  • [out] args – pointer to the address of the array of program startup parameters, or RTL_NULL if these parameters are not available.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

To delete an array of program startup parameters, call the KosTaskFreeArgsList() function.

KosTaskFreeArgsList()

Purpose

Deletes the array of program startup parameters that was received from the KosTaskGetArgsList() call.

Parameters

  • [in] args – pointer to the array of program startup parameters.

Returned values

N/A

KosTaskSetEnv()

Purpose

Defines environment variables of a program.

Parameters

  • [in] task – pointer to the object that describes the process.
  • [in] envs – pointer to the array of environment variables of the program. The RTL_NULL value must be the last element of the array.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

The function is used by the libkos library when creating processes.

KosTaskGetEnvList()

Purpose

Gets the environment variables of a program.

Parameters

  • [in] task – pointer to the object that describes the process.
  • [out] envs – pointer to the address of the array of program environment variables, or RTL_NULL if these variables are not available.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

To delete an array of program environment variables, call the KosTaskFreeEnvList() function.

KosTaskFreeEnvList()

Purpose

Deletes the array of program environment variables that was received from calling the KosTaskGetEnvList() function.

Parameters

  • [in] envs – pointer to the array of environment variables of the program.

Returned values

N/A

KosTaskRunEx()

Purpose

Starts a process.

Parameters

  • [in] task – pointer to the object that describes the process.
  • [in] fsBackend – parameter that specifies whether the ROMFS file system for the started process is supported by the kernel or by a system program.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosTaskRun()

Purpose

Starts a process.

Parameters

  • [in] task – pointer to the object that describes the process.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosTaskStop()

Purpose

Terminates a process.

Parameters

  • [in] task – pointer to the object that describes the process.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosTaskStopAndWait()

Purpose

Terminates a process and waits for the termination of this process.

Parameters

  • [in] task – pointer to the object that describes the process.
  • [in] timeout – timeout in milliseconds, or INFINITE_TIMEOUT to define an unlimited timeout.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosTaskWait()

Purpose

Waits for the termination of a process.

Parameters

  • [in] task – pointer to the object that describes the process.
  • [in] timeout – timeout in milliseconds, or INFINITE_TIMEOUT to define an unlimited timeout.
  • [out] retcode – pointer to the process exit code.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosTaskGetHandle()

Purpose

Gets the process handle.

Parameters

  • [in] task – pointer to the object that describes the process.

Returned values

Process handle.

KosTaskLaunch()

Purpose

Creates and starts a process.

Parameters

  • [in] params – pointer to the structure containing process parameters.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosTaskGetSelf()

Purpose

Gets the address of an object that describes a calling process.

Parameters

N/A

Returned values

Pointer to the object describing the process, or RTL_NULL if this object was deleted.

Additional information

The function adds 1 to the counter for links to the object describing the process, therefore the KosTaskPut() function must be called after this function is called.

KosTaskPut()

Purpose

Subtracts 1 from the counter for links to the object describing the process.

Parameters

  • [in] task – pointer to the object that describes the process.

Returned values

N/A

KosTaskAddEndpoints()

Purpose

Registers endpoints.

Parameters

  • [in,out] task – pointer to the object that describes the process.
  • [in] endpoints – pointer to the array of structures describing endpoints. The type of structure is defined in the header file sysroot-*-kos/include/services/handle/if_connection.h from the KasperskyOS SDK.
  • [in] count – number of endpoints.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

The function is used by the libkos library when creating processes.

KosTaskSetSelfFSBackend()

Purpose

Defines whether the ROMFS file system for a calling process is supported by the kernel or by a system program.

Parameters

  • [in] fsBackend – parameter that defines whether the ROMFS file system is supported by the kernel or by a system program.

Returned values

N/A

KosTaskGetSelfFSBackend()

Purpose

Gets information indicating whether the ROMFS file system for a calling process is supported by the kernel or by a system program.

Parameters

N/A

Returned values

Value indicating whether the ROMFS file system is supported by the kernel or by a system program.

KosTaskSetComponentTree()

Purpose

Creates structures containing information about endpoints from the formal specification of the solution component and links these structures to the object describing the process.

Parameters

  • [in] task – pointer to the object that describes the process.
  • [in] root – pointer to the structure containing information from the formal specification of the solution component. The type of structure is defined in the header file sysroot-*-kos/include/nk/types.h from the KasperskyOS SDK. This structure is an element of automatically generated transport code.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosTaskTransferResource()

Purpose

Transfers a handle to a process that is not yet running.

Parameters

  • [in] task – pointer to the object that describes the process.
  • [in] srcHandle – transferred handle.
  • [in] srcBadge – handle of the resource transfer context object.
  • [in] dstRights – permissions mask of the descendant of the transferred handle.
  • [in] handleName – name of the descendant of the transferred handle.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosTaskLookupResource()

Purpose

Searches for a handle based on the name defined by the KosTaskTransferResource() function.

Parameters

  • [in] handleName – name of the handle.

Returned values

If successful, it returns the handle. Otherwise, it returns INVALID_HANDLE.

Page top
[Topic libkos_task_high_api]

Managing processes (low-level API task_api.h)

The API is defined in the header file sysroot-*-kos/include/coresrv/task/task_api.h from the KasperskyOS SDK.

Main capabilities of the API:

  • Create, start, and terminate processes.
  • Handle exceptions.
  • Get information about processes, including information about the reasons for their termination.
  • Define priorities and scheduler classes for initial threads of processes.

Information about API functions is provided in the table below.

The libkos library also provides a high-level API for process management. This API is defined in the header file sysroot-*-kos/include/kos/task.h from the KasperskyOS SDK. It is recommended to use this specific API. The low-level API should be used only if the high-level API does not have sufficient capabilities.

Creating and starting processes

To create a process, call the KnTaskCreate() or KnTaskCreateEx() function. These functions create an "empty" process, which is a process in whose memory the ELF image of the program is not loaded. Before starting this process, complete the following steps:

  1. Create a seed value by calling the KosRandomGenerate() function, which is declared in the header file sysroot-*-kos/include/kos/random/random_api.h from the KasperskyOS SDK.

    This step is required for completion of the next step.

  2. Define the seed value by calling the KnTaskReseedAslr() function.

    This step is required for address space layout randomization. Address Space Layout Randomization (ASLR) is the use of random addresses for the location of data structures (ELF image, dynamic libraries, stack and heap) in process memory to make it harder to exploit vulnerabilities associated with a conventional process address space structure that is known by a hacker in advance.

    The KnTaskReseedAslr() function defines the seed value of the random number generator that is used to automatically select the base address of an allocated virtual memory region in functions such as KnVmAllocate(), KnPmmMdlMap(), KnIoDmaMap(), and KnTaskVmReserve(). The stack and heap are created in the process and dynamic libraries are loaded into the process memory by the operating system using the KnVmAllocate() function. The addr parameter is set to zero so that the address of the allocated virtual memory region is selected automatically (as a random value).

  3. Wipe the seed value created at step 1 from memory.

    This step is required for security purposes. To complete this step, use the RtlRandomMemSanitize() function, which is declared in the header file sysroot-*-kos/include/rtl/random.h from the KasperskyOS SDK.

  4. Load ELF image segments into process memory by using the KnTaskLoadSeg() function.

    In the loadAddr field of the seg parameter, specify the load address of the ELF image segment. To ensure ASLR support (as a supplement to step 2), the load address of the ELF image segment specified in the ELF file must be increased by the ELF image load offset. The ELF image load offset must be a random value. The KnElfCreateVmSegEx() function declared in the header file sysroot-*-kos/include/coresrv/elf/elf_api.h from the KasperskyOS SDK generates the random offset for loading the ELF image and calculates the load addresses of ELF image segments according to this offset.

    As a result of this step, MDL buffers that contain ELF image segments will be mapped to virtual memory of the process.

  5. [Optional] Load the symbol table .symtab and string table .strtab into process memory by calling the KnTaskLoadElfSyms() function.

    The load addresses of ELF image segments containing the symbol table .symtab and string table .strtab must be calculated just like the load addresses of other ELF image segments. This calculation is performed by the KnElfCreateVmSegEx() function declared in the header file sysroot-*-kos/include/coresrv/elf/elf_api.h from the KasperskyOS SDK.

    The kernel uses the symbol table .symtab and string table .strtab to get the names of functions for generating stack backtrace data (call stack information).

  6. Define the program entry point and the ELF image load offset by calling the KnTaskSetInitialState() function.

    The program entry point is the sum of the address specified in the e_entry field of the ELF image header and the ELF image load offset. The KnElfCreateVmSegEx() function declared in the header file sysroot-*-kos/include/coresrv/elf/elf_api.h from the KasperskyOS SDK generates a random offset for loading the ELF image and calculates the address of the program entry point according to this offset.

  7. [Optional] Load the ELF image header into process memory by calling the KnTaskSetElfHdr() function.

    This step must be completed if data from the ELF image header must be available in the created process.

The handle of a process can be transferred to another process via IPC.

By default, the initial thread of a process is a standard thread whose priority can take values ranging from 0 to 15. (For details about thread scheduler classes, see Managing threads (low-level API thread_api.h).) To change the scheduler class and/or priority of the initial thread of a process, call the KnTaskSetInitialPolicy() function. To change the priority of the initial thread of a process, call the KnTaskSetInitialThreadPriority() function. The KnTaskSetInitialPolicy() and KnTaskSetInitialThreadPriority() functions can be used after the program entry point is defined. These functions can also be used after starting the process.

To start the process, call the KnTaskResume() function. A running process cannot be stopped.

Before a process is started, it receives data from its parent process via a static connection page. A static connection page (SCP) is a set of structures containing data for statically creating IPC channels, startup parameters, and environment variables of a program. A parent process writes data to the SCP of a child process by calling the KnTaskSetEnv() function. When a child process is started, it reads data from the SCP by calling the KnTaskGetEnv() function, then it deletes the SCP by calling the KnTaskFreeEnv() function. All three functions do not need to be explicitly called because their calls are made by the libkos library.

Terminating processes

Process termination includes the following:

  • Terminating all threads of the process.
  • Freeing the memory of the process.
  • Freeing system resources and user resources that are exclusively owned by the process.

    When a process is terminated, all the handles that it owns are closed. If a closed handle was the only handle of a resource, this resource is freed.

A process can be terminated for the following reasons:

  • On its own initiative.

    The KnTaskExit() function is called, or all threads of the process are terminated.

  • By external request.

    The KnTaskTerminate() function is called.

  • As a result of an unhandled exception (crash).

    By calling the KnTaskPanic() function, a process can purposefully initiate an exception that cannot be handled and leads to the process terminating. This assures that the process can terminate itself. (For example, if the process contains threads attached to interrupts, the KnTaskExit() cannot terminate the process, while the KnTaskPanic() function can.)

The exit codes of processes are defined by the developer of the KasperskyOS-based solution. These codes must be specified in the status parameter of the KnTaskExit() function. If a process was terminated due to the termination of all its threads, the exit code of this process will be the exit code of its initial thread. To get the exit code of a process that was terminated on its own initiative, call the KnTaskGetExitCode() function.

To get information regarding the reason for process termination, call the KnTaskGetExitStatus() function. This function determines whether a process was terminated on its own initiative, by external request, or unexpectedly.

To get information about an unhandled exception that led to an unexpected termination of a process, call the KnTaskGetExceptionInfo() function. This information includes the exception code and the context of the thread in which this exception occurred.

If the process was created by calling the KnTaskCreateEx() function with the TaskExceptionFreezesTask flag in the flags parameter, an unhandled exception will cause this process to switch to a "frozen" state instead of terminating. When a process is switched to a "frozen" state, its threads are terminated as a result of the unhandled exception but its resources are not freed, which means that you can get information about this process. To get the context of a thread that is part of a frozen process, call the KnTaskGetThreadContext() function. To get information about the virtual memory region that belongs to a frozen process, call the KnTaskGetNextVmRegion() function. This information includes the base address and size of the virtual memory region, and the access rights to this virtual memory region. Before a process switches to the frozen state, stack backtrace data (call stack information) is printed for the thread in which the unhandled exception occurred. To terminate a frozen process, call the KnTaskTerminateAfterFreezing() function.

To ensure that the kernel object describing a process is deleted after this process is terminated, each of its handles must be closed or revoked in all processes that own these handles before or after termination of this process. To do so, use the KnHandleClose() and/or KnHandleRevoke() functions that are declared in the header file sysroot-*-kos/include/coresrv/handle/handle_api.h from the KasperskyOS SDK.

Handling exceptions

To register an exception handling function, call the KnTaskSetExceptionHandler() function. This function deregisters the previous exception handling function and returns its ID. By saving this ID, you can subsequently register the previous exception handling function again.

An exception handling function is called when an exception occurs in any process thread. If the exception is successfully handled, this function returns a value other than zero. Otherwise it returns zero. The input parameter of the exception handling function is a structure containing information about the exception. The type of this structure is defined in the header file sysroot-*-kos/include/thread/tcbpage.h from the KasperskyOS SDK.

If an exception handling function registered at the process level failed to successfully handle an exception, the exception handling function registered at the level of the thread in which the exception occurred will be called. (For details about handling exceptions at the thread level, see Managing threads (low-level API thread_api.h)).

Reserving memory in a child process

The API includes the KnTaskVmReserve() and KnTaskVmFree() functions, which reserve and free virtual memory regions, respectively, in a child process that does not yet have a defined program entry point. These functions comprise only a part of the functionality intended to increase control of the parent process over the virtual address space of a child process. This functionality is currently under development.

Getting the GSI address

Global system information (GSI) is a structure containing system information, such as the timer count since the kernel started, the timer counts per second, the number of processors (processor cores) in active state, and processor cache data. The type of structure is defined in the header file sysroot-*-kos/include/task/pcbpage.h from the KasperskyOS SDK. The KnTaskGetGsi() function gets the GSI address. This function is intended for use by the libc library.

Getting the PCB address

A process control block (PCB) is a structure containing process information that is used by the kernel to manage this process. The type of structure is defined in the header file sysroot-*-kos/include/task/pcbpage.h from the KasperskyOS SDK. The KnTaskGetPcb() function gets the PCB address. This function is intended for use by the libc library.

Information about API functions

task_api.h functions

Function

Information about the function

KnTaskCreate()

Purpose

Creates a process.

Parameters

  • [in] name – pointer to the process name.
  • [in] eiid – pointer to the process class name.
  • [in] path – parameter that must have the value RTL_NULL.
  • [in,optional] stackSize – thread stack limit (in bytes) used by default when creating process threads. If 0 is specified, the stack will be 1 MB by default.
  • [in] priority – priority of the initial thread. The parameter type is defined in the header file sysroot-*-kos/include/coresrv/thread/thread_api.h from the KasperskyOS SDK.
  • [out] outHandle – pointer to the process handle.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnTaskCreateEx()

Purpose

Creates a process.

Parameters

  • [in] name – pointer to the process name.
  • [in] eiid – pointer to the process class name.
  • [in] path – parameter that must have the value RTL_NULL.
  • [in,optional] stackSize – thread stack limit (in bytes) used by default when creating process threads. If 0 is specified, the stack will be 1 MB by default.
  • [in] priority – priority of the initial thread. The parameter type is defined in the header file sysroot-*-kos/include/coresrv/thread/thread_api.h from the KasperskyOS SDK.
  • [in] flags – flags defining the parameters for creating the process.
  • [out] outHandle – pointer to the process handle.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

In the flags parameter, you can specify the following flags:

  • TaskExceptionTerminatesTask – the process is terminated as a result of an unhandled exception.
  • TaskExceptionFreezesTask – the process switches to the "frozen" state as a result of an unhandled exception. This flag cannot be specified together with the TaskExceptionTerminatesTask flag.
  • TaskEmpty – creates an "empty" process. This mandatory flag must be set.

KnTaskGetGsi()

Purpose

Gets the GSI address for the calling process.

Parameters

N/A

Returned values

Pointer to the GSI. The data type for GSI storage is defined in the header file sysroot-*-kos/include/task/pcbpage.h from the KasperskyOS SDK.

KnTaskGetPcb()

Purpose

Gets the address of the process control block (PCB) for the calling process.

Parameters

N/A

Returned values

Pointer to the PCB. The data type for PCB storage is defined in the header file sysroot-*-kos/include/task/pcbpage.h from the KasperskyOS SDK.

KnTaskGetEnv()

Purpose

Gets the SCP address of the calling process.

Parameters

  • [out] envSize – pointer to the size of the SCP (in bytes).

Returned values

Pointer to the SCP, or RTL_NULL if the process does not have an SCP.

KnTaskSetEnv()

Purpose

Writes data to the SCP of a process.

Parameters

  • [in] task – process handle.
  • [in] env – pointer to the buffer containing data to be written to the SCP.
  • [in] envSize – size (in bytes) of the data to be written to the SCP.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnTaskFreeEnv()

Purpose

Deletes the SCP of the calling process.

Parameters

N/A

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnTaskSetElfHdr()

Purpose

Writes the ELF image header to the PCB of a process.

Parameters

  • [in] h – process handle.
  • [in] hdrData – pointer to the buffer containing the ELF image header.
  • [in] hdrSize – size (in bytes) of the ELF image header.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnTaskResume()

Purpose

Starts a process.

Parameters

  • [in] task – process handle.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnTaskExit()

Purpose

Terminates the calling process.

Parameters

  • [in] status – exit code of the process.

Returned values

Error code.

Additional information

Does not terminate the process as long as it contains threads attached to interrupts.

KnTaskTerminate()

Purpose

Terminates a process.

Parameters

  • [in] task – process handle.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnTaskGetExitStatus()

Purpose

Gets information about the reason for process termination.

Parameters

  • [in] task – handle of the terminated process.
  • [out] status – pointer to the value indicating the reason for process termination. The data type for storing this value is defined in the header file sysroot-*-kos/include/task/pcbpage.h from the KasperskyOS SDK.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

You can use the status parameters to get the following values:

  • TaskExitUnexpected – the process terminated unexpectedly.
  • TaskExitNormal – the process terminated on its own initiative.
  • TaskExitTerminated – the process was terminated by an external request.

KnTaskGetExceptionInfo()

Purpose

Gets information about an unhandled exception that led to an unexpected termination of a process.

Parameters

  • [in] task – handle of the unexpectedly terminated process.
  • [out] excType – pointer to an exception code that is non-specific for any processor architecture. The data type for storing this code is defined in the header file sysroot-*-kos/include/hal/exc_codes.h from the KasperskyOS SDK.
  • [out] excNo – pointer to an exception code that is specific to the utilized processor architecture. The data type for storing this code is defined in the header file sysroot-*-kos/include/hal/exc_codes.h from the KasperskyOS SDK.
  • [out] exceptionContext – pointer to the structure containing the context of the thread in which the exception occurred. The type of structure is defined in the header file sysroot-*-kos/include/hal/*/frame.h from the KasperskyOS SDK.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnTaskGetThreadContext()

Purpose

Gets the context of a thread that is part of a frozen process.

Parameters

  • [in] task – handle of the frozen process.
  • [in] index – thread index. It is used to enumerate threads. Enumeration starts with zero. A thread in which an unhandled exception occurred has a zero index.
  • [out] context – pointer to the structure containing the thread ID (TID) and context of the thread. The type of structure is defined in the header file sysroot-*-kos/include/thread/context.h from the KasperskyOS SDK.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnTaskGetNextVmRegion()

Purpose

Gets information about the virtual memory region that belongs to a frozen process.

Parameters

  • [in] task – handle of the frozen process.
  • [in] after – address that is followed by the virtual memory region.
  • [out] next – pointer to the base address of the virtual memory region.
  • [out] size – pointer to the size of the virtual memory region (in bytes).
  • [out] flags – pointer to the flags indicating the parameters of the virtual memory region. The flags are defined in the header file sysroot-*-kos/include/vmm/flags.h from the KasperskyOS SDK.
  • [out] outHandle – pointer to the handle of the MDL buffer mapped to the virtual memory region. The KnTaskGetNextVmRegion() function creates an MDL buffer from physical memory mapped to a virtual memory region (even if there is already an MDL buffer mapped to this virtual memory region).

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnTaskTerminateAfterFreezing()

Purpose

Terminates a frozen process.

Parameters

  • [in] task – handle of the frozen process.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnTaskGetExitCode()

Purpose

Gets the exit code of a process that terminated on its own initiative.

Parameters

  • [in] task – handle of the terminated process.
  • [out] exitCode – pointer to the process exit code.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnTaskGetId()

Purpose

Gets the process ID (PID) for the calling process.

Parameters

N/A

Returned values

Process ID. The ID type is defined in the header file sysroot-*-kos/include/task/pidtype.h from the KasperskyOS SDK.

KnTaskGetName()

Purpose

Gets the name of a calling process.

Parameters

  • [out] name – pointer to the buffer used to store the process name.
  • [in] msize – size of the buffer used to store the process name (in bytes).

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnTaskGetPath()

Purpose

Gets the name of the executable file (in ROMFS) that was used to create the calling process.

Parameters

  • [out] path – pointer to the buffer used to store the executable file name.
  • [in] msize – size (in bytes) of the buffer used to store the name of the executable file.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnTaskGetInitialThreadPriority()

Purpose

Gets the priority of the initial thread of a process.

Parameters

  • [in] task – process handle.
  • [out] priority – pointer to the priority of the initial thread of the process. The data type for storing the priority of a thread is defined in the header file sysroot-*-kos/include/coresrv/thread/thread_api.h from the KasperskyOS SDK.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnTaskSetInitialThreadPriority()

Purpose

Defines the priority of the initial thread of a process.

Parameters

  • [in] task – process handle.
  • [in] priority – priority of the initial thread of a process. The parameter type is defined in the header file sysroot-*-kos/include/coresrv/thread/thread_api.h from the KasperskyOS SDK.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnTaskSetExceptionHandler()

Purpose

Registers the exception handling function for the calling process.

Parameters

  • [in,optional] handler – ID of the exception handling function, or RTL_NULL to deregister the previously registered function without registering a new one. The parameter type is defined in the header file sysroot-*-kos/include/task/pcbpage.h from the KasperskyOS SDK.

Returned values

ID of the previously registered exception handling function if one exists, otherwise RTL_NULL. The type of returned value is defined in the header file sysroot-*-kos/include/task/pcbpage.h from the KasperskyOS SDK.

KnTaskLoadSeg()

Purpose

Loads an ELF image segment into process memory.

Parameters

  • [in] h – process handle.
  • [in] seg – pointer to the structure describing the ELF image segment. If the loadAddr field of this structure is set equal to 0, the ELF image segment load address will be selected automatically. The type of structure is defined in the header file sysroot-*-kos/include/coresrv/vmm/vmm_types.h from the KasperskyOS SDK.
  • [out] actual – pointer to the load address of the ELF image segment.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnTaskVmReserve()

Purpose

Reserves a virtual memory region in a process.

Parameters

  • [in] task – process handle.
  • [in,optional] hint – page-aligned, preferred base address of the virtual memory region, or RTL_NULL to select this address automatically.
  • [in] size – size of the virtual memory region in bytes.
  • [in] flags – flags defining the parameters of the virtual memory region. The flags are defined in the header file sysroot-*-kos/include/vmm/flags.h from the KasperskyOS SDK.
  • [out] addr – pointer to the base address of the reserved virtual memory region.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

In the flags parameter, you can specify the following flags:

  • VMM_FLAG_LOCKED – commits the virtual memory region while allocating the entire required volume of physical memory. When the KnTaskVmReserve() function is called with this flag, the memory is not committed. This flag affects subsequent commitment-related actions taken on the reserved virtual memory region.
  • VMM_FLAG_READ, VMM_FLAG_WRITE, VMM_FLAG_EXECUTE and VMM_FLAG_RWX_MASK – flags defining the access rights to the virtual memory region.
  • VMM_FLAG_LOW_GUARD, VMM_FLAG_HIGH_GUARD – adds a protected page to the beginning and end of the virtual memory region, respectively. The size of the protected page is not included in the size of the virtual memory region.

Permissible combinations of flags defining the access rights to the virtual memory region:

  • VMM_FLAG_READ – read access.
  • VMM_FLAG_READ | VMM_FLAG_WRITE – read-and-write access.
  • VMM_FLAG_READ | VMM_FLAG_EXECUTE – read-and-execute access.
  • VMM_FLAG_RWX_MASK or VMM_FLAG_READ | VMM_FLAG_WRITE | VMM_FLAG_EXECUTE – read/write/execute access.

KnTaskVmFree()

Purpose

Frees the virtual memory region that was reserved by calling the KnTaskVmReserve() function.

Parameters

  • [in] task – process handle.
  • [in] base – page-aligned base address of the virtual memory region.
  • [in] size – size of the virtual memory region in bytes.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnTaskSetInitialState()

Purpose

Defines the program entry point and the ELF image load offset.

Parameters

  • [in] h – process handle.
  • [in] state – pointer to the structure containing the address of the program entry point and the ELF image load offset (in bytes).

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnTaskLoadElfSyms()

Purpose

Loads the symbol table .symtab and string table .strtab into process memory.

Parameters

  • [in] h – process handle.
  • [in] symTabSeg – pointer to the structure describing the ELF image segment with the symbol table .symtab. The type of structure is defined in the header file sysroot-*-kos/include/coresrv/vmm/vmm_types.h from the KasperskyOS SDK.
  • [in] symTabSize – size of the symbol table .symtab (in bytes).
  • [in] strTabSeg – pointer to the structure describing the ELF image segment with the string table .strtab. The type of structure is defined in the header file sysroot-*-kos/include/coresrv/vmm/vmm_types.h from the KasperskyOS SDK.
  • [in] strTabSize – size of the string table .strtab (in bytes).

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnTaskSetInitialPolicy()

Purpose

Defines the scheduler class and priority of the initial thread of a process.

Parameters

  • [in] task – process handle.
  • [in] policy – scheduler class of the initial thread of the process. The parameter type is defined in the header file sysroot-*-kos/include/thread/tidtype.h from the KasperskyOS SDK.
  • [in] priority – priority of the initial thread of a process. The parameter type is defined in the header file sysroot-*-kos/include/coresrv/thread/thread_api.h from the KasperskyOS SDK.
  • [in,optional] param – pointer to the parameters of the initial thread scheduler class, or RTL_NULL. The data type for storing these parameters is defined in the header file sysroot-*-kos/include/coresrv/thread/thread_api.h from the KasperskyOS SDK.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

In the param parameter, you can specify RTL_NULL if you need to define the default parameters for the scheduler class of the initial thread of the process.

In the param parameter, you must specify RTL_NULL if the scheduler class of the initial thread of the process does not have any parameters.

KnTaskReseedAslr()

Purpose

Defines the seed value for ASLR support in the defined process.

Parameters

  • [in] task – process handle.
  • [in] seed – pointer to the buffer containing the seed value of the random number generator.
  • [in] seedSize – size (in bytes) of the buffer containing the seed value of the random number generator.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnTaskGetElfSyms()

Purpose

Gets the addresses and sizes of the symbol table .symtab and string table .strtab for the calling process.

Parameters

  • [out] relocBase – pointer to the ELF image load offset (in bytes). Add the ELF image load offset to the address of a symbol from the symbol table .symtab to get the address of this symbol in process memory.
  • [out] syms – pointer to the address of the symbol table .symtab.
  • [out] symsCnt – pointer to the size of the symbol table .symtab (in bytes).
  • [out] strs – pointer to the address of the string table .strtab.
  • [out] strsCnt – pointer to the size of the string table .strtab (in bytes).

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

If the symbol table .symtab and string table .strtab are not loaded into process memory by calling the KnTaskLoadElfSyms() function, the KnTaskGetElfSyms() function returns rcOk (if there are no other errors). In this case, the received addresses of the tables have RTL_NULL values, and the received sizes of the tables are zero.

The function is intended for a mechanism that displays stack backtrace data and runs in a process and not in the kernel. This mechanism is currently under development.

KnTaskGetIdByHandle()

Purpose

Gets the process ID (PID).

Parameters

  • [in] task – process handle.
  • [out] taskId – pointer to the process ID. The ID type is defined in the header file sysroot-*-kos/include/task/pidtype.h from the KasperskyOS SDK.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnTaskPanic()

Purpose

Initiates an exception that cannot be handled and leads to the process terminating.

Parameters

N/A

Returned values

N/A

KnTaskTransferResource()

Purpose

Transfers a handle to a process that is not yet running.

Parameters

  • [in] task – process handle.
  • [in] srcHandle – transferred handle.
  • [in] srcBadge – handle of the resource transfer context object.
  • [in] dstRights – permissions mask of the descendant of the transferred handle.
  • [out] outDstHandle – pointer to the descendant of the transferred handle (from the handle space of the process that received the handle).

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

In contrast to the KosTaskTransferResource() function from the API task.h, the KnTaskTransferResource() function does not copy the value of the descendant of the transferred handle to the SCP of the process to which the handle was transferred. The KosTaskTransferResource() function does this so that the process that received the descendant of the transferred handle can find it by calling the KosTaskLookupResource() function from the API task.h.

Page top
[Topic libkos_task_low_api]

Initializing IPC transport for interprocess communication and managing IPC request processing (transport-kos.h, transport-kos-dispatch.h)

APIs are defined in the header files transport-kos.h and transport-kos-dispatch.h from the KasperskyOS SDK that are located at the path sysroot-*-kos/include/coresrv/nk.

API capabilities:

Information about API functions is provided in the tables below.

This section contains API usage examples. In these examples, programs acting as servers have the following formal specification:

FsDriver.edl

task class FsDriver components { operationsComp : Operations }

Operations.cdl

component Operations endpoints { fileOperations : FileIface }

FileIface.idl

package FileIface interface { Open(in array<UInt8, 1024> path); Read(out sequence<UInt8, 2048> content); }

Initializing IPC transport for interprocess communication

To initialize IPC transport for interaction with other processes, call the NkKosTransport_Init() or NkKosTransportSync_Init() function declared in the header file transport-kos.h.

Example use of the NkKosTransport_Init() function on the client side:

int main(int argc, const char *argv[]) { /* Declare the structure containing the IPC transport parameters */ NkKosTransport driver_transport; /* Declare the proxy object. (The type of proxy object is automatically * generated transport code.) */ struct FileIface_proxy file_operations_proxy; /* Declare the structures for saving the constant part of an IPC request and * IPC response for the endpoint method. (The types of structures are automatically * generated transport code.) */ struct FileIface_Open_req req; struct FileIface_Open_res res; /* Get the client IPC handle and RIID */ Handle driver_handle; rtl_uint32_t file_operations_riid; if (KnCmConnect("FsDriver", "operationsComp.fileOperations", INFINITE_TIMEOUT, &driver_handle, &file_operations_riid) == rcOk) { /* Initialize the structure containing the IPC transport parameters */ NkKosTransport_Init(&driver_transport, driver_handle, NK_NULL, 0); /* Initialize the proxy object. (The proxy object initialization method is * is automatically generated transport code.) */ FileIface_proxy_init(&file_operations_proxy, &driver_transport.base, (nk_iid_t) file_operations_riid); } ... /* Call the endpoint method. (The method is automatically * generated transport code.) */ strncpy(req.path, "/example/file/path", sizeof(req.path)); if (FileIface_Open(file_operations_proxy.base, &req, NULL, &res, NULL) != NK_EOK) { ... } ... }

If a client needs to use several endpoints, the same number of proxy objects must be initialized. When initializing each proxy object, you need to specify the IPC transport that is associated through the client IPC handle with the relevant server. When initializing multiple proxy objects pertaining to the endpoints of one server, you can specify the same IPC transport that is associated with this server.

Example use of the NkKosTransport_Init() function on the server side:

int main(int argc, const char *argv[]) { ... /* Declare the structure containing the IPC transport parameters */ NkKosTransport transport; /* Get the listener handle. (RIID * FsDriver_operationsComp_fileOperations_iid is * automatically generated transport code.) */ Handle handle; char client[32]; char endpoint[32]; Retcode rc = KnCmListen(RTL_NULL, INFINITE_TIMEOUT, client, endpoint); if (rc == rcOk) rc = KnCmAccept(client, endpoint, FsDriver_operationsComp_fileOperations_iid, INVALID_HANDLE, &handle); ... /* Initialize the structure containing the IPC transport parameters */ NkKosTransport_Init(&transport, handle, NK_NULL, 0); ... /* IPC request processing loop */ do { ... /* Get the IPC request */ rc = nk_transport_recv(&transport.base, ...); if (rc == NK_EOK) { /* Process the IPC request by calling the dispatcher. (The dispatcher * is automatically generated transport * code.) */ rc = FsDriver_entity_dispatch(...); if (rc == NK_EOK) { /* Send an IPC response */ rc = nk_transport_reply(&transport.base, ...); } } } while (rc == NK_EOK) return EXIT_SUCCESS; }

If a server processes IPC requests received through multiple IPC channels, the following special considerations should be taken into account:

  • If a listener handle is associated with all IPC channels, IPC interaction with all clients can use the same IPC transport associated with this listener handle.
  • If IPC channels are associated with different listener handles, IPC interaction with each group of clients corresponding to the same listener handle must use a separate IPC transport associated with this listener handle. In this case, IPC requests can be processed in parallel threads if you are using a thread-safe implementation of endpoint methods.

The NkKosTransportSync_Init() function initializes IPC transport with support for interrupting the Call() and Recv() locking system calls. (For example, an interrupt of these calls may be required for correct termination of the process that is executing them.) To interrupt the Call() and Recv() system calls, use the API ipc_api.h.

The NkKosSetTransportTimeouts() function declared in the header file transport-kos.h defines the maximum lockout duration for Call() and Recv() system calls used for IPC transport.

Starting the IPC request processing loop

The IPC request processing loop on a server includes the following steps:

  1. Receive an IPC request.
  2. Process the IPC request.
  3. Send an IPC response.

Each step of this loop can be completed separately by sequentially calling the nk_transport_recv(), dispatcher, and nk_transport_reply() functions. (The nk_transport_recv() and nk_transport_reply() functions are declared in the header file sysroot-*-kos/include/nk/transport.h from the KasperskyOS SDK.) You can also call the NkKosTransport_Dispatch(), NkKosDoDispatch() or NkKosDoDispatchEx() function in which this loop is completed in its entirety. (The NkKosTransport_Dispatch() function is declared in the header file transport-kos.h, and the NkKosDoDispatch() and NkKosDoDispatchEx() functions are declared in the header file transport-kos-dispatch.h.) Use of the NkKosDoDispatch() or NkKosDoDispatchEx() function is more convenient than the NkKosTransport_Dispatch() function because they require fewer preparatory operations (for example, you do not need to initialize IPC transport).

You can initialize the structure passed to the NkKosDoDispatch() or NkKosDoDispatchEx() function via the info parameter by using the macros defined in the header file transport-kos-dispatch.h. You can use the syncHandle parameter of the NkKosDoDispatchEx() function to interrupt the system call Recv(). You can use the cb parameter of the NkKosDoDispatchEx() function to define the callback functions that are called after completing the Recv() and Reply() system calls, and after exiting the IPC request processing loop (you do not need to define all functions). The callback function corresponding to the enterDispatchProcessing pointer is called immediately after the Recv() system call is completed. The callback function corresponding to the leaveDispatchProcessing pointer is called immediately after the Reply() system call is completed. The callback function corresponding to the stopDispatchLoop pointer is called immediately after exiting the IPC request processing loop. The callbackContext pointer is passed to each of these callback functions. These callback functions can be used to implement a thread pool, for example.

The NkKosTransport_Dispatch(), NkKosDoDispatch(), and NkKosDoDispatchEx() functions can be called from parallel threads if you are using a thread-safe implementation of endpoint methods.

Example use of the NkKosDoDispatch() function:

/* This function implements the endpoint method. */ static nk_err_t Open_impl(...) { ... } /* This function implements the endpoint method. */ static nk_err_t Read_impl(...) { ... } /* This function initializes the pointers to functions implementing the endpoint methods. * (These pointers are used by the dispatcher to call functions implementing the * endpoint methods.The types of structures are automatically generated * transport code. static struct FileIface *CreateFileOperations() { static const struct FileIface_ops ops = { .Open = Open_impl, .Read = Read_impl }; static struct FileIface impl = { .ops = &ops }; return &impl; } int main(int argc, const char *argv[]) { ... /* Declare the structure that is required for the * NkKosDoDispatch() function to use transport code. */ NkKosDispatchInfo info; /* Declare the stubs. (The types of stubs are automatically generated * transport code. */ struct Operations_component component; struct FsDriver_entity entity; /* Get the listener handle */ Handle handle = ServiceLocatorRegister("driver_connection", NULL, 0, &iid); assert(handle != INVALID_HANDLE); /* Initialize the stubs. (Methods for initializing stubs are * automatically generated transport code.) */Function * CreateFileOperations() is implemented by the developer of the * KasperskyOS-based solution to initialize * pointers to functions implementing the endpoint methods.) */ Operations_component_init(&component, CreateFileOperations()); FsDriver_entity_init(&entity, &component); /* Initialize the structure that is required for the * NkKosDoDispatch() function to use transport code. */ info = NK_TASK_DISPATCH_INFO_INITIALIZER(FsDriver, entity); /* Start the IPC request processing loop */ NkKosDoDispatch(handle, info); return EXIT_SUCCESS; }

Example use of the NkKosTransport_Dispatch() function:

/* This function implements the endpoint method. */ static nk_err_t Open_impl(...) { ... } /* This function implements the endpoint method. */ static nk_err_t Read_impl(...) { ... } /* This function initializes the pointers to functions implementing the endpoint methods. * (These pointers are used by the dispatcher to call functions implementing the * endpoint methods.The types of structures are automatically generated * transport code. static struct FileIface *CreateFileOperations() { static const struct FileIface_ops ops = { .Open = Open_impl, .Read = Read_impl }; static struct FileIface impl = { .ops = &ops }; return &impl; } int main(int argc, const char *argv[]) { ... /* Declare the structure containing the IPC transport parameters */ NkKosTransport transport; /* Declare the stubs. (The types of stubs are automatically generated * transport code. */ struct Operations_component component; struct FsDriver_entity entity; /* Declare the unions of the constant part of IPC requests and * IPC responses. (Types of unions are automatically generated * transport code.) */ union FsDriver_entity_req req; union FsDriver_entity_res res; /* Declare the array for the IPC response arena. (The array size is * automatically generated transport code.) */ char res_buffer[FsDriver_entity_res_arena_size]; /* Declare and initialize the arena descriptor of the IPC response. * (The type of handle and its initialization macro are defined in the header file * sysroot-*-kos/include/nk/arena.h from the KasperskyOS SDK.) */ struct nk_arena res_arena = NK_ARENA_INITIALIZER(res_buffer, res_buffer + sizeof(res_buffer)); /* Get the listener handle */ Handle handle = ServiceLocatorRegister("driver_connection", NULL, 0, &iid); assert(handle != INVALID_HANDLE); /* Initialize the structure containing the IPC transport parameters */ NkKosTransport_Init(&transport, handle, NK_NULL, 0); /* Initialize the stubs. (Methods for initializing stubs are * automatically generated transport code.) */Function * CreateFileOperations() is implemented by the developer of the * KasperskyOS-based solution to initialize * pointers to functions implementing the endpoint methods.) */ Operations_component_init(&component, CreateFileOperations()); FsDriver_entity_init(&entity, &component); /* Start the IPC request processing loop. (The dispatcher FsDriver_entity_dispatch * is automatically generated transport code.) */ NkKosTransport_Dispatch(&transport.base, FsDriver_entity_dispatch, &entity, &req, sizeof(FsDriver_entity_req), RTL_NULL, &res, &res_arena); return EXIT_SUCCESS; }

Copying data to the IPC message arena

To copy a string to the IPC message arena, call the NkKosCopyStringToArena() function declared in the header file transport-kos.h. This function reserves a segment of the arena and copies a string to this segment.

Example use of the NkKosCopyStringToArena() function:

static nk_err_t Read_impl(struct FileIface *self, const struct FileIface_Read_req *req, const struct nk_arena* req_arena, struct FileIface_Read_res* res, struct nk_arena* res_arena) { /* Copy the string to the IPC response arena */ if (NkKosCopyStringToArena(&res_arena, &res.content, "CONTENT OF THE FILE") != rcOk) { ... } return NK_EOK; }

Information about API functions

transport-kos.h functions

Function

Information about the function

NkKosTransport_Init()

Purpose

Initializes IPC transport.

Parameters

  • [out] transport – pointer to the structure containing the IPC transport parameters.
  • [in] handle – client or server IPC handle.
  • [in] view – parameter that must have the value NK_NULL.
  • [in] size – parameter that must have the value 0.

Returned values

N/A

NkKosTransportSync_Init()

Purpose

Initializes IPC transport with support for interrupting the Call() and/or Recv() system calls.

Parameters

  • [out] transport – pointer to the structure containing the IPC transport parameters.
  • [in] handle – client or server IPC handle.
  • [in,optional] callSyncHandle – handle of the IPC synchronization object for Call() system calls, or INVALID_HANDLE if an interrupt of Call() system calls is not required.
  • [in,optional] recvSyncHandle – handle of the IPC synchronization object for Recv() system calls, or INVALID_HANDLE if an interrupt of Recv() system calls is not required.

Returned values

N/A

NkKosSetTransportTimeouts()

Purpose

Defines the maximum lockout duration for Call() and Recv() system calls used for IPC transport.

Parameters

  • [out] transport – pointer to the structure containing the IPC transport parameters.
  • [in] recvTimeout – maximum lockout duration for Recv() system calls in milliseconds, or INFINITE_TIMEOUT to define an unlimited lockout duration.
  • [in] callTimeout – maximum lockout duration for Call() system calls in milliseconds, or INFINITE_TIMEOUT to define an unlimited lockout duration.

Returned values

N/A

NkKosTransport_Dispatch()

Purpose

Starts the IPC request processing loop.

Parameters

  • [in] transport – pointer to the base field of the structure containing the IPC transport parameters.
  • [in] dispatch – pointer to the dispatcher (dispatch method) from the transport code. The dispatcher is named <process class name>_entity_dispatch.
  • [in] impl – pointer to the stub, which consists of a structure with the type <process class name>_entity from the transport code. The dispatcher uses this structure to get the pointers to functions implementing endpoint methods.
  • [out] req – pointer to the union with the type <process class name>_entity_req from the transport code. This union is intended for storing the constant part of IPC requests for any methods of endpoints provided by the server.
  • [in] req_size – maximum size (in bytes) of the constant part of IPC requests. It is defined as sizeof(<process class name>_entity_req), where <process class name>_entity_req is the type from the transport code.
  • [in,out,optional] req_arena – pointer to the IPC request arena descriptor, or RTL_NULL if an IPC request arena is not in use. The type of handle is defined in the header file sysroot-*-kos/include/nk/arena.h from the KasperskyOS SDK.
  • [out] res – pointer to the union with the type <process class name>_entity_res from the transport code. This union is intended for storing the constant part of IPC responses for any methods of endpoints provided by the server.
  • [in,out,optional] res_arena – pointer to the IPC response arena descriptor, or RTL_NULL if an IPC response arena is not in use. The type of handle is defined in the header file sysroot-*-kos/include/nk/arena.h from the KasperskyOS SDK.

Returned values

If unsuccessful, it returns an error code.

NkKosCopyStringToArena()

Purpose

Reserves a segment of the arena and copies a string to this segment.

Parameters

  • [in,out] arena – pointer to the arena descriptor. The type of handle is defined in the header file sysroot-*-kos/include/nk/arena.h from the KasperskyOS SDK.
  • [out] field – pointer to the arena chunk descriptor where the string is copied. The type of handle is defined in the header file sysroot-*-kos/include/nk/types.h.
  • [in] src – pointer to the string to be copied to the IPC message arena.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

transport-kos-dispatch.h functions

Function

Information about the function

NkKosDoDispatch()

Purpose

Starts the IPC request processing loop.

Parameters

  • [in] h – server IPC handle.
  • [in] info – pointer to the structure containing the data required by the function to use transport code (including the names of types, sizes of the constant part and IPC message arena).

Returned values

N/A

NkKosDoDispatchEx()

Purpose

Starts the IPC request processing loop.

Parameters

  • [in] h – server IPC handle.
  • [in] info – pointer to the structure containing the data required by the function to use transport code (including the names of types, sizes of the constant part and IPC message arena).
  • [in,optional] cb – pointer to the structure containing pointers to the callback functions that are called after completing the Recv() and Reply() system calls, and after exiting the IPC request processing loop. In addition to the pointers to callback functions, this structure contains the pointer that is passed to these callback functions when they are called. You can set this parameter to RTL_NULL if you do not need to define callback functions.
  • [in,optional] syncHandle – handle of the IPC synchronization object, or INVALID_HANDLE if an interrupt of the Recv() system call is not required.

Returned values

N/A

Page top
[Topic libkos_ipc_transport_api]

Initializing IPC transport for querying the security module (transport-kos-security.h)

The API is defined in the header file sysroot-*-kos/include/coresrv/nk/transport-kos-security.h from the KasperskyOS SDK.

The API initializes IPC transport for querying the Kaspersky Security Module via the security interface. Transport code works on top of IPC transport.

Information about API functions is provided in the table below.

This section contains an API usage example. In this example, the program that queries the security module has the following formal specification:

Verifier.edl

task class Verifier security Approve

Approve.idl

package Approve interface { Check(in UInt32 port); }

Fragment of the policy description in the example:

security.psl

... security src=Verifier, method=Check { assert (message.port > 80) } ...

Using the API

To initialize IPC transport for querying the security module, call the NkKosSecurityTransport_Init() function.

Example use of the NkKosSecurityTransport_Init() function:

int main(void) { /* Declare the structure containing the IPC transport parameters for querying the * security module */ NkKosSecurityTransport security_transport; /* Declare the proxy object. (The type of proxy object is automatically * generated transport code.) */ struct Approve_proxy security_proxy; /* Declare the structures for saving the constant part of an IPC request and IPC response for the * security interface method. (The types of structures are automatically generated * transport code.) */ struct Approve_Check_req security_req; struct Approve_Check_res security_res; /* Initialize the structure containing the IPC transport parameters for querying the * security module */ if (NkKosSecurityTransport_Init(&security_transport, NK_NULL, 0) == NK_EOK) { /* Initialize the proxy object. (The proxy object initialization method and the * security interface ID Verifier_securityIid are * automatically generated transport code.) */ Approve_proxy_init(&security_proxy, &security_transport.base, Verifier_securityIid); } ... /* Call the security interface method. (The method is automatically generated * transport code.The method does not pass any data through the security_res parameter. * This parameter should be specified only if required by the method implementation.) */ security_req.port = 80; nk_err_t result = Approve_Check(&security_proxy.base, &security_req, NULL, &security_res, NULL); if (result == NK_EOK) fprintf(stderr, "Granted"); if (result == NK_EPERM) fprintf(stderr, "Denied"); else fprintf(stderr, "Error"); return EXIT_SUCCESS; }

If a process needs to use several security interfaces, the same number of proxy objects must be initialized by specifying the same IPC transport and the unique IDs of the security interfaces.

Information about API functions

transport-kos-security.h functions

Function

Information about the function

NkKosSecurityTransport_Init()

Purpose

Initializes IPC transport for querying the Kaspersky Security Module through the security interface.

Parameters

  • [out] transport – pointer to the structure containing the IPC transport parameters for querying the security module.
  • [in] view – parameter that must have the value NK_NULL.
  • [in] size – parameter that must have the value 0.

Returned values

If successful, the function returns NK_EOK, otherwise it returns an error code.

Page top
[Topic libkos_ipc_security_transport_api]

Generating random numbers (random_api.h)

The API is defined in the header file sysroot-*-kos/include/kos/random/random_api.h from the KasperskyOS SDK.

The API generates random numbers and includes functions that can be used to ensure high entropy (high level of unpredictability) of the seed value of the random number generator. The start number of the random number generator (seed) determines the sequence of the generated random numbers. In other words, if the same seed value is set, the generator creates identical sequences of random numbers. (The entropy of these numbers is fully determined by the entropy of the seed value, which means that these numbers are not entirely random, but pseudorandom.)

The random number generator of one process does not depend on the random number generators of other processes.

Information about API functions is provided in the table below.

Using the API

To generate a sequence of random byte values, call the KosRandomGenerate() or KosRandomGenerateEx() function.

Example use of the KosRandomGenerate() function:

size_t random_number; if (KosRandomGenerate(sizeof random_number, &random_number) == rcOk) { ... }

The KosRandomGenerateEx() function gets the quality level of the generated random values through the output parameter quality. The quality level can be high or low. High-quality random values are random values that are generated while fulfilling all of the following conditions:

  1. When the seed value is changed, at least one entropy source is registered and data is successfully received from all registered entropy sources.

    To register the entropy source, call the KosRandomRegisterSrc() function. This function uses the callback parameter to receive the pointer to a callback function of the following type:

    typedef Retcode (*KosRandomSeedMethod)(void *context, rtl_size_t size, void *output);

    Using the context parameters, this callback function receives data with the specified size of bytes from the entropy source and writes this data to the output buffer. If the function returns rcOk, it is assumed that data was successfully received from the entropy source. An entropy source can be a digitalized signal of a sensor or a hardware-based random number generator, for example.

    To deregister an entropy source, call the KosRandomUnregisterSrc() function.

  2. The random number generator is initialized if the quality level was low before changing the seed value while fulfilling condition 1.

    If the quality level is low, it cannot be changed to high without initializing the random number generator.

    To initialize a random number generator, call the KosRandomInitSeed() function. The entropy of data passed through the seed parameter must be guaranteed by the calling process.

  3. The counter of random byte values that were generated after changing the seed value while fulfilling condition 1 does not exceed the system-defined limit.
  4. The counter of time that has elapsed since changing the seed value while fulfilling condition 1 does not exceed the system-defined limit.

If at least one of these conditions is not fulfilled, the generated random values are deemed low-quality values.

When a process is started, the seed value is automatically defined by the system. Then the seed value is modified when doing the following:

  • Generating a sequence of random values.

    Each successful call of the KosRandomGenerateEx() function with the size parameter greater than zero and each successful call of the KosRandomGenerate() function results in a change of the seed value of the random number generator, but not each seed change results in the receipt of data from registered entropy sources. The registered entropy sources are used only when condition 3 or 4 is not fulfilled. If at least one entropy source is registered, the time counter for the change in the seed value is reset. If data from at least one entropy source is successfully received, the counter of generated random byte values is also reset.

    The quality level may change from high to low.

  • Initializing a random number generator.

    Each successful call of the KosRandomInitSeed() function changes the seed value by using the data that is passed through the seed parameter and received from registered entropy sources. If at least one registered entropy source is available, the counters for generated byte values and the time of a change in the seed value are reset. Otherwise, only the counter of generated random byte values is reset.

    The quality level may change from high to low, and vice versa.

  • Registering an entropy source.

    Each successful call of the KosRandomRegisterSrc() function changes the seed value by using the data only from the registered entropy source. The counter of the generated random byte values is also reset.

    The quality level may not change.

A possible scenario for generating high-quality random values includes the following steps:

  1. Register at least one source of entropy by calling the KosRandomRegisterSrc() function.
  2. Generate a sequence of random values by calling the KosRandomGenerateEx() function.
  3. Check the quality level of the random values.

    If the quality level is low, initialize the random number generator by calling the KosRandomInitSeed() function, and proceed to step 2.

    If the quality level is high, proceed to step 4.

  4. Use random values.

To get the quality level without generating random values, call the KosRandomGenerateEx() function with the values 0 and RTL_NULL in the size and output parameters, respectively.

Information about API functions

random_api.h functions

Function

Information about the function

KosRandomInitSeed()

Purpose

Initializes the random number generator.

Parameters

  • [in] seed – pointer to the byte array that is used to change the seed value. The array must have a size of 32 bytes.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosRandomGenerate()

Purpose

Generates a sequence of random byte values.

Parameters

  • [in] size – size (in bytes) of the buffer used to store the sequence.
  • [out] output – pointer to the buffer used to store the sequence.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosRandomGenerateEx()

Purpose

Generates a sequence of random byte values.

Parameters

  • [in] size – size (in bytes) of the buffer used to store the sequence.
  • [out] output – pointer to the buffer used to store the sequence.
  • [out] quality – pointer to the boolean value that is true if the generated random values have high quality, and false if the generated random values have low quality.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosRandomRegisterSrc()

Purpose

Registers an entropy source.

Parameters

  • [in] callback – pointer to the function that receives data from the entropy source to change the seed value.
  • [in,optional] context – pointer to the parameters passed to the function defined through the callback parameter, or RTL_NULL if there are no parameters.
  • [in] size – size (in bytes) of the data that should be received from the entropy source when calling the function defined through the callback parameter. The size must be at least 32 bytes.
  • [out] handle – address of the pointer used to deregister the entropy source.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosRandomUnregisterSrc()

Purpose

Deregisters the source of entropy.

Parameters

  • [in] handle – pointer that is received when registering the source of entropy.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Page top
[Topic libkos_random_api]

Getting and changing time values (time_api.h)

The API is defined in the header file sysroot-*-kos/include/coresrv/time/time_api.h from the KasperskyOS SDK.

Main capabilities of the API:

  • Get and modify the system time
  • Get the monotonic time that has elapsed since the moment the KasperskyOS kernel was started
  • Get the resolution of the sources of system time and monotonic time

Information about API functions is provided in the table below.

time_api.h functions

Function

Information about the function

KnGetSystemTimeRes()

Purpose

Gets the resolution of the system time source.

Parameters

  • [out] res – pointer to the structure containing the resolution of the system time source (in nanoseconds) in the nsec field. The type of structure is defined in the header file sysroot-*-kos/include/rtl/rtc.h from the KasperskyOS SDK.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnSetSystemTime()

Purpose

Sets the system time.

Parameters

  • [in] time – pointer to the structure containing the sec field, which indicates the number of seconds that have elapsed since January 1, 1970, and the nsec field, which indicates the number of nanoseconds that have elapsed since the time defined in the sec field. The type of structure is defined in the header file sysroot-*-kos/include/rtl/rtc.h from the KasperskyOS SDK.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnGetSystemTime()

Purpose

Gets the system time.

Parameters

  • [out] time – pointer to the structure containing the sec field, which indicates the number of seconds that have elapsed since January 1, 1970, and the nsec field, which indicates the number of nanoseconds that have elapsed since the time defined in the sec field. The type of structure is defined in the header file sysroot-*-kos/include/rtl/rtc.h from the KasperskyOS SDK.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnGetUpTimeRes()

Purpose

Gets the resolution of the source of monotonic time that has elapsed since the KasperskyOS kernel was started.

Parameters

  • [out] res – pointer to the structure containing the nsec field, which indicates the resolution of the source of monotonic time (in nanoseconds) that has elapsed since the KasperskyOS kernel was started. The type of structure is defined in the header file sysroot-*-kos/include/rtl/rtc.h from the KasperskyOS SDK.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnGetUpTime()

Purpose

Gets the monotonic time that has elapsed since the moment the KasperskyOS kernel was started.

Parameters

  • [out] time – pointer to the structure containing the sec field, which indicates the number of seconds that have elapsed since the KasperskyOS kernel started, and the nsec field, which indicates the number of nanoseconds that have elapsed since the time defined in the sec field. The type of structure is defined in the header file sysroot-*-kos/include/rtl/rtc.h from the KasperskyOS SDK.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnGetRtcTime()

Purpose

Gets the system time.

Parameters

  • [out] rt – pointer to the structure containing the following time data: year, month, day, hours, minutes, seconds, and milliseconds. The type of structure is defined in the header file sysroot-*-kos/include/rtl/rtc.h from the KasperskyOS SDK.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnGetMSecSinceStart()

Purpose

Gets the monotonic time that has elapsed since the moment the KasperskyOS kernel was started.

Parameters

N/A

Returned values

Monotonic time (in milliseconds) that has elapsed since the KasperskyOS kernel was started.

KnAdjSystemTime()

Purpose

Starts gradual adjustment of the system time.

Parameters

  • [in] adj – pointer to the structure containing the amount of time by which the system time must be adjusted (sec*10^9+nsec nanoseconds), or RTL_NULL if you do not need to start an adjustment but instead only need information about a previously run adjustment (through the prev parameter). The type of structure is defined in the header file sysroot-*-kos/include/rtl/rtc.h from the KasperskyOS SDK.
  • [in] slew – rate of system time adjustment (microseconds per second).
  • [out] prev – pointer to the structure containing the amount of time correction that remained (or remains if RTL_NULL was indicated in the adj parameter) for the already running gradual adjustment to fully complete (sec*10^9+nsec nanoseconds). The type of structure is defined in the header file sysroot-*-kos/include/rtl/rtc.h from the KasperskyOS SDK.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

If a new adjustment is started before a previously running adjustment is finished, the previously running adjustment is interrupted.

Page top
[Topic libkos_time_api]

Using notifications (notice_api.h)

The API is defined in the sysroot-*-kos/include/coresrv/handle/notice_api.h header file from the KasperskyOS SDK.

The API can track events associated with (both system and user) resources, and inform other processes and threads about events involving user resources.

Information about API functions is provided in the table below.

Using the API

The notification mechanism uses an event mask. An event mask is a value whose bits are interpreted as events that should be tracked or that have already occurred. An event mask has a size of 32 bits and consists of a general part and a specialized part. The common part describes events that are not specific to any resources. The specialized part describes events that are specific to certain resources. Specialized part flags for system resources and common part flags are defined in the sysroot-*-kos/include/handle/event_descr.h header file from KasperskyOS SDK. (For example, the common part flag EVENT_OBJECT_DESTROYED signifies resource termination, and the specialized part flag EVENT_TASK_COMPLETED signifies process termination.) Specialized part flags for a user resource are defined by the resource provider with the help of the OBJECT_EVENT_SPEC() and OBJECT_EVENT_USER() macros, which are defined in the sysroot-*-kos/include/handle/event_descr.h header file from the KasperskyOS SDK. The resource provider must export the public header files describing the flags of the specialized part.

The standard scenario for receiving notifications about events associated with resources consists of the following steps:

  1. Creating a notification receiver (KasperskyOS kernel object that collects notifications) by calling the KnNoticeCreate() function.

    The notification receiver ID is the pointer to the KosObject containing the handle of the notification receiver (for details about KosObjects, see Using KosObjects (objects.h)). Destruction of this object will cause the destruction of the notification receiver. If you need to create a copy of the notification receiver ID (for example, for use in another thread), you must increment the counter of links to the KosObject by calling the KosRefObject() function to ensure that this object exists while the created copy of the ID exists. If the copy of the notification receiver ID is no longer needed, you must decrement the counter of links to the KosObject by calling the KosPutObject() function to make sure that this object is destroyed if there are no other links.

  2. Adding "resource—event mask" entries to the notification receiver to configure it to get notifications about events associated with relevant resources.

    To add a "resource—event mask" entry to the notification receiver, you need to call the KnNoticeSubscribeToObject() function. (The OCAP_HANDLE_GET_EVENT flag should be set in the handle permissions mask of the resource stated in the object parameter.) Several "resource—event mask" entries can be added for one resource, and the entry identifiers do not need to be unique. Tracked events for each "resource—event mask" entry should be defined with an event mask that may match one or several events.

    "Resource—event mask" entries added to the notification receiver can be fully or partially removed to prevent the receiver from getting notifications that match these entries. To remove all "resource—event mask" entries from the receiver, you need to call the KnNoticeDropAndWake() function. To remove from the receiver "resource—event mask" entries that refer to the same resource, you need to call the KnNoticeUnsubscribeFromObject() function. To remove from the receiver a "resource—event mask" entry with a specific identifier, you need to call the KnNoticeUnsubscribeFromEvent() function.

    "Resource—event mask" entries can be added to the notification receiver or removed from it throughout the entire lifetime of this notification receiver.

  3. Extracting notifications from the receiver by using the KnNoticeGetEvent() or KnNoticeGetEventEx() function.

    You can set the waiting time for notifications to appear in the receiver when calling the KnNoticeGetEvent() or KnNoticeGetEventEx() function. Threads that are locked while waiting for notifications to appear in the receiver will resume when notifications appear, even if these notifications match "resource—event mask" entries that were added to the receiver during the waiting period.

    Threads that are locked while waiting for notifications to appear in the receiver will resume their execution and will not be locked upon subsequent calls of the KnNoticeGetEvent() or KnNoticeGetEventEx() function if all "resource—event mask" entries are removed from this receiver by calling the KnNoticeDropAndWake() function. If you add at least one "resource—event mask" entry to the notification receiver after calling the KnNoticeDropAndWake() function, threads that get notifications from that receiver will be locked again on KnNoticeGetEvent() or KnNoticeGetEventEx() function calls for the defined waiting time as long as there are no notifications. If all "resource—event mask" entries are removed from the notification receiver by using the KnNoticeUnsubscribeFromObject() and/or KnNoticeUnsubscribeFromEvent() function, threads waiting for notifications to appear in the receiver will not resume until the timeout elapses, and they will be locked during the waiting period upon subsequent calls of the KnNoticeGetEvent() or KnNoticeGetEventEx() function.

  4. Terminate operations with the notification receiver by calling the KnNoticeRelease() function.

    The KnNoticeRelease() function removes all "resource—event mask" entries from the notification receiver and makes it impossible to add new ones. Threads that are locked while waiting for notifications to appear in the receiver will resume their execution and will not be locked upon subsequent calls of the KnNoticeGetEvent() or KnNoticeGetEventEx() function. In addition, the KnNoticeRelease() function decrements the counter of links to the KosObject containing the handle of the notification receiver. If there are no other links to this object, the notification receiver will be destroyed. Otherwise, the notification receiver will exist until all other links are deleted.

To notify other processes and/or threads about events associated with the user resource, you need to call the KnNoticeSetObjectEvent() function. Calling the function results in notifications appearing in receivers configured to get events defined with the evMask parameter and associated with the user resource defined with the object parameter. You cannot set flags of the general part of an event mask in the evMask parameter, because only the kernel can signal about events that match the general part of an event mask. If the process calling the KnNoticeSetObjectEvent() function created the user resource handle stated in the object parameter, you can set flags defined by the OBJECT_EVENT_SPEC() and OBJECT_EVENT_USER() macros in the evMask parameter. If the process calling the KnNoticeSetObjectEvent() function received the user resource handle stated in the object parameter from another process, you can set only those flags defined by the OBJECT_EVENT_USER() macro in the evMask parameter, while the permissions mask of the resulting handle must have a OCAP_HANDLE_SET_EVENT flag set.

Information about API functions

notice_api.h functions

Function

Information about the function

KnNoticeCreate()

Purpose

Creates a notification receiver.

Parameters

  • [out] notice – pointer to the identifier of the notification receiver.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnNoticeSubscribeToObject()

Purpose

Adds a "resource–event mask" entry to the notification receiver so that it can receive notifications about events associated with the defined resource and match the defined event mask.

Parameters

  • [in] notice – identifier of the notification receiver.
  • [in] object – resource handle.
  • [in] evMask – event mask.
  • [in] evId – ID of the "resource–event mask" entry.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnNoticeGetEvent()

Purpose

Extracts notifications from the receiver.

Parameters

  • [in] notice – identifier of the notification receiver.
  • [in] msec – time-out before notifications appearing in the receiver, in milliseconds, or INFINITE_TIMEOUT to set an unlimited time-out.
  • [in] countMax – maximum number of notifications extracted with one function call.
  • [out] events – pointer to a set of notifications that represent structures containing the identifier of a "resource—event mask" entry and the mask of the events associated with the resource.
  • [out] count – number of notifications extracted.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

If the time-out for notifications to appear in the receiver has elapsed, returns rcTimeout.

If all "resource—event mask" entries are removed from the notification receiver by calling the KnNoticeRelease() or KnNoticeDropAndWake() function, the function returns rcResourceNotFound.

KnNoticeGetEventEx()

Purpose

Extracts notifications from the receiver.

Parameters

  • [in] notice – identifier of the notification receiver.
  • [in] msec – time-out before notifications appearing in the receiver, in milliseconds, or INFINITE_TIMEOUT to set an unlimited time-out.
  • [in] countMax – maximum number of notifications extracted with one function call.
  • [out] events – pointer to a set of notifications that represent structures containing the identifier of a "resource—event mask" entry and the counter of events associated with the resource.
  • [out] count – number of notifications extracted.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

If the time-out for notifications to appear in the receiver has elapsed, returns rcTimeout.

If all "resource—event mask" entries are removed from the notification receiver by calling the KnNoticeRelease() or KnNoticeDropAndWake() function, the function returns rcResourceNotFound.

KnNoticeUnsubscribeFromObject()

Purpose

Removes from the notification receiver "resource—event mask" entries that match the specified resource to prevent the receiver from getting notifications about events that match these entries.

Parameters

  • [in] notice – identifier of the notification receiver.
  • [in] object – resource handle.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

Notifications that correspond to the removed "resource—event mask" entries will be removed from the receiver.

KnNoticeUnsubscribeFromEvent()

Purpose

Removes from the notification receiver "resource—event mask" entries with the specified identifier to prevent the receiver from getting notifications about events that match these entries.

Parameters

  • [in] notice – identifier of the notification receiver.
  • [in] evId – ID of the "resource–event mask" entry.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

Notifications that correspond to the removed "resource—event mask" entries will be removed from the receiver.

KnNoticeDropAndWake()

Purpose

Removes all "resource—event mask" entries from the specified notification receiver and resumes all threads that are waiting for notifications to appear in the specified receiver.

Parameters

  • [in] notice – identifier of the notification receiver.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnNoticeRelease()

Purpose

Removes all "resource—event mask" entries from the specified notification receiver and makes it impossible to add new ones, resumes all threads waiting for notifications to appear in the specified receiver, and decrements the counter of links to the KosObject containing the handle of the specified notification receiver.

Parameters

  • [in] notice – identifier of the notification receiver.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnNoticeSetObjectEvent()

Purpose

Signals the occurrence of events that are related to the defined user resource and match the defined event mask.

Parameters

  • [in] object – user resource handle.
  • [in] evMask – mask of events to be signaled.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Page top
[Topic libkos_notice_api]

Dynamically creating IPC channels (cm_api.h, ns_api.h)

APIs are defined in the following header files from the KasperskyOS SDK:

  • sysroot-*-kos/include/coresrv/cm/cm_api.h
  • sysroot-*-kos/include/coresrv/ns/ns_api.h

The APIs dynamically create IPC channels.

Information about API functions is provided in the tables below.

Using the API

To ensure that servers can notify clients about the endpoints that they provide, the solution should include a name server, which is provided by the NameServer system program (executable file sysroot-*-kos/bin/ns from the KasperskyOS SDK). IPC channels from clients and servers to a name server can be statically created (these IPC channels must be named kl.core.NameServer). If this is not done, attempts will be made to dynamically create these IPC channels whenever clients and servers call the NsCreate() function. A name server does not have to be included in a solution if the clients initially already have information about the names of servers and the endpoints provided by these servers.

The names of endpoints and interfaces should be defined according to the formal specifications of solution components. (For information about the qualified name of an endpoint, see Binding methods of security models to security events.) Instead of the qualified name of an endpoint, you can use any conditional name of this endpoint. The names of clients and servers are defined in the init description. You can also get a process name by calling the KnTaskGetName() function from the API task_api.h.

Dynamic creation of an IPC channel on the server side includes the following steps:

  1. Connect to the name server by calling the NsCreate() function.
  2. Publish the provided endpoints on the name server by using the NsPublishService() function.

    To unpublish an endpoint, call the NsUnPublishService() function.

  3. Receive a client request to create an IPC channel by calling the KnCmListen() function.

    The KnCmListen() function gets the first request in the queue without deleting this request but instead putting it at the end of the queue. If there is only one request in the queue, multiple consecutive calls of the KnCmListen() function will provide the same result. A request is deleted from the queue when the KnCmAccept() or KnCmDrop() function is called.

  4. You can accept a client request to create an IPC channel by calling the KnCmAccept() function.

    To decline a client request, call the KnCmDrop() function.

    A listener handle is created when the KnCmAccept() function is called with the INVALID_HANDLE value in the listener parameter. If a listener handle is specified, the created server IPC handle will provide the capability to receive IPC requests over all IPC channels associated with this listener handle. (The first IPC channel associated with the listener handle is created when the KnCmAccept() function is called with the INVALID_HANDLE value in the listener parameter. The second and subsequent IPC channels associated with the listener handle are created during the second and subsequent calls of the KnCmAccept() function specifying the handle that was obtained during the first call.) In the listener parameter of the KnCmAccept() function, you can specify the listener handle received using the KnHandleConnect(), KnHandleConnectEx() and KnHandleCreateListener() functions from the API handle_api.h, and the ServiceLocatorRegister() function declared in the header file sysroot-*-kos/include/coresrv/sl/sl_api.h from the KasperskyOS SDK. In the rsid parameter of the KnCmAccept() function, you must specify the endpoint ID (RIID), which is a constant in the automatically generated transport code (for example: FsDriver_operationsComp_fileOperations_iid).

Dynamic creation of an IPC channel on the client side includes the following steps:

  1. Connect to the name server by calling the NsCreate() function.
  2. Find the server providing the required endpoint by using the NsEnumServices() function.

    To get a full list of endpoints with a defined interface, call the function several times while incrementing the index until you receive the rcResourceNotFound error.

  3. Fulfill the request to create an IPC channel with the necessary server by calling the KnCmConnect() function.

You can connect multiple clients and servers to the name server. Each client and server can create multiple connections to the name server. A server can unpublish an endpoint that was published by another server.

To delete a connection to the name server, call the NsDestroy() function.

Deleting dynamically created IPC channels

A dynamically created IPC channel will be deleted when its client IPC handle and server IPC handle are closed.

Information about API functions

ns_api.h functions

Function

Information about the function

NsCreate()

Purpose

Creates a connection to a name server.

Parameters

  • [in,optional] name – pointer to the name of the name server process, or RTL_NULL to assign the default name (corresponds to the NS_SERVER_NAME macro value).
  • [in] msecs – timeout (in milliseconds) for creating a connection to the name server, or INFINITE_TIMEOUT to define an unlimited timeout.
  • [out] ns – pointer to the ID of the connection to the name server.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

NsDestroy()

Purpose

Deletes a connection to the name server.

Parameters

  • [in] ns – ID of the connection to the name server.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

NsPublishService()

Purpose

Publishes an endpoint on a name server.

Parameters

  • [in] ns – ID of the connection to the name server.
  • [in] type – pointer to the name of the endpoint interface.
  • [in,optional] server – pointer to the name of the server providing the endpoint, or RTL_NULL to use the name of the calling process.
  • [in] service – pointer to the qualified name of the endpoint.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

NsUnPublishService()

Purpose

Unpublishes an endpoint on a name server.

Parameters

  • [in] ns – ID of the connection to the name server.
  • [in] type – pointer to the name of the endpoint interface.
  • [in,optional] server – pointer to the name of the server providing the endpoint, or RTL_NULL to use the name of the calling process.
  • [in] service – pointer to the qualified name of the endpoint.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

NsEnumServices()

Purpose

Enumerates the endpoints published on a name server.

Parameters

  • [in] ns – ID of the connection to the name server.
  • [in] type – pointer to the name of the interface of endpoints.
  • [in] index – index for enumerating endpoints. Enumeration starts with zero.
  • [out] server – pointer to the buffer for the name of the server providing the endpoint.
  • [in] serverSize – buffer size (in bytes) for the name of the server providing the endpoint.
  • [out] service – pointer to the buffer for the qualified name of the endpoint.
  • [in] serviceSize – buffer size (in bytes) for the qualified name of the endpoint.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

cm_api.h functions

Function

Information about the function

KnCmConnect()

Purpose

Requests to create an IPC channel with a server for use of the defined endpoint.

Parameters

  • [in] server – pointer to the server name.
  • [in] service – pointer to the qualified name of the endpoint.
  • [in] msecs – timeout (in milliseconds) for fulfilling a request, or INFINITE_TIMEOUT to define an unlimited timeout.
  • [out] handle – pointer to the client IPC handle.
  • [out] rsid – pointer to the Runtime Implementation Identifier (RIID).

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnCmListen()

Purpose

Receives a client request to create an IPC channel for use of an endpoint.

Parameters

  • [in] filter – fictitious parameter that must have the value RTL_NULL.
  • [in] msecs – timeout (in milliseconds) for the appearance of a client request, or INFINITE_TIMEOUT to define an unlimited timeout.
  • [out] client – pointer to the client name.
  • [out] service – pointer to the qualified name of the endpoint.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnCmDrop()

Purpose

Rejects a client request to create an IPC channel for use of the defined endpoint.

Parameters

  • [in] client – pointer to the client name.
  • [in] service – pointer to the qualified name of the endpoint.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnCmAccept()

Purpose

Accepts a client request to create an IPC channel for use of the defined endpoint.

Parameters

  • [in] client – pointer to the client name.
  • [in] service – pointer to the qualified name of the endpoint.
  • [in] rsid – Runtime Implementation Identifier (RIID).
  • [in,optional] listener – listener handle, or INVALID_HANDLE if you need to create it.
  • [out] handle – pointer to the server IPC handle.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Page top
[Topic libkos_cm_ns_api]

Using synchronization primitives (event.h, mutex.h, rwlock.h, semaphore.h, condvar.h)

The libkos library provides APIs that enable use of the following synchronization primitives:

  • Events (event.h)
  • Mutexes (mutex.h)
  • Read-write locks (rwlock.h)
  • Semaphores (semaphore.h)
  • Conditional variables (condvar.h)

The header files are located in the KasperskyOS SDK at sysroot-*-kos/include/kos.

The APIs are intended for synchronizing threads that belong to the same process.

Events

An event is a synchronization primitive that is used to notify one or more threads about the fulfillment of a condition required by these threads. The notified thread waits for the event to switch from a non-signaling state to a signaling state, and the notifying thread changes the state of this event.

The standard API usage scenario for working with events includes the following steps:

  1. An event is initialized via the KosEventInit() function call.
  2. The event is used by threads:
    • The notified threads wait for the event to switch from non-signaling state to signaling state via the KosEventWait() or KosEventWaitTimeout() function call.
    • The notifying threads change the state of the event via the KosEventSet() and KosEventReset() function calls.

Information about the API event functions is provided in the table below.

event.h functions

Function

Information about the function

KosEventInit()

Purpose

Initializes an event.

The event is in a non-signaling state after it is initialized.

Parameters

  • [out] event – pointer to the event. The event type is defined in the sysroot-*-kos/include/kos/sync_types.h header file from the KasperskyOS SDK.

Returned values

N/A

KosEventSet()

Purpose

Sets the event state to signaling.

Parameters

  • [out] event – pointer to the event. The event type is defined in the sysroot-*-kos/include/kos/sync_types.h header file from the KasperskyOS SDK.

Returned values

N/A

KosEventReset()

Purpose

Sets the event state to non-signaling.

Parameters

  • [out] event – pointer to the event. The event type is defined in the sysroot-*-kos/include/kos/sync_types.h header file from the KasperskyOS SDK.

Returned values

N/A

KosEventWait()

Purpose

Waits for the event to change its state from non-signaling to signaling.

Parameters

  • [in,out] event – pointer to the event. The event type is defined in the sysroot-*-kos/include/kos/sync_types.h header file from the KasperskyOS SDK.
  • [in] reset – value that defines whether the event state should be changed set to non-signaling after the time-out has elapsed (rtl_true – yes, rtl_false – no). The parameter type is defined in the sysroot-*-kos/include/rtl/stdbool.h header file from the KasperskyOS SDK.

Returned values

N/A

KosEventWaitTimeout()

Purpose

Waits on the event to change its state from non-signaling to signaling for a period that does not exceed the specified time.

Parameters

  • [in,out] event – pointer to the event. The event type is defined in the sysroot-*-kos/include/kos/sync_types.h header file from the KasperskyOS SDK.
  • [in] reset – value that defines whether the event state should be changed set to non-signaling after the time-out has elapsed (rtl_true – yes, rtl_false – no). The parameter type is defined in the sysroot-*-kos/include/rtl/stdbool.h header file from the KasperskyOS SDK.
  • [in] mdelay – time-out (in milliseconds) or INFINITE_TIMEOUT to set an unlimited time-out.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Returns rcTimeout if the time-out has elapsed.

Mutexes

A mutex is a synchronization primitive that ensures mutually exclusive execution of critical sections (areas of code where resources shared between threads are queried). One thread captures the mutex and executes a critical section. Meanwhile, other threads wait for the mutex to be freed and attempt to capture this mutex to execute other critical sections. A mutex can be freed only by the specific thread that captured it. You can use a recursive mutex, which can be captured by the same thread multiple times.

The standard API usage scenario for working with mutexes includes the following steps:

  1. A mutex is initialized via the KosMutexInit() or KosMutexInitEx() function call.
  2. The mutex is used by threads:
    1. The mutex is captured via the KosMutexTryLock(), KosMutexLock() or KosMutexLockTimeout() function call.
    2. The mutex is freed via the KosMutexUnlock() function call.

Information about the API mutex functions is provided in the table below.

mutex.h functions

Function

Information about the function

KosMutexInit()

Purpose

Initializes a non-recursive mutex.

Parameters

  • [out] mutex – pointer to the mutex. The mutex type is defined in the sysroot-*-kos/include/kos/sync_types.h header file from the KasperskyOS SDK.

Returned values

N/A

KosMutexInitEx()

Purpose

Initializes a mutex.

Parameters

  • [out] mutex – pointer to the mutex. The mutex type is defined in the sysroot-*-kos/include/kos/sync_types.h header file from the KasperskyOS SDK.
  • [in] recursive – value that defines whether the mutex should be recursive (1 – yes, 0 – no).

Returned values

N/A

KosMutexTryLock()

Purpose

Acquires the mutex.

If the mutex is already acquired, returns control rather than waits for the mutex to be released.

Parameters

  • [in,out] mutex – pointer to the mutex. The mutex type is defined in the sysroot-*-kos/include/kos/sync_types.h header file from the KasperskyOS SDK.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

If the mutex is already acquired, returns rcBusy.

KosMutexLock()

Purpose

Acquires the mutex.

If the mutex is already acquired, waits indefinitely for it to be released.

Parameters

  • [in,out] mutex – pointer to the mutex. The mutex type is defined in the sysroot-*-kos/include/kos/sync_types.h header file from the KasperskyOS SDK.

Returned values

N/A

KosMutexUnlock()

Purpose

Releases the mutex.

Parameters

  • [in,out] mutex – pointer to the mutex. The mutex type is defined in the sysroot-*-kos/include/kos/sync_types.h header file from the KasperskyOS SDK.

Returned values

N/A

KosMutexLockTimeout()

Purpose

Acquires the mutex.

If the mutex is already acquired, waits for it to be released for a period that does not exceed the specified time.

Parameters

  • [in,out] mutex – pointer to the mutex. The mutex type is defined in the sysroot-*-kos/include/kos/sync_types.h header file from the KasperskyOS SDK.
  • [in] mdelay – time-out (in milliseconds) or INFINITE_TIMEOUT to set an unlimited time-out.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Returns rcTimeout if the time-out has elapsed.

Read-write locks

A read-write lock is a synchronization primitive used to allow access to resources shared between threads: write access for one thread or read access for multiple threads at the same time.

The standard API usage scenario for working with read-write locks includes the following steps:

  1. A read-write lock is initialized by the KosRWLockInit() function call.
  2. The read-write lock is used by threads:
    1. The read-write lock is captured for write operations (via the KosRWLockWrite() or KosRWLockTryWrite() function call) or for read operations (via the KosRWLockRead() or KosRWLockTryRead() function call).
    2. The read-write lock is freed via the KosRWLockUnlock() function call.

Information about the API read-write lock functions is provided in the table below.

rwlock.h functions

Function

Information about the function

KosRWLockInit()

Purpose

Initializes a read-write lock.

Parameters

  • [out] rwlock – pointer to a read-write lock. The read-write lock type is defined in the sysroot-*-kos/include/kos/sync_types.h header file from the KasperskyOS SDK.

Returned values

N/A

KosRWLockRead()

Purpose

Acquires the read-write lock for reading.

If the read-write lock is already acquired for writing, or if there are threads waiting on the lock to be acquired for writing, waits indefinitely for the lock to be released.

Parameters

  • [in,out] rwlock – pointer to the read-write lock. The read-write lock type is defined in the sysroot-*-kos/include/kos/sync_types.h header file from the KasperskyOS SDK.

Returned values

N/A

KosRWLockTryRead()

Purpose

Acquires the read-write lock for reading.

If the read-write lock is already acquired for writing, or if there are threads waiting on the lock to be acquired for writing, returns control, rather than waits for the lock to be released.

Parameters

  • [in,out] rwlock – pointer to the read-write lock. The read-write lock type is defined in the sysroot-*-kos/include/kos/sync_types.h header file from the KasperskyOS SDK.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosRWLockWrite()

Purpose

Acquires the read-write lock for writing.

If the read-write lock is already acquired for writing or reading, waits indefinitely for the lock to be released.

Parameters

  • [in,out] rwlock – pointer to the read-write lock. The read-write lock type is defined in the sysroot-*-kos/include/kos/sync_types.h header file from the KasperskyOS SDK.

Returned values

N/A

KosRWLockTryWrite()

Purpose

Acquires the read-write lock for writing.

If the read-write lock is already acquired for writing or reading, returns control, rather than waits for the lock to be released.

Parameters

  • [in,out] rwlock – pointer to the read-write lock. The read-write lock type is defined in the sysroot-*-kos/include/kos/sync_types.h header file from the KasperskyOS SDK.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosRWLockUnlock()

Purpose

Releases the read-write lock.

Parameters

  • [in,out] rwlock – pointer to the read-write lock. The read-write lock type is defined in the sysroot-*-kos/include/kos/sync_types.h header file from the KasperskyOS SDK.

Returned values

N/A

Additional information

If the read-write lock is acquired for reading, it remains acquired for reading until released by every reading thread.

Semaphores

A semaphore is a synchronization primitive that is based on a counter whose value can be atomically modified. The value of the counter normally reflects the number of available resources shared between threads. To execute a critical section, the thread waits until the counter value becomes greater than zero. If the counter value is greater than zero, it is decremented by one and the thread executes the critical section. After the critical section is executed, the thread signals the semaphore and the counter value is increased.

The standard API usage scenario for working with semaphores includes the following steps:

  1. A semaphore is initialized via the KosSemaphoreInit() function call.
  2. The semaphore is used by threads:
    1. They wait for the semaphore via the KosSemaphoreWait(), KosSemaphoreWaitTimeout() or KosSemaphoreTryWait() function call.
    2. The semaphore is signaled via the KosSemaphoreSignal() or KosSemaphoreSignalN() function call.
  3. Deallocating semaphore resources by calling the KosSemaphoreDeinit() function.

Information about the API semaphore functions is provided in the table below.

semaphore.h functions

Function

Information about the function

KosSemaphoreInit()

Purpose

Initializes a semaphore.

Parameters

  • [out] semaphore – pointer to the semaphore. The semaphore type is defined in the sysroot-*-kos/include/kos/sync_types.h header file from the KasperskyOS SDK.
  • [in] count – counter value.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

If the value of the count parameter exceeds the KOS_SEMAPHORE_VALUE_MAX constant, returns rcInvalidArgument. (The KOS_SEMAPHORE_VALUE_MAX constant is defined in the sysroot-*-kos/include/kos/sync_types.h header file from the KasperskyOS SDK.)

KosSemaphoreDeinit()

Purpose

Deallocates semaphore resources.

Parameters

  • [in] semaphore – pointer to the semaphore. The semaphore type is defined in the sysroot-*-kos/include/kos/sync_types.h header file from the KasperskyOS SDK.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

If there are threads waiting on the semaphore, returns rcBusy.

KosSemaphoreSignal()

Purpose

Signals the semaphore and increases the counter by one.

Parameters

  • [in, out] semaphore – pointer to the semaphore. The semaphore type is defined in the sysroot-*-kos/include/kos/sync_types.h header file from the KasperskyOS SDK.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosSemaphoreSignalN()

Purpose

Signals the semaphore and increases the counter by the specified number.

Parameters

  • [in, out] semaphore – pointer to the semaphore. The semaphore type is defined in the sysroot-*-kos/include/kos/sync_types.h header file from the KasperskyOS SDK.
  • [in] n – natural number by which to increase the counter.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosSemaphoreWaitTimeout()

Purpose

Waits on the semaphore for a period that does not exceed the specified time.

Parameters

  • [in, out] semaphore – pointer to the semaphore. The semaphore type is defined in the sysroot-*-kos/include/kos/sync_types.h header file from the KasperskyOS SDK.
  • [in] mdelay – semaphore time-out in milliseconds or INFINITE_TIMEOUT to set an unlimited time-out.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Returns rcTimeout if the time-out has elapsed.

KosSemaphoreWait()

Purpose

Waits on the semaphore indefinitely.

Parameters

  • [in, out] semaphore – pointer to the semaphore. The semaphore type is defined in the sysroot-*-kos/include/kos/sync_types.h header file from the KasperskyOS SDK.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosSemaphoreTryWait()

Purpose

Waits on the semaphore.

If the semaphore counter has a zero value, returns control, rather than waits for the semaphore counter to increase.

Parameters

  • [in, out] semaphore – pointer to the semaphore. The semaphore type is defined in the sysroot-*-kos/include/kos/sync_types.h header file from the KasperskyOS SDK.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

If the semaphore counter has a zero value, returns rcBusy.

Conditional variables

A conditional variable is a synchronization primitive that is used to notify one or more threads about the fulfillment of a condition required by these threads. A conditional variable is used together with a mutex. The notifying and notified threads capture a mutex to execute critical sections. During execution of a critical section, the notified thread verifies that its required condition was fulfilled (for example, the data has been prepared by the notifying thread). If the condition is fulfilled, the notified thread executes the critical section and frees the mutex. If the condition is not fulfilled, the notified thread is locked at the conditional variable and waits for the condition to be fulfilled. When this happens, the mutex is automatically freed. During execution of a critical section, the notifying thread verifies fulfillment of the condition required by the notified thread. If the condition is fulfilled, the notifying thread signals this fulfillment through the conditional variable and frees the mutex. The notified thread that was locked and waiting for the fulfillment of its required condition resumes execution of the critical section while automatically capturing the mutex. After the critical section is executed, the notified thread frees the mutex.

The standard API usage scenario for working with conditional variables includes the following steps:

  1. The conditional variable and mutex are initialized.

    To initialize a conditional variable, you need to call the KosCondvarInit() function.

  2. The conditional variable and mutex are used by threads.

Use of a conditional variable and mutex by notified threads includes the following steps:

  1. The mutex is captured.
  2. Condition fulfillment is verified.
  3. The KosCondvarWait() or KosCondvarWaitTimeout() function is called to wait for condition fulfillment.

    After the KosCondvarWait() or KosCondvarWaitTimeout() function is returned, you normally need to re-verify that the condition is fulfilled because another notified thread also received the signal and may have voided this condition again. (For example, another thread could have extracted the data prepared by the notifying thread). To do so, you need to use the following construct:

    while(<condition>) <call of KosCondvarWait() or KosCondvarWaitTimeout()>
  4. The mutex is freed.

Use of a conditional variable and mutex by notifying threads includes the following steps:

  1. The mutex is captured.
  2. Condition fulfillment is verified.
  3. Fulfillment of the condition is signaled via the KosCondvarSignal() or KosCondvarBroadcast() function call.
  4. The mutex is freed.

Information about the API conditional variable functions is provided in the table below.

condvar.h functions

Function

Information about the function

KosCondvarInit()

Purpose

Initializes a conditional variable.

Parameters

  • [out] condvar – pointer to the conditional variable. The conditional variable type is defined in the sysroot-*-kos/include/kos/sync_types.h header file from the KasperskyOS SDK.

Returned values

N/A

KosCondvarWaitTimeout()

Purpose

Waits for condition fulfillment for a period that does not exceed the specified time.

Parameters

  • [in] condvar – pointer to the conditional variable. The conditional variable type is defined in the sysroot-*-kos/include/kos/sync_types.h header file from the KasperskyOS SDK.
  • [in,out] mutex – pointer to the mutex. The mutex type is defined in the sysroot-*-kos/include/kos/sync_types.h header file from the KasperskyOS SDK.
  • [in] mdelay – condition fulfillment time-out in milliseconds, or INFINITE_TIMEOUT to set an unlimited time-out.

Returned values

Returns rcOk if successful.

Returns rcTimeout if the time-out has elapsed.

KosCondvarWait()

Purpose

Waits indefinitely for condition fulfillment.

Parameters

  • [in] condvar – pointer to the conditional variable. The conditional variable type is defined in the sysroot-*-kos/include/kos/sync_types.h header file from the KasperskyOS SDK.
  • [in,out] mutex – pointer to the mutex. The mutex type is defined in the sysroot-*-kos/include/kos/sync_types.h header file from the KasperskyOS SDK.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosCondvarSignal()

Purpose

Signals condition fulfillment to one of the threads waiting for it.

Parameters

  • [in, out] condvar – pointer to the conditional variable. The conditional variable type is defined in the sysroot-*-kos/include/kos/sync_types.h header file from the KasperskyOS SDK.

Returned values

N/A

KosCondvarBroadcast()

Purpose

Signals condition fulfillment to all threads waiting for it.

Parameters

  • [in, out] condvar – pointer to the conditional variable. The conditional variable type is defined in the sysroot-*-kos/include/kos/sync_types.h header file from the KasperskyOS SDK.

Returned values

N/A

Page top
[Topic libkos_sync_api]

Managing I/O memory isolation (iommu_api.h)

The API is defined in the sysroot-*-kos/include/coresrv/iommu/iommu_api.h header file from the KasperskyOS SDK.

The API is intended for managing the isolation of physical memory regions used by devices on a PCIe bus for DMA. (Isolation is provided by the IOMMU.)

Information about API functions is provided in the table below.

Using the API

A device on the PCIe bus cannot use DMA unless the device is attached to the IOMMU domain. After a device is attached to the IOMMU domain, the device can access all DMA buffers that are associated with this IOMMU domain. A device can be attached to only one IOMMU domain at a time, but multiple devices can be attached to the same IOMMU domain. A DMA buffer can be associated with multiple IOMMU domains at the same time. Each IOMMU domain is associated with only one process, but multiple IOMMU domains can be associated with the same process. The capability to create multiple IOMMU domains associated with the same process allows you to restrict access to DMA buffers for different devices managed by the same process.

The API lets you create IOMMU domains, attach devices on a PCIe bus to IOMMU domains, and detach devices on the PCIe bus from IOMMU domains. A device is normally attached to an IOMMU domain when its driver is initialized. A device is usually detached from an IOMMU domain when errors are encountered during driver initialization or driver finalization.

A DMA buffer is associated with an IOMMU domain when calling the KnIoDmaBegin() and KnIoDmaBeginEx() functions that are included in the dma.h API. The KnIoDmaBegin() function associates a DMA buffer with an automatically created IOMMU domain. Each process may be associated with only one such IOMMU domain. This IOMMU domain is created after the first successful call of the KnIommuAttachDevice() function and exists throughout the entire lifetime of the process. The KnIoDmaBeginEx() function associates a DMA buffer with the IOMMU domain that was created by calling the KnIommuCreateDomain() function. Each process may be associated with multiple IOMMU domains that were created by KnIommuCreateDomain() function calls. These IOMMU domains may be removed prior to process termination by closing their handles.

To attach a device to an automatically created IOMMU domain or detach it, you must call the KnIommuAttachDevice() or KnIommuDetachDevice() function, respectively.

To attach a device to an IOMMU domain that was created by calling the KnIommuCreateDomain() function or detach it, you must call the KnIommuAttachDeviceToDomain() or KnIommuDetachDeviceFromDomain() function, respectively.

Information about API functions

iommu_api.h functions

Function

Information about the function

KnIommuAttachDevice()

Purpose

Attaches a device on a PCIe bus to the automatically created IOMMU domain associated with the calling process.

Parameters

  • [in] bdf – address of the device on the PCIe bus in BDF format.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

If IOMMU is not enabled, rcOk is returned.

KnIommuDetachDevice()

Purpose

Detaches a device on a PCIe bus from the automatically created IOMMU domain associated with the calling process.

Parameters

  • [in] bdf – address of the device on the PCIe bus in BDF format.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

If IOMMU is not enabled, rcOk is returned.

KnIommuCreateDomain()

Purpose

Creates an IOMMU domain associated with the calling process.

Parameters

  • [out] domain – pointer to the IOMMU domain handle.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnIommuAttachDeviceToDomain()

Purpose

Attaches a device on a PCIe bus to the defined IOMMU domain associated with the calling process.

Parameters

  • [in] bdf – address of the device on the PCIe bus in BDF format.
  • [in] domain – IOMMU domain handle.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnIommuDetachDeviceFromDomain()

Purpose

Detaches a device on a PCIe bus from the defined IOMMU domain associated with the calling process.

Parameters

  • [in] bdf – address of the device on the PCIe bus in BDF format.
  • [in] domain – IOMMU domain handle.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Page top
[Topic libkos_iommu_api]

Using queues (queue.h)

The API is defined in the header file sysroot-*-kos/include/kos/queue.h from the KasperskyOS SDK.

The API sets up data exchange between threads owned by one process via a queuing mechanism that does not lock threads. In other words, you can add or extract elements of a queue without locking other threads that add or extract elements of this queue.

Information about API functions is provided in the table below.

Using the API

The standard scenario for API usage includes the following steps:

  1. Create a queue abstraction.

    A queue abstraction consists of a structure containing queue metadata and a queue buffer intended for storing elements of the queue. A queue buffer is logically divided into equal segments, each of which is intended for an individual element of the queue. The number of segments in a queue buffer matches the maximum number of elements in the queue. The alignment of segment addresses corresponds to the data types of elements in the queue.

    To complete this step, call the KosQueueCreate() function. This function can allocate memory for the queue buffer or use already allocated memory. The size of the already allocated memory must be sufficient to accommodate the maximum number of elements in the queue. Also take into account that the size of a segment in the queue buffer is rounded to the next largest multiple of the alignment value defined through the objAlign parameter. The initial address of the already allocated memory must also be aligned to correspond to the data types of queue elements. If the memory address alignment specified in the buffer parameter is less than the value defined through the objAlign parameter, the function returns RTL_NULL.

  2. Exchange data between threads by adding and extracting elements of the queue.

    To add one element to the end of the queue, you must reserve a segment in the queue buffer by calling the KosQueueAlloc() function, copy this element to the reserved segment, and call the KosQueuePush() function.

    To add a sequence of elements to the end of the queue, you must reserve the necessary number of segments in the queue buffer via KosQueueAlloc() function calls, copy the elements of this sequence to the reserved segments, and call the KosQueuePushArray() function. The order of elements in a sequence is not changed after this sequence is added to the queue. In other words, elements are added to the queue in the same order in which the pointers to reserved segments in the queue buffer are put into the array that is passed through the objs parameter of the KosQueuePushArray() function.

    To extract the first element of the queue, you must call the KosQueuePop() function. This function returns the pointer to the reserved segment in the queue buffer that contains the first element of the queue. After using an extracted element (for example, after checking or saving the value of an element), you must free the queue buffer segment occupied by this element. To do so, call the KosQueueFree() function.

    To clear the queue and free all registered segments in the queue buffer, you must call the KosQueueFlush() function.

  3. Delete the queue abstraction.

    To complete this step, call the KosQueueDestroy() function. This function deletes the queue buffer if only the memory for this buffer was allocated by the KosQueueCreate() function. Otherwise, you must separately delete the queue buffer.

Information about API functions

queue.h functions

Function

Information about the function

KosQueueCreate()

Purpose

Creates a queue abstraction.

Parameters

  • [in] objCount – maximum number of elements in the queue.
  • [in] objSize – size (in bytes) of an element in the queue.
  • [in] objAlign – alignment of segment addresses in the queue buffer. The addresses of segments in the queue buffer may be unaligned (objAlign=1) or aligned (objAlign=2,4,...,2^N) to the boundary of a 2^N-byte sequence (for example, two-byte or four-byte).
  • [in,optional] buffer – pointer to the allocated memory for the queue buffer, or RTL_NULL to automatically allocate the memory.

Returned values

If successful, the function returns the queue abstraction ID, otherwise it returns RTL_NULL.

KosQueueDestroy()

Purpose

Deletes a queue abstraction.

Parameters

  • [in] queue – queue abstraction ID.

Returned values

N/A

KosQueueAlloc()

Purpose

Reserves a segment in the queue buffer.

Parameters

  • [in] queue – queue abstraction ID.

Returned values

If successful, the function returns the pointer to the reserved segment in the queue buffer, otherwise it returns RTL_NULL.

KosQueueFree()

Purpose

Resets the reservation of the defined segment in the queue buffer.

Parameters

  • [in] queue – queue abstraction ID.
  • [in] obj – pointer to the reserved segment in the queue buffer.

Returned values

N/A

KosQueuePush()

Purpose

Adds an element to the end of the queue.

Parameters

  • [in] queue – queue abstraction ID.
  • [in] obj – pointer to the reserved segment in the queue buffer.

Returned values

N/A

KosQueuePushArray()

Purpose

Adds a sequence of elements to the end of the queue.

Parameters

  • [in] queue – queue abstraction ID.
  • [in] objs – array of pointers to reserved segments in the queue buffer.
  • [in] count – number of elements in the sequence.

Returned values

N/A

KosQueuePop()

Purpose

Extracts the first element of the queue.

Parameters

  • [in] queue – queue abstraction ID.
  • [in] timeout – timeout (in milliseconds) for an element to appear in the queue, or INFINITE_TIMEOUT to set an unlimited timeout.

Returned values

If successful, this function returns the pointer to the reserved segment in the queue buffer containing the first element of the queue. Otherwise it returns RTL_NULL.

KosQueueFlush()

Purpose

Clears the queue and resets the reservation of all registered segments in the queue buffer.

Parameters

  • [in] queue – queue abstraction ID.

Returned values

N/A

Page top
[Topic libkos_queue_api]

Using memory barriers (barriers.h)

This API is defined in the header file sysroot-*-kos/include/coresrv/io/barriers.h from the KasperskyOS SDK.

The API sets barriers for reading from memory and/or writing to memory. A memory barrier is an instruction for a compiler or processor that guarantees that memory access operations specified in source code before setting a barrier will be executed before the memory access operations specified in source code after setting a barrier. Use of memory barriers is required if the specific order of memory write and memory read operations is important. Otherwise, the optimization mechanisms of a compiler and/or processor could cause these operations to be executed in a different order than the order specified in the source code.

Information about API functions is provided in the table below.

barriers.h functions

Function

Information about the function

IoReadBarrier()

Purpose

Sets a barrier for reading from memory.

Parameters

N/A

Returned values

N/A

IoWriteBarrier()

Purpose

Sets a barrier for writing to memory.

Parameters

N/A

Returned values

N/A

IoReadWriteBarrier()

Purpose

Sets a barrier for writing to memory and reading from memory.

Parameters

N/A

Returned values

N/A

Page top
[Topic libkos_barriers_api]

Executing system calls (syscalls.h)

This API is defined in the header file sysroot-*-kos/include/coresrv/syscalls.h from the KasperskyOS SDK.

The API allows execution of the Call(), Recv(), and Reply() system calls for sending and receiving IPC messages.

Information about API functions is provided in the table below.

Using the API

Pointers to buffers containing the constant part and arena of IPC messages are passed to API functions by using an IPC message header whose type is defined in the header file sysroot-*-kos/include/ipc/if_rend.h from the KasperskyOS SDK. Prior to API function calls, the headers of IPC messages must be bound to buffers containing the constant part and arena of IPC messages. To do so, use the PackInMsg() and PackOutMsg() functions that are declared in the header file sysroot-*-kos/include/services/rtl/nk_msg.h from the KasperskyOS SDK.

The Call(), CallEx(), Recv(), and RecvEx() functions lock execution of the calling thread while waiting for the system calls to complete. The CallEx() and RecvEx() functions let you define the timeout for completion of a system call. When this timeout is reached, an uncompleted system call is interrupted and the thread that is waiting for its completion resumes execution. A system call is also interrupted if an error occurs during its execution (such as an error due to termination of a server process). If a thread waiting on the completion of a system call is terminated externally, this system call is also interrupted. A system call executed by the CallEx() or RecvEx() function can be interrupted (for example, for correct termination of a process) by using the API ipc_api.h.

If a system call was interrupted using the API ipc_api.h, the CallEx() and RecvEx() functions return the error code rcIpcInterrupt. If IPC message transmission is prohibited by security mechanisms (such as the Kaspersky Security Module or a capability-based security mechanism implemented by the KasperskyOS kernel), the Call(), CallEx(), and Reply() functions return the error code rcSecurityDisallow.

Information about API functions

syscalls.h functions

Function

Information about the function

Call()

Purpose

Executes the Call() system call with an unlimited timeout for its completion.

Parameters

  • [in] handle – client IPC handle.
  • [in] msgOut – pointer to the header of IPC requests.
  • [in,out] msgIn – pointer to the header of IPC responses.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

CallEx()

Purpose

Executes the Call() system call with a defined timeout for its completion and the capability to interrupt its execution.

Parameters

  • [in] handle – client IPC handle.
  • [in] msgOut – pointer to the header of IPC requests.
  • [in,out] msgIn – pointer to the header of IPC responses.
  • [in] mdelay – timeout (in milliseconds) for completion of a Call() system call, or INFINITE_TIMEOUT to define an unlimited timeout.
  • [in,optional] syncHandle – handle of the IPC synchronization object, or INVALID_HANDLE if an interrupt of the Call() system call is not required.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Reply()

Purpose

Executes the Reply() system call.

Parameters

  • [in] handle – server IPC handle.
  • [in] msgOut – pointer to the header of IPC responses.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Recv()

Purpose

Executes the Recv() system call with an unlimited timeout for its completion.

Parameters

  • [in] handle – server IPC handle.
  • [in,out] msgIn – pointer to the header of IPC requests.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

RecvEx()

Purpose

Executes the Recv() system call with a defined timeout for its completion and the capability to interrupt its execution.

Parameters

  • [in] handle – server IPC handle.
  • [in,out] msgIn – pointer to the header of IPC responses.
  • [in] mdelay – timeout (in milliseconds) for completion of a Recv() system call, or INFINITE_TIMEOUT to define an unlimited timeout.
  • [in,optional] syncHandle – handle of the IPC synchronization object, or INVALID_HANDLE if an interrupt of the Recv() system call is not required.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Page top
[Topic libkos_syscalls_api]

IPC interrupt (ipc_api.h)

This API is defined in the header file sysroot-*-kos/include/coresrv/ipc/ipc_api.h from the KasperskyOS SDK.

The API interrupts the Call() and Recv() system calls if one or more process threads are locked while waiting for these system calls to complete. For example, you may need to interrupt these system calls to correctly terminate a process so that threads waiting for the completion of these system calls can resume execution.

Information about API functions is provided in the table below.

Using the API

The API interrupts system calls in process threads that were locked after the CallEx() or RecvEx() function was called from the API syscalls.h if these functions were called while specifying the IPC synchronization object handle in the syncHandle parameter. To create an IPC synchronization object, call the KnIpcCreateSyncObject() function. (The handle of an IPC synchronization object cannot be transferred to another process because the necessary flag for this operation is not set in the permissions mask of this handle.)

The KnIpcSetInterrupt() function switches an IPC synchronization object to a state that allows interruption of the system calls in those process threads that have been locked after a CallEx() or RecvEx() function call specifying the handle of this IPC synchronization object in the syncHandle parameter. A system call can be interrupted only during certain stages of its execution. A system call that is executed by the CallEx() function can be interrupted only when the server has not yet received a Recv() or RecvEx() function call for the IPC channel whose client IPC handle was specified during the CallEx() function call. A system call executed by the RecvEx() function can be interrupted only while waiting for an IPC request from a client.

The KnIpcClearInterrupt() function cancels the action of the KnIpcSetInterrupt() function.

To delete an IPC synchronization object, close its handle by calling the KnHandleClose() function that is declared in the header file sysroot-*-kos/include/coresrv/handle/handle_api.h from the KasperskyOS SDK.

Information about API functions

ipc_api.h functions

Function

Information about the function

KnIpcCreateSyncObject()

Purpose

Creates an IPC synchronization object.

Parameters

  • [out] syncHandle – pointer to the handle of the IPC synchronization object.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnIpcSetInterrupt()

Purpose

Switches the defined IPC synchronization object to a state in which the Call() and Recv() system calls are interrupted.

Parameters

  • [in] syncHandle – handle of the IPC synchronization object.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnIpcClearInterrupt()

Purpose

Switches the defined IPC synchronization object to a state in which the Call() and Recv() system calls are not interrupted.

Parameters

  • [in] syncHandle – handle of the IPC synchronization object.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Page top
[Topic libkos_ipc_api]

Using sessions (session.h)

The API is defined in the header file sysroot-*-kos/include/kos/session.h from the KasperskyOS SDK.

The API is intended for use in the code of resource providers that provide access to user resources via IPC, and in the code of programs that utilize user resources locally (without IPC). The API lets you organize session-based management of access to user resources. A session consists of a sequence of actions, such as opening access to a resource, using the resource, and closing access to the resource. When access to a resource is opened, a session is created. Closing access to the resource terminates the session. Multiple operations can be simultaneously performed with a resource in one session. A resource can be used in exclusive mode or multi-access mode. In the latter case, the resource must be opened multiple times (possibly with different access permissions). In other words, the resource will be used via multiple, simultaneously existing sessions (parallel sessions).

In the API description, an "object" refers to a KosObject, which is an abstraction of a resource (for details about KosObjects, see Using KosObjects (objects.h)). The type of session and session context are also KosObjects. (A session context contains information about this session, such as the resource access permissions and the counter for active operations with the resource.)

Information about API functions is provided in the table below.

Creating a session type

A session type is created before sessions are created. To create a session type, call the KosSessionCreateType() function.

You must use the objectType parameter to define the type of objects for which the created type of sessions are intended. The object type must inherit the type with the ID kosSessionBaseObjectType.

Use the sessionType parameter to define the type of session contexts. You can specify the base type of session contexts with the ID kosSessionBaseSessionType or the type that inherits it. The base type of session contexts corresponds to the structure containing data such as the pointer to the object, the resource access permissions, the resource handle permissions mask that is transferred to resource consumers, and the counter of active operations with the resource during the session (the type of this structure is not exported to programs, but instead is used by the libkos library). You can add additional information to the session context by creating your own session context type that inherits the base type. For example, the session context for device usage may additionally contain pointers to functions that are called by solution programs to work with the device.

You must use the ops parameter to define the callback functions that are called when creating and terminating sessions. The callback functions for the open and close IDs must be defined. You do not have to define the callback function for the closeComplete ID, therefore this ID can be set to RTL_NULL.

The callback function corresponding to the open ID is called when creating a session and receives the pointers to the object, session context, data passed to the KosSessionOpenObject() function via the openCtx parameter, and the buffer for saving the resource handle permissions mask transferred to resource consumers. In this callback function, you can check the status of the resource, define the resource handle permissions mask transferred to resource consumers, and write data to the object or session context, for example. If the return code is different from rcOk, a session will not be created.

The callback function corresponding to the close ID is called when the session is terminated, irrespective of whether operations with the resource were completed (the counter of active operations in the closed session may be greater than zero), and receives pointers to the object and session context. In this callback function, you can interrupt active operations in a terminated session and write data to an object or session context, for example. Any return code is acceptable.

The callback function corresponding to the closeComplete ID is called when a session is terminated only after completion of all operations with the resource (the counter of active operations in the completed session is equal to zero) and receives the pointers to the object and session context. In this callback function, you can write data to an object, for example.

Registering an object

After creating a session type, you must register the required objects as objects that can be linked to sessions of this type. To register an object, call the KosSessionRegisterObject() function.

You cannot register one object to be linked to different types of sessions at the same time.

After registration, the object is ready to be opened.

Opening an object

When an object is opened, a session linked to this object is created, and an object is opened when there is a request to open access to a resource. This may be a request via IPC from the resource consumer or a local request from another program component.

To open an object, call the KosSessionOpenObject() function. You must use the requiredRights parameter to define the resource access permissions in the created session, and use the shareMode parameter to define the multi-access permissions for a resource to properly restrict access to this resource for parallel sessions. For example, if read-and-write permissions are defined via the requiredRights parameter and the shareMode parameter is set to 0, the created session requires exclusive read-and-write access to the resource. If read-and-write permissions are defined via the requiredRights parameter but only read permissions are defined via the shareMode parameter, the created session requires read-and-write permissions and allows read operations in parallel sessions. If read permissions are defined via the requiredRights parameter but read-and-write permissions are defined via the shareMode parameter, the created session requires read-access and allows read-and-write operations in parallel sessions.

If a resource needs to be used in multi-access mode, you must consider the following conditions when the object is opened a second time and subsequent times:

  • The access permissions defined via the requiredRights parameter cannot exceed the minimal access permissions defined via the shareMode parameter for all parallel sessions linked to this object.
  • The access permissions defined via the shareMode parameter must include all of the access permissions defined via the requiredRights parameter for all parallel sessions linked to this object.

The session context will be created after the object is opened.

If a program uses resources locally, after the object is opened, the program component managing the resources must pass the pointer of the created session context to the program component that uses the resources. When subsequently requesting operations with a resource, the program component using the resources must pass this pointer to the program component managing the resources for session identification.

After opening an object, the resource provider must transfer the resource handle to the consumer. The session context must be used as the resource transfer context so that the consumer can receive the handle of the resource linked to the session. When subsequently requesting operations with a resource, the consumer must put the received resource handle into IPC requests so that the provider receives the pointer to the session context after dereferencing this handle. To fill the resource handle transport container with data for transfer to a resource consumer, call the KosSessionContextToIpcHandle() function. This function receives the session context via the sessionCtx parameter and transfers the resource handle transport container via the desc parameter.

The KosSessionContextToIpcHandle() function takes the permissions mask defined in the callback function that is called when creating the session and puts this permissions mask into the resource handle transport container. The access permissions defined in this mask must not exceed the session access permissions defined via the requiredRights parameter of the KosSessionOpenObject() function. However, the same access permission may correspond to different bits in the permissions mask and in the value defined via the requiredRights parameter of the KosSessionOpenObject() function.

The KosSessionContextToIpcHandle() function defines the session context as the resource transfer context. The session context will be automatically deleted (and therefore the session will be terminated) after closure or revocation of the resource handles that were generated by the transfer of the resource handle that was received by calling the KosSessionContextToIpcHandle() function. If you need to prevent automatic termination of a session for subsequent termination via the KosSessionCloseObject() function call, prior to transferring the resource handle you must increment the counter for links to the context of this session by calling the KosRefObject() function from the objects.h API. In this case, after calling the KosSessionCloseObject() function, you must decrement the counter for links to the session context by calling the KosPutObject() function from the objects.h API.

Performing operations with a resource

An operation with a resource (for example, reading, writing, or getting parameters) is performed by request via IPC from the resource consumer or by local request from another program component.

The scenario for performing an operation with a resource includes the followings steps:

  1. Verify the resource access permissions.

    When processing a local request, call the KosSessionGetOpenRights() function. This function gets information about session resource access permissions defined via the requiredRights parameter of the KosSessionOpenObject() function to compare these permissions with the permissions needed to perform the operation.

    During IPC request processing, you must call the KosSessionIpcHandleToSession() function, which gets the session context and verifies whether the permissions mask of the resource handle that the resource consumer put into the IPC request corresponds to the requested operation. The resource handle transport container received from the resource consumer must be passed to the function via the desc parameter. In the operation parameter, you must specify the resource access permissions that are needed to perform the requested operation. In the type parameter, you must specify the ID of the session type to verify that the type of session context matches the session type. If you set the type parameter to RTL_NULL, you must verify the type of session context prior to converting the pointer type that was received via the sessionCtx parameter. Verification of the session context type is mandatory because the resource provider may create sessions with contexts of different types while the resource consumer may erroneously make an IPC request with the resource handle matching a session with a different type of context. To verify the context type, use the objects.h API.

  2. Increment the counter for active operations in the session by calling the KosSessionRef() function.

    This function verifies that the session has not terminated. In the type parameter, you must specify the ID of the session type to verify that the type of session context matches the session type. You can use the object parameter to receive a pointer to the object.

  3. Perform the requested actions with the resource.
  4. Decrement the counter for active operations in the session by calling the KosSessionPut() function.

Getting a resource handle

A resource handle may be required for using notifications or for querying the Kaspersky Security Module through the security interface, for example. To get a resource handle for an object or session context, call the KosSessionGetObjectHandle() or KosSessionGetObjectHandleBySession() function, respectively.

Enumerating sessions linked to an object

You may need to enumerate sessions linked to an object to notify each of the resource consumers using a resource about the state of that resource, for example. To enumerate sessions linked to an object, call the KosSessionWalk() function. Use the handler parameter to define the callback function that is called for each session during enumeration and receives pointers to the object, session context and data that is passed to the KosSessionWalk() function via the walkCtx parameter. In this callback function, you can send a notification about the state of a resource to consumers of that resource, for example.

Closing an object

When an object is closed, one of the sessions linked to this object is terminated. A session will not be terminated until all operations in this session are terminated (in other words, when the counter of active operations is equal to zero). When a session is terminated, the handles of the resource linked to this session are automatically revoked.

An object is closed when there is a request to close access to the resource. This may be a request via IPC from the resource consumer or a local request from another program component. After making a request to close access to a resource, the resource consumer must close the handle of this resource. (If the resource consumer terminates without making a request to close access to the resource, or closes the resource handle without making this request, the corresponding session will be automatically terminated under the condition that the resource consumer has not additionally incremented the counter for links to the context of this session.)

To close an object, call the KosSessionCloseObject() or KosSessionCloseObjectByIpcHandle() function.

The KosSessionCloseObject() function terminates the session corresponding to the session context that was defined via the sessionCtx parameter.

The KosSessionCloseObjectByIpcHandle() function terminates the session linked to the resource handle that the resource consumer put into the IPC request to close access to the resource. The received resource handle transport container must be passed to the function via the desc parameter. In the type parameter, you must specify the ID of the session type to verify that the type of session context matches the session type.

Deregistering an object

When an object is deregistered, all sessions linked to this object are terminated and it is no longer possible to open this object. A session will not be terminated until all operations in this session are terminated (in other words, when the counter of active operations is equal to zero). When a session is terminated, the handles of the resource linked to this session are automatically revoked. (Revocation does not close resource handles, therefore revoked handles need to be closed.)

To deregister an object, call the KosSessionUnregisterObject() function.

Deleting a session type

A session type must be deleted if there are no registered objects for which sessions of this type can be used, and there will be no more registrations. For example, a session type must be deleted when the resource provider is terminated.

To delete a session type, call the KosSessionDestroyType() function.

Information about API functions

session.h functions

Function

Information about the function

KosSessionCreateType()

Purpose

Creates a session type.

Parameters

  • [in] objectType – ID of the object type for which the sessions are intended. The parameter type is defined in the header file sysroot-*-kos/include/kos/objects.h from the KasperskyOS SDK.
  • [in] sessionType – ID of the session context type. The parameter type is defined in the header file sysroot-*-kos/include/kos/objects.h from the KasperskyOS SDK.
  • [in] ops – pointer to the structure containing the IDs of callback functions that are called when sessions are created and terminated.
  • [out] outType – pointer to the ID of the session type.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosSessionDestroyType()

Purpose

Deletes a session type.

Parameters

  • [in] type – ID of the session type.

Returned values

N/A

KosSessionRegisterObject()

Purpose

Registers an object as an object that can be linked to sessions of the defined type.

Parameters

  • [in] type – ID of the session type.
  • [in] object – pointer to the object.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosSessionUnregisterObject()

Purpose

Deregisters an object that was registered by calling the KosSessionRegisterObject() function.

Parameters

  • [in] object – pointer to the object.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosSessionOpenObject()

Purpose

Opens an object.

Parameters

  • [in] object – pointer to the object.
  • [in,optional] openCtx – pointer to the data that will be passed to the callback function that is called when the session is created. You can specify RTL_NULL if data does not need to be passed. The callback function will receive the passed data through its own ctx parameter.
  • [in] requiredRights – value that defines the resource access permissions in a created session.
  • [in] shareMode – value that defines multi-access permissions for a resource.
  • [out] sessionCtx – pointer to the session context address.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosSessionCloseObject()

Purpose

Closes an object.

Parameters

  • [in] sessionCtx – pointer to the session context.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosSessionRef()

Purpose

Increments the counter for active operations in a session.

Parameters

  • [in,optional] type – ID of the session type, or RTL_NULL if there is no need to verify that the session context type matches the session type.
  • [in] sessionCtx – pointer to the session context.
  • [out,optional] object – pointer to the object address, or RTL_NULL if the object address is not required.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosSessionPut()

Purpose

Decrements the counter for active operations in a session.

Parameters

  • [in] sessionCtx – pointer to the session context.

Returned values

N/A

KosSessionWalk()

Purpose

Enumerates the sessions linked to a defined object.

Parameters

  • [in] object – pointer to the object.
  • [in] handler – ID of the callback function that is called for each session during enumeration.
  • [in,optional] walkCtx – pointer to the data that will be passed to the callback function that was defined via the handler parameter. You can specify RTL_NULL if data does not need to be passed. The callback function will receive the passed data through its own walkCtx parameter.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

If the callback function defined via the handler parameter returns rtl_false, enumeration is terminated.

The callback function defined via the handler parameter must not call the KosSessionOpenObject(), KosSessionCloseObject(), KosSessionRegisterObject(), and KosSessionUnregisterObject() functions.

KosSessionGetOpenRights()

Purpose

Gets information about resource access permissions in the specified session.

These permissions are defined via the requiredRights parameter of the KosSessionOpenObject() function.

Parameters

  • [in] sessionCtx – pointer to the session context.

Returned values

If successful, the function returns the value indicating the resource access permissions, otherwise it returns 0.

KosSessionContextToIpcHandle()

Purpose

Fills the resource handle transport container with data for transfer to a resource consumer when processing an IPC request to open access to the resource.

Parameters

  • [in] sessionCtx – pointer to the session context.
  • [out] desc – pointer to the handle transport container.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosSessionIpcHandleToSession()

Purpose

Gets the session context when processing an IPC request from a resource consumer.

Parameters

  • [in] desc – pointer to the handle transport container.
  • [in] operation – value that indicates the resource access permissions required for performing operations to verify that the handle permissions mask put into the IPC request by the resource consumer matches the requested operation.
  • [in,optional] type – ID of the session type, or RTL_NULL if there is no need to verify that the session context type matches the session type.
  • [out] sessionCtx – pointer to the session context address.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosSessionCloseObjectByIpcHandle()

Purpose

Closes an object when processing an IPC request from a resource consumer to close access to the resource.

Parameters

  • [in] desc – pointer to the handle transport container.
  • [in,optional] type – ID of the session type, or RTL_NULL if there is no need to verify that the session context type matches the session type.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosSessionGetObjectHandle()

Purpose

Gets a resource handle for an object.

Parameters

  • [in] object – pointer to the object.
  • [out] handle – pointer to the handle.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosSessionGetObjectHandleBySession()

Purpose

Gets a resource handle for a session context.

Parameters

  • [in] sessionCtx – pointer to the session context.
  • [out] handle – pointer to the handle.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Page top
[Topic libkos_session_api]

Using KosObjects (objects.h)

The API is defined in the header file sysroot-*-kos/include/kos/objects.h from the KasperskyOS SDK.

The API lets you use typified KosObjects. A KosObject is a process memory region consisting of segments containing service data and payload data. Service data includes a pointer to the structure describing the object type, a counter for links to the object, and other information about the object. Payload data may consist of any data depending on the purpose of the object. For example, segments of payload data in an object representing a device abstraction save the structures that contain the device operating parameters, pointers to low-level methods for working with the device, and the parameters of software/hardware interfaces for device management.

A type inheritance mechanism is supported for KosObjects. For example, an abstraction of the NS16550 UART device contains the following structures in different segments of payload data: a structure specific to NS16550 UART devices, a structure specific to the UART device class, and common structures for all devices. The NS16550 UART device abstraction type corresponds only to the structure that is specific to NS16550 UART devices. All other structures correspond to types that inherited the NS16550 UART device abstraction type.

In the API, the pointer to an object is the pointer to the segment of payload data in this object.

Information about API functions is provided in the table below.

Creating an object type

An object type is created before objects are created. An object type is a process memory region containing the structure that includes data such as the type name, pointers to functions that are called when objects of this type are created and destroyed, a pointer to the parent type, and a counter for links to the type. Each object stores the pointer to this structure, which means that the objects are typified.

To create an object type, call the KosCreateObjectType() or KosCreateObjectTypeEx() function. In contrast to the KosCreateObjectType() function, the KosCreateObjectTypeEx() function lets you create a type that inherits other types. This type contains the address of the parent type that is defined via the parentType parameter. You can also use the parentType parameter to define a type that also contains the address of its parent type. As a result, you can use the KosCreateObjectTypeEx() function to create a type inheritance tree. Each type in this tree will inherit the entire chain of types that form the path from the root of the tree to this specific type.

Depending on whether type inheritance is being employed, objects may be simple or composite. Objects that correspond to one type are known as simple objects. Objects that correspond to a type inheritance chain are known as composite objects. Composite ones consist of simple objects. The number of simple objects in a composite object is equal to the number of types in the inheritance chain. The simple objects form an inheritance chain corresponding to the chain of inheritance of their types. In other words, each object except the first one in the inheritance chain contains the address of the parent object.

You need to use the defaultObjSize parameter of the KosCreateObjectType() and KosCreateObjectTypeEx() functions to define the default size of objects (you can define a different size when creating an object). When creating a type that inherits other types, this parameter pertains only to the last type in the inheritance chain. The defaultObjSize parameter effectively defines the minimum size of a segment of payload data in simple objects because the actual size of objects will be larger than the defined size due to the alignment of memory regions, inheritance of types, and the presence of segments containing service data.

You can use the ops parameter of the KosCreateObjectType() and KosCreateObjectTypeEx() functions to define the callback functions that are called when objects are created and destroyed (you can define both functions or just one of them). When a composite object is created, a set of simple objects is created within it. When the composite object is destroyed, the set of simple objects within it is also destroyed. When each simple object is created and destroyed, separate callback functions that were defined when creating the type of this object are called. The first object in the inheritance chain is created first, and the last object in the inheritance chain is created last. The last object in the inheritance chain is destroyed first, and the first object in the inheritance chain is destroyed last.

The callback function that is called when creating an object receives pointers to the object and the data passed to the KosCreateObjectEx() function via the context parameter. In this callback function, you can allocate resources and initialize data in an object, for example. If the return code differs from rcOk, the object will not be created. If a composite object is being created without creating at least one simple object, this composite object will not be created. Also, when creating a composite object, the data passed to the KosCreateObjectEx() function via the context parameter will be received only by the callback function that is called when creating the last simple object in the inheritance chain.

The callback function that is called when an object is destroyed receives the pointer to the object. In this callback function, you can free up resources, for example. Any return code is acceptable.

Creating an object

After creating an object type, you can create objects. To create an object, you must call the KosCreateObject() or KosCreateObjectEx() function.

Use the type parameter to define the object type. If you define a type that does not inherit other types, a simple object will be created. If you define a type that inherits other types, a composite object will be created and the last simple object in the inheritance chain for this composite object will have the defined type.

Use the size parameter to define the object size, or specify 0 to set the default object size specified in the type of this object. If a composite object is created, this parameter pertains only to the last simple object in the inheritance chain. The size parameter effectively defines the minimum size of a segment of payload data in a simple object because the actual size of the object will be larger than the defined size due to the alignment of the memory region, inheritance of types, and the presence of segments containing service data.

In contrast to the KosCreateObject() function, the KosCreateObjectEx() function has the context parameter, which can be used to pass data to the callback function that is called when an object is created. When creating a composite object, the data passed via the context parameter will be received only by the callback function that is called when creating the last simple object in the inheritance chain.

The outObject parameter is used by the KosCreateObject() and KosCreateObjectEx() functions to transfer the pointer of the created object. The pointer to the created composite object is the pointer to the last simple object in the inheritance chain.

After it is created, the object can be used to write data to it and read data from it.

Obtaining access to simple objects in a composite object

To gain access to simple objects in a composite object, you need to use the KosGetObjectParent() function and/or the KosGetObjectAncestor() function. The KosGetObjectParent() function gets the pointer to the object that is the direct ancestor of the defined object. The KosGetObjectAncestor() function gets the pointer to the object that is the ancestor of the defined object and has the defined type.

Managing the lifetime of objects and their types

An object exists as long as the counter for links to that object has a value greater than zero. Likewise, an object type exists as long as the counter for links to that object has a value greater than zero. When an object or object type is created, the value of the links counter is equal to 1. This counter can then be incremented or decremented to manage the lifetime of the object or object type. For example, after an object is created, you can decrement the counter for links to its type because the libkos library increments the counter for links to this object type when an object is created. In this case, the object type will be destroyed automatically after the object is destroyed because the libkos library decrements the counter for links to the object type when an object is destroyed. In addition, when saving an object address in another object, you must increment the counter for links to the first object to ensure that it exists throughout the lifetime of the second object. When you destroy an object that contains the address of another object, you must decrement the counter for links to the second object to ensure that it is destroyed when no other links remain.

The lifetime of a simple object within a composite object corresponds to the lifetime of this composite object. You cannot separately manage the lifetime of a simple object within a composite object.

To increment the counter for links to an object or object type, call the KosRefObject() or KosRefObjectType() function, respectively.

To decrement the counter for links to an object or object type, call the KosPutObject() or KosPutObjectType() function, respectively.

Verifying an object type

The KosCheckParentType() and KosObjectTypeInheritsType() functions let you check whether one object type is a parent to another object type.

The KosObjectOfType() function verifies whether an object has the defined type.

The KosObjectInheritsType() function checks whether an object has the defined type or a type inherited by the defined type.

Getting the type and name of an object

To get the object type, call the KosObjectGetType() function.

To get the object name, call the KosGetObjectName() function. (Each simple object in a composite object has the name of this composite object.)

Getting the name of an object type

To get the name of an object type, call the KosObjectGetTypeName() function.

Information about API functions

objects.h functions

Function

Information about the function

KosCreateObjectType()

Purpose

Creates an object type.

Parameters

  • [in] name – pointer to the name of the object type.
  • [in] defaultObjSize – default size of objects, in bytes.
  • [in,optional] ops – pointer to the structure containing pointers to the callback functions that are called when creating and destroying objects. You can set this to RTL_NULL if you do not need to define these callback functions.
  • [out] outType – pointer to the ID of the object type.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosCreateObjectTypeEx()

Purpose

Creates an object type.

Parameters

  • [in] name – pointer to the name of the object type.
  • [in] id – fictitious parameter. You must specify 0.
  • [in] defaultObjSize – default size of objects, in bytes.
  • [in,optional] ops – pointer to the structure containing pointers to the callback functions that are called when creating and destroying objects. You can set this to RTL_NULL if you do not need to define these callback functions.
  • [in,optional] parentType – ID of the parent object type, or RTL_NULL if inheritance of other object types is not required.
  • [out] outType – pointer to the ID of the object type.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosCreateObjectEx()

Purpose

Creates an object.

Parameters

  • [in] type – ID of the object type.
  • [in,optional] name – pointer to the object name, or RTL_NULL if you do not need to define the object name.
  • [in,optional] size – size of the object (in bytes), or 0 to set the default object size.
  • [in,optional] context – pointer to the data that will be passed to the callback function that is called when the object is created. You can specify RTL_NULL if data does not need to be passed. The callback function will receive the passed data through its own context parameter.
  • [out] outObject – pointer to the object address.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

When an object is created, memory is allocated for that object and this memory is filled with zeros.

KosRefObjectType()

Purpose

Increments the counter for links to an object type.

Parameters

  • [in] type – ID of the object type.

Returned values

N/A

KosPutObjectType()

Purpose

Decrements the counter for links to an object type.

Parameters

  • [in] type – ID of the object type.

Returned values

N/A

KosCheckParentType()

Purpose

Verifies that the specific object type is a direct descendant of the parentType object type.

Parameters

  • [in] type – ID of the object type.
  • [in] parentType – ID of the object type.

Returned values

If the verification is successful, the function returns rtl_true, otherwise it returns rtl_false.

KosObjectTypeInheritsType()

Purpose

Verifies that the specific object type is a descendant of the parentType object type.

Parameters

  • [in] type – ID of the object type.
  • [in] parentType – ID of the object type.

Returned values

If the verification is successful, the function returns rtl_true, otherwise it returns rtl_false.

KosCreateObject()

Purpose

Creates an object.

Parameters

  • [in] type – ID of the object type.
  • [in,optional] name – pointer to the object name, or RTL_NULL if you do not need to define the object name.
  • [in,optional] size – size of the object (in bytes), or 0 to set the default object size.
  • [out] outObject – pointer to the object address.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

When an object is created, memory is allocated for that object and this memory is filled with zeros.

KosRefObject()

Purpose

Increments the counter for links to an object.

Parameters

  • [in] object – pointer to the object.

Returned values

N/A

KosPutObject()

Purpose

Decrements the counter for links to an object.

Parameters

  • [in] object – pointer to the object.

Returned values

N/A

KosGetObjectName()

Purpose

Gets the object name.

Parameters

  • [in] object – pointer to the object.

Returned values

Returns the ID of the KosString containing the object name. The type of returned value is defined in the header file sysroot-*-kos/include/kos/strings.h from the KasperskyOS SDK.

Additional information

The KosGetObjectName() function increments the counter for links to the KosString containing the object name. If this string is no longer needed, you need to decrement the number of links to it by calling the KosPutString() function from the strings.h API.

KosGetObjectParent()

Purpose

Gets the pointer to the object that is the direct ancestor of the defined object.

Parameters

  • [in] object – pointer to the object.

Returned values

If successful, the function returns the pointer for the object that is the direct ancestor of the defined object, otherwise it returns RTL_NULL.

KosGetObjectAncestor()

Purpose

Gets the pointer to the object that is the ancestor of the defined object and has the defined type.

Parameters

  • [in] object – pointer to the object.
  • [in] type – ID of the object type.

Returned values

If successful, the function returns the pointer for the object that is the ancestor of the defined object and has the defined type, otherwise it returns RTL_NULL.

Additional information

If the object parameter is used to define an object that has the type defined via the type parameter, the function returns the pointer for this object.

KosObjectOfType()

Purpose

Verifies that the object has the defined type.

Parameters

  • [in] object – pointer to the object.
  • [in] type – ID of the object type.

Returned values

If the verification is successful, the function returns rtl_true, otherwise it returns rtl_false.

KosObjectInheritsType()

Purpose

Verifies that the object has the defined type or the type that inherits the defined type.

Parameters

  • [in] object – pointer to the object.
  • [in] type – ID of the object type.

Returned values

If the verification is successful, the function returns rtl_true, otherwise it returns rtl_false.

KosObjectGetType()

Purpose

Gets the ID of the object type.

Parameters

  • [in] object – pointer to the object.

Returned values

Object type ID.

Additional information

Increments the counter for links to an object type. If the received object type ID is no longer needed, you must decrement the number of links to the object type by calling the KosPutObjectType() function.

KosObjectGetTypeName()

Purpose

Gets the name of the object type.

Parameters

  • [in] type – ID of the object type.

Returned values

Returns the ID of the KosString containing the object type name. The type of returned value is defined in the header file sysroot-*-kos/include/kos/strings.h from the KasperskyOS SDK.

Additional information

The KosObjectGetTypeName() function increments the counter for links to the KosString containing the object type name. If this string is no longer needed, you need to decrement the number of links to it by calling the KosPutString() function from the strings.h API.

Page top
[Topic libkos_objects_api]

Using KosObject containers (objcontainer.h)

The API is defined in the header file sysroot-*-kos/include/kos/objcontainer.h from the KasperskyOS SDK.

The API lets you merge KosObjects into containers to conveniently use sets of these objects (for details about KosObjects, see Using KosObjects (objects.h)). The containers are also KosObjects and may be elements of other containers. The same KosObject may be an element of multiple containers at the same time.

Information about API functions is provided in the table below.

Creating a container

To create a container, call the KosCreateObjContainer() function. In the parent parameter, you can specify the ID of the parent container, which is the container to which the created container will be added.

Adding an object to a container

To add an object to a container, call the KosInsertObjContainerObject() function. An object can be another container. You must use the name parameter to define the object name that this object will have within the container. This name is not related to the name that was defined when the object was created. The name of an object within a container must be unique so that this object can be unambiguously identified among other objects in this container. When an object is added to a container, the counter for links to this object is incremented.

Removing an object from a container

To remove an object from a container, call the KosRemoveObjContainerObjectByName() or KosRemoveObjContainerObject() function. When an object is removed from a container, the counter for links to this object is decremented.

Searching for an object in a container

To search for an object with the defined name in a container, call the KosGetObjContainerObjectByName() function. Child containers will not be searched for the object. This function increments the counter for links to the found object.

Enumerating objects in a container

Enumeration may be necessary to perform specific actions with multiple objects in a container. To enumerate objects in a container, call the KosWalkObjContainerObjects() function. Use the walk parameter to define the callback function that is called for each object during enumeration and receives pointers to the object and data that is passed to the KosWalkObjContainerObjects() function via the context parameter. Objects in child containers are not enumerated.

Enumerating the names of objects in a container

To enumerate the names of objects in a container, use the KosEnumObjContainerNames() function. The order of enumeration for object names matches the order in which these objects are added to the container. Object names in child containers are not enumerated.

Getting the number of objects in a container

To get the number of objects in a container, call the KosCountObjContainerObjects() function. Objects in child containers are not taken into account.

Clearing a container

To remove all objects from a container, call the KosClearObjContainer() function. This function decrements the counters for links to objects that are removed from the container.

Checking whether an object is a container

To check whether an object is a container, call the KosIsContainer() function.

Deleting a container

To delete a container, call the KosDestroyObjContainer() function. When a container is deleted, the counters for links to objects within this container are decremented.

Information about API functions

objcontainer.h functions

Function

Information about the function

KosCreateObjContainer()

Purpose

Creates a container.

Parameters

  • [in,optional] parent – ID of the parent container, or RTL_NULL if you do not need to add the created container to an already existing container.
  • [in] name – pointer to the name of the created container.
  • [out] outContainer – ID of the created container.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosDestroyObjContainer()

Purpose

Deletes a container.

Parameters

  • [in] container – ID of the container.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosInsertObjContainerObject()

Purpose

Adds an object to a container.

Parameters

  • [in] container – ID of the container.
  • [in] name – pointer to the object name.
  • [in] object – pointer to the object.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosRemoveObjContainerObjectByName()

Purpose

Removes the object with the defined name from a container.

Parameters

  • [in] container – ID of the container.
  • [in] name – pointer to the object name.
  • [in,optional] object – pointer to the object, or RTL_NULL if you do not need to verify that the object name defined via the name parameter matches the object being removed.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosRemoveObjContainerObject()

Purpose

Removes an object from a container.

Parameters

  • [in] container – ID of the container.
  • [in] object – pointer to the object.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosGetObjContainerObjectByName()

Purpose

Searches a container for the object with the defined name.

Parameters

  • [in] container – ID of the container.
  • [in] name – pointer to the name of the object that you are searching for.
  • [out] outObject – pointer to the address of the found object.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

If an object with the defined name is not found, the function returns the RTL_NULL value via the outObject parameter.

KosWalkObjContainerObjects()

Purpose

Enumerates objects in a container and calls the defined function for each object during enumeration.

Parameters

  • [in] container – ID of the container.
  • [in] walk – ID of the callback function that is called for each object during enumeration. The parameter type is defined in the header file sysroot-*-kos/include/kos/objects.h from the KasperskyOS SDK.
  • [in,optional] context – pointer to the data that will be passed to the callback function that was defined via the walk parameter. You can specify RTL_NULL if data does not need to be passed. The callback function will receive this data through its own context parameter.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

The callback function defined via the walk parameter must not call other API functions.

If a callback function defined via the walk parameter returns a value with the KOS_OBJECT_WALK_FINISH flag, the KosWalkObjContainerObjects() function terminates enumeration.

If a callback function defined via the walk parameter returns a value with the KOS_OBJECT_WALK_REMOVE_OBJECT flag, the KosWalkObjContainerObjects() function removes the corresponding object from the container.

The KOS_OBJECT_WALK_FINISH and KOS_OBJECT_WALK_REMOVE_OBJECT flags are defined in the header file sysroot-*-kos/include/kos/objects.h from the KasperskyOS SDK.

KosEnumObjContainerNames()

Purpose

Enumerates the names of objects in a container.

Parameters

  • [in] container – ID of the container.
  • [in] index – index for enumerating object names. Enumeration starts with zero.
  • [out] outStr – pointer to the ID of the KosString containing the object name.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Additional information

The KosEnumObjContainerNames() function increments the counter for links to the KosString containing the object name. If this string is no longer needed, you need to decrement the number of links to it by calling the KosPutString() function from the strings.h API.

KosCountObjContainerObjects()

Purpose

Gets the number of objects in a container.

Parameters

  • [in] container – ID of the container.

Returned values

Number of objects in a container.

KosClearObjContainer()

Purpose

Clears a container.

Parameters

  • [in] container – ID of the container.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosIsContainer()

Purpose

Checks whether an object is a container.

Parameters

  • [in] object – pointer to the object.

Returned values

If the verification is successful, the function returns rtl_true, otherwise it returns rtl_false.

Page top
[Topic libkos_objcontainer_api]

Using KosStrings (strings.h)

The API is defined in the header file sysroot-*-kos/include/kos/strings.h from the KasperskyOS SDK.

The API lets you use KosStrings, which have the following distinguishing characteristics:

  1. A KosString is a C-string (with a terminating zero) that follows the header containing the service data.
  2. KosStrings are stored in hash tables, which are arrays whose elements are lists of strings. (The pointers for creating linked lists of strings are stored in the headers of strings.) Each list consists of one or more strings. Each list contains the strings who have the same value for the remainder after dividing the hash value of the string by the number of lists in the hash table. The main property of a hash table is that the computational complexity of searching for a string does not depend on the degree of occupancy of this table if all lists include only one string.

    When adding KosStrings to a hash table in real-world scenarios, lists containing multiple strings may be created. This leads to varying computational complexity when searching for strings in the hash table for the following reason. When searching for a key, the hash value is calculated and then converted into a string list index (by calculating the remainder from dividing the hash value by the number of lists). If there is only one string in the list containing the calculated index, the search will be complete after comparing this string to the key. However, if there are multiple strings in the list containing the calculated index, you may need to compare the key to all strings in this list to complete the search. In this case, the computational complexity of searching for a string may be higher than when there is only one string in the list.

  3. KosStrings from one hash table are unique, which means that there are no identical strings in a hash table. If the strings from one hash table have different IDs, that means that these are different strings. (In the API, the ID of the KosString is the pointer to this string.) This lets you compare strings based on their IDs instead of their contents, thereby ensuring that the computational complexity of the comparison does not depend on the sizes of strings.
  4. The size of a KosString is stored in the header instead of being calculated based on a search for a terminating zero, thereby ensuring that the computational complexity of getting the size does not depend on the actual size of the string.
  5. KosStrings cannot be modified. This characteristic is a result of characteristics 2–4. Modification of a string may lead to the appearance of identical strings in the same hash table, a discrepancy between the actual size of a string and the size stored in the header, and a discrepancy between the string contents and the index of the string list in which this string is listed in the hash table.
  6. A KosString exists as long as the counter for links to it remains greater than zero. (The string links counter is stored in the header.)

Information about API functions is provided in the table below.

Creating a hash table

You can use the default hash table, which is created automatically during initialization of the libkos library. This table may include no more than 2039 lists of strings with a string size of no more than 65,524 bytes without taking into account the terminating zero.

You can create a hash table with the required maximum number of string lists and the required maximum size of strings by calling the KosCreateStringRoot() function.

A hash table is created empty without any strings.

Adding a KosString to a hash table

To add a string to the default hash table, call the KosCreateString() function.

To add a string to a defined hash table, call the KosCreateStringEx() function.

If the string being added is already listed in the hash table, these functions do not add a new string but instead pass the ID of the already existing string via the outStr parameter.

Searching for a KosString in a hash table

To search for a string in the default hash table, call the KosGetString() function.

To search for a string in a defined hash table, call the KosGetStringEx() function.

The search is completed successfully if the key completely matches the string.

Managing the lifetime of KosStrings

A string exists as long as the counter for links to it remains greater than zero. The KosCreateString() and KosCreateStringEx() functions add a string whose links counter has a value of 1 to the hash table. If the string has already been added to the hash table, these functions increment the counter for links to this string. The KosGetString() and KosGetStringEx() functions increment the counter for links to the found string. This counter can then be incremented or decremented to manage the lifetime of the string. When passing the ID of a string to another program component, you must increment the counter for links to the corresponding string to ensure that this string will exist for the amount of time required by this component. If the string is no longer needed, you must decrement the counter for links to this string to ensure that it is destroyed when no other links remain.

To increment the counter for links to a string, call the KosRefString() or KosRefStringEx() function.

To decrement the counter for links to a string in the default hash table, call the KosPutString() function.

To decrement the counter for links to a string in a defined hash table, call the KosPutStringEx() function.

Getting the size of a KosString

To get the size of a string without taking into account the terminating zero, call the KosGetStringLen() function.

To get the size of a string while taking into account the terminating zero, call the KosGetStringSize() function.

Deleting a hash table

To delete a hash table, call the KosDestroyStringRoot() function. The table will be deleted only if it is empty.

Information about API functions

strings.h functions

Function

Information about the function

KosCreateStringRoot()

Purpose

Creates an empty hash table.

Parameters

  • [in] numBuckets – maximum number of KosString lists.
  • [in] maxStrLength – maximum size of KosStrings without taking into account the terminating zero, in bytes.

Returned values

ID of the hash table.

KosDestroyStringRoot()

Purpose

Deletes an empty hash table.

Parameters

  • [in] handle – ID of the hash table.

Returned values

N/A

KosGetString()

Purpose

Searches for a KosString in the default hash table.

Parameters

  • [in] str – pointer to the C-string containing the search key.

Returned values

If successful, the function returns the ID of the KosString, otherwise it returns RTL_NULL.

KosGetStringEx()

Purpose

Searches for a KosString in a defined hash table.

Parameters

  • [in,optional] root – ID of the hash table, or RTL_NULL to assign the default hash table.
  • [in] str – pointer to the C-string containing the search key.

Returned values

If successful, the function returns the ID of the KosString, otherwise it returns RTL_NULL.

KosCreateString()

Purpose

Adds a KosString to the default hash table.

Parameters

  • [in] str – pointer to the C-string whose data needs to be put into the KosString.
  • [out] outStr – pointer to the ID of the KosString.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosCreateStringEx()

Purpose

Adds a KosString to a defined hash table.

Parameters

  • [in,optional] root – ID of the hash table, or RTL_NULL to assign the default hash table.
  • [in] str – pointer to the C-string whose data needs to be put into the KosString.
  • [out] outStr – pointer to the ID of the KosString.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KosRefString()

Purpose

Increments the counter for links to a KosString.

Parameters

  • [in] str – ID of the KosString.

Returned values

N/A

KosRefStringEx()

Purpose

Increments the counter for links to a KosString.

Parameters

  • [in,optional] root – fictitious parameter. You must specify RTL_NULL.
  • [in] str – ID of the KosString.

Returned values

N/A

KosPutString()

Purpose

Decrements the counter for links to a KosString in the default hash table.

Parameters

  • [in] str – ID of the KosString.

Returned values

N/A

KosPutStringEx()

Purpose

Decrements the counter for links to a KosString in a defined hash table.

Parameters

  • [in,optional] root – ID of the hash table, or RTL_NULL to assign the default hash table.
  • [in] str – ID of the KosString.

Returned values

N/A

KosGetStringLen()

Purpose

Gets the size of the KosString without taking into account the terminating zero.

Parameters

  • [in] str – ID of the KosString.

Returned values

Size of the KosString without taking into account the terminating zero, in bytes.

Additional information

If the parameter has the RTL_NULL value, it returns 0.

KosGetStringSize()

Purpose

Gets the size of the KosString while taking into account the terminating zero.

Parameters

  • [in] str – ID of the KosString.

Returned values

Size of the KosString while taking into account the terminating zero, in bytes.

Additional information

If the parameter has the RTL_NULL value, it returns 0.

Page top
[Topic libkos_strings_api]

KasperskyOS kernel XHCI DbC driver management (xhcidbg_api.h)

This API is defined in the header file sysroot-*-kos/include/coresrv/xhcidbg/xhcidbg_api.h from the KasperskyOS SDK.

This API is intended for use in the code of drivers that implement a USB stack (kusb class drivers) and lets you stop and start the XHCI DbC (Debug Capability) driver of the KasperskyOS kernel. (The KasperskyOS kernel includes the XHCI DbC driver, which is a simplified XHCI controller driver and is used by the kernel for diagnostic output or by the kernel GDB server to interact with the GDB debugger.) If a kusb class driver needs to restart the XHCI controller, the kernel's XHCI DbC driver must be stopped by calling the KnXhcidbgStop() function before the restart and then started by calling the KnXhcidbgStart() function after the restart. If you do not do this, a restart of the XHCI controller will lead to a failure of diagnostic output (or debugging) via the USB port.

This API has not been implemented for the Raspberry Pi 4 B and Radxa ROCK 3A hardware platforms (the functions return rcUnimplemented).

Information about API functions is provided in the table below.

xhcidbg_api.h functions

Function

Information about the function

KnXhcidbgStart()

Purpose

Starts the XHCI DbC driver of the KasperskyOS kernel.

Parameters

N/A

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnXhcidbgStop()

Purpose

Stops the XHCI DbC driver of the KasperskyOS kernel.

Parameters

N/A

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Page top
[Topic libkos_xhcidbg_api]

Receiving security audit data (vlog_api.h)

This API is defined in the header file sysroot-*-kos/include/coresrv/vlog/vlog_api.h from the KasperskyOS SDK.

The API lets you read from the KasperskyOS kernel log containing security audit data and is used in the code of the static library sysroot-*-kos/lib/libklog_system_audit.a, which is linked to the Klog system program.

Information about API functions is provided in the table below.

Using the API

The API usage scenario includes the following steps:

  1. Open the kernel log containing security audit data by calling the KnAuOpen() function.
  2. Receive messages from the kernel log containing security audit data via calls of the KnAuRead() function.

    This log is a cyclic buffer, and therefore you must prevent overwrites in this log because they could lead to a loss of security audit data that has not yet been read. To monitor overwrites in the log, the outDropMsgs parameter of the KnAuRead() function is used to pass the number of dropped messages. (The counter of these messages is reset to zero after this value is read each time the function is called.) If messages have been dropped, you must either increase the speed at which messages are read from the log, for example, by performing the read operation from parallel threads, or reduce the speed of message generation by editing the security audit profile.

  3. Close the kernel log containing security audit data by calling the KnAuClose() function.

Information about API functions

vlog_api.h functions

Function

Information about the function

KnAuOpen()

Purpose

Opens the kernel log containing security audit data.

Parameters

  • [in] name – pointer to the name of the kernel log containing security audit data (kss must be specified).
  • [out] outRID – pointer to the handle of the kernel log containing security audit data.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnAuClose()

Purpose

Closes the kernel log containing security audit data.

Parameters

  • [in] rid – handle of the kernel log containing security audit data.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnAuRead()

Purpose

Receives a message from the kernel log containing security audit data.

Parameters

  • [in] rid – handle of the kernel log containing security audit data.
  • [out] msg – pointer to the buffer used to store the message. The type of message is defined in the header file sysroot-*-kos/include/vlog/audit.h. The buffer size must be at least FULL_AUDIT_MESSAGE_LENGTH_MAX bytes.
  • [out] outDropMsgs – pointer to the number of messages that were lost due to overwrites in the kernel log containing security audit data.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Page top
[Topic libkos_vlog_api]

Using futexes (sync.h)

This API is defined in the header file sysroot-*-kos/include/coresrv/sync/sync.h from the KasperskyOS SDK.

The API is intended for working with futexes and is used in code of the API functions in event.h, mutex.h, rwlock.h, semaphore.h, and condvar.h. A futex is a low-level synchronization primitive that supports two operations: lock a thread and add it to the futex-linked queue of locked threads, and resume execution of threads from the futex-linked queue of locked threads. A futex is a kernel object linked to an integer variable in the user space. The kernel object provides the capability to store a queue of locked threads linked to the futex. The value of the integer variable in the user space (futex value) is atomically modified by the synchronized threads to signal the changed state of shared resources. For example, the futex value may indicate the specific state of an event (signaling or non-signaling state), indicate whether the mutex has been captured or freed, and indicate the specific value of the semaphore counter. The futex value determines whether to lock a thread that attempts to obtain access to shared resources.

Information about API functions is provided in the table below.

Using the API

To use a futex, you must create only an integer variable for storing its value. The API functions receive the pointer to this variable via the ftx parameter. The kernel object linked to this variable is created or deleted automatically when using the API functions.

The KnFutexWait() function locks the calling thread if the futex value matches the value of the val parameter. (A futex value can be changed by another thread during execution of a function.) The thread is locked for the mdelay time period, but execution of this thread may be resumed before the mdelay period elapses by calling the KnFutexWake() function from another thread. The KnFutexWake() function resumes execution of threads from a futex-linked queue of locked threads. The number of threads whose execution is resumed is limited by the value of the nThreads parameter. Thread execution is resumed starting with the beginning of the queue.

Information about API functions

sync.h functions

Function

Information about the function

KnFutexWait()

Purpose

Locks the calling thread if the futex value is equal to the expected value.

Parameters

  • [in] ftx – pointer to the variable containing the futex value.
  • [in] val – expected value of the futex.
  • [in] mdelay – maximum lockout duration in milliseconds, or INFINITE_TIMEOUT to set an unlimited lockout duration.
  • [out,optional] outDelay – actual lockout duration in milliseconds, or RTL_NULL if this information is not required.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

If the thread lockout duration has expired, the function returns rcTimeout.

If the futex value is not equal to the expected value, the function returns rcFutexWouldBlock.

KnFutexWake()

Purpose

Resumes execution of threads that were blocked by KnFutexWait() function calls with the defined futex.

Parameters

  • [in] ftx – pointer to the variable containing the futex value.
  • [in] nThreads – maximum number of threads whose execution can be resumed.
  • [out,optional] wokenCnt – actual number of threads whose execution has been resumed, or RTL_NULL if this information is not required.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Page top
[Topic libkos_futex_sync_api]

Getting IPC handles and RIIDs to use statically created IPC channels (sl_api.h)

This API is defined in the header file sysroot-*-kos/include/coresrv/sl/sl_api.h from the KasperskyOS SDK.

The API allows servers to get the listener handles, and allows clients to get the client IPC handles and Runtime Implementation Identifiers (RIIDs) for the purpose of using statically created IPC channels.

Closing an obtained IPC handle will cause the IPC channel to become unavailable. After an IPC handle is closed, it is impossible to obtain it again or restore access to the IPC channel.

Information about API functions is provided in the table below.

sl_api.h functions

Function

Information about the function

ServiceLocatorRegister()

Purpose

Gets the listener handle based on the name of the IPC channel.

Parameters

  • [in] channelName – pointer to the name of the IPC channel.
  • [in] endpoints – fictitious parameter (obsolete). It must be set to RTL_NULL.
  • [in] endpointsSize – fictitious parameter (obsolete). It must be set to 0.
  • [out] id – fictitious parameter (obsolete).

Returned values

If successful, it returns the listener handle. Otherwise, it returns INVALID_HANDLE.

ServiceLocatorConnect()

Purpose

Gets the client IPC handle based on the name of the IPC channel.

Parameters

  • [in] channelName – pointer to the name of the IPC channel.

Returned values

If successful, it returns the client IPC handle. Otherwise, it returns INVALID_HANDLE.

ServiceLocatorGetRiid()

Purpose

Gets the endpoint ID (RIID).

Parameters

Returned values

If successful, the function returns the endpoint ID (RIID), otherwise it returns INVALID_RIID. The type of returned value is defined in the header file sysroot-*-kos/include/nk/types.h from the KasperskyOS SDK.

Page top
[Topic libkos_sl_api]

Power management (pm_api.h)

This API is defined in the header file sysroot-*-kos/include/coresrv/pm/pm_api.h from the KasperskyOS SDK.

The API changes the power mode of the hardware platform (for example, shutdown or restart), and enables and disables processors (processor cores).

Information about API functions is provided in the table below.

Using the API

To make a request to change the power mode of the hardware platform, call the KnPmRequest() function.

The KnPmSetCpusOnline() and KnPmGetCpusOnline() functions have the mask parameter, which is used to pass the processor mask. A processor mask is a bit mask indicating the set of processors (processor cores). A flag set in the ith bit indicates that a processor with the i index is included in the set (numbering starts at zero). To work with a processor mask, you must use the functions defined in the header file sysroot-*-kos/include/rtl/cpuset.h.

To enable and/or disable processors, call the KnPmSetCpusOnline() function while specifying the processor mask indicating the required set of active processors. The flag corresponding to the bootstrap processor must be set in this mask, otherwise the function will end with an error. To get the bootstrap processor index, call the KnPmGetBootstrapCpuNum() function.

To find out which processors are in the active state, call the KnPmGetCpusOnline() function. The output parameter of this function is the processor mask indicating the actual set of active processors.

If the KnPmSetCpusOnline() function ended with an error, this could lead to an unpredictable change in the set of active processors. To make a repeated attempt to configure the set of active processors, you must find out which processors are in the active state by calling the KnPmGetCpusOnline() function and use this information to adjust the required set of active processors during the subsequent KnPmSetCpusOnline() function call.

Information about API functions

pm_api.h functions

Function

Information about the function

KnPmRequest()

Purpose

Requests to change the power mode of a hardware platform.

Parameters

  • [in] request – value defining the necessary power mode of the hardware platform. The parameter type is defined in the header file sysroot-*-kos/include/pm/pmstate.h from the KasperskyOS SDK.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnPmSetCpusOnline()

Purpose

Requests to enable and/or disable processors.

Parameters

  • [in] mask – pointer to the processor mask indicating the required set of active processors. The type of processor mask is defined in the header file sysroot-*-kos/include/rtl/cpuset.h from the KasperskyOS SDK.
  • [in] timeoutMs – fictitious parameter (obsolete).

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnPmGetCpusOnline()

Purpose

Gets information regarding which processors are in the active state.

Parameters

  • [out] mask – pointer to the processor mask indicating the actual set of active processors. The type of processor mask is defined in the header file sysroot-*-kos/include/rtl/cpuset.h from the KasperskyOS SDK.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

KnPmGetBootstrapCpuNum()

Purpose

Gets the index of the bootstrap processor.

Parameters

  • [out] num – pointer to the bootstrap processor index. The type of processor index is defined in the header file sysroot-*-kos/include/rtl/cpuset.h from the KasperskyOS SDK.

Returned values

If successful, the function returns rcOk, otherwise it returns an error code.

Page top
[Topic libkos_pm_api]