KasperskyOS Community Edition

Transferring handles

May 21, 2024

ID libkos_handles_transfer

Overview

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 specialized objects of the KosObject type. 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.

Did you find this article helpful?
What can we do better?
Thank you for your feedback! You're helping us improve.
Thank you for your feedback! You're helping us improve.