Transferring handles

August 2, 2023

ID libkos_handles_transfer

Overview

Handles are transferred between programs so that clients (programs that utilize resources) can obtain 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 program. This handle is registered as a descendant of the transferred handle and identifies the same resource.

One handle can be transferred multiple times by one or multiple programs. Each transfer initiates the creation of a new descendant of the transferred handle on the recipient program side. A program can transfer the handles that it received from other programs or from the KasperskyOS kernel (when creating handles of system resources). 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 program can transfer handles for user resources and system resources if the access rights of these handles permit such a transfer. A descendant may have less access rights than an ancestor. For example, a transferring program with read-and-write permissions for a file can transfer read-only permissions. The transferring program can also prohibit the recipient program from further transferring the handle. Access rights are defined in the transferred permissions mask for the handle.

Conditions for transferring handles

For programs to transfer handles to other programs, the following conditions must be met:

  1. An IPC channel is created between the programs.
  2. The solution security policy (security.psl) allows interaction between the programs.
  3. Interface methods are implemented for transferring handles.
  4. The client program received the endpoint ID (RIID) of the server program that has methods for transferring handles.

Interface methods for transferring handles are declared in the IDL language with input (in) and/or output (out) parameters of the Handle type. Methods with input parameters of the Handle type are intended for transferring handles from the client program to the server program. Methods with output parameters of the Handle type are intended for transferring handles from the server program to the client program. No more than seven input and seven output parameters of the Handle type can be declared for one method.

Example IDL description containing declarations 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 in the *_req request structure and/or *_res response structure of the nk_handle_desc_t type (hereinafter also referred to as the transport container of the handle). This type is declared in the nk/types.h header file 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 is the data that allows the server program 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. A server program receives a pointer to the resource transfer context when dereferencing a handle.

Regardless of whether or not a server program is the resource provider, it 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 request.

If the server program 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 program that is the resource provider can use 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 program uses multiple various-type resources of the server program, 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 program can verify that the client program 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 program could mistakenly send the interface method a resource handle that does not correspond to this method. For example, a client program receives a file handle and sends it to an interface method for working with volumes.

To associate a handle transfer with a resource transfer context, the server program 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 object that stores the pointer to the resource transfer context. The resource transfer context object is created by the KnHandleCreateBadge() function, which is declared in the coresrv/handle/handle_api.h header file. This function is bound to the Notification Subsystem regarding the state of resources because a server program needs to know when a resource transfer context object will be closed and terminated. The server program 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 when deleting or revoking the handle descendants (see Deleting handles, Revoking handles) that were generated during its transfer in association with this object. (A transferred handle may be deleted intentionally or unintentionally, such as when a recipient client program is unexpectedly terminated.) After receiving a notification regarding the closure of a resource transfer context object, the server program deletes the handle of this object. After this, the resource transfer context object is terminated. After receiving a notification regarding the termination of the resource transfer context object, the server program 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.

handle_api.h (fragment)

/**

* Creates a resource transfer context object for

* the resource transfer "context" and configures the

* notification receiver "notice" to receive notifications about

* this object. The notification receiver is configured to

* receive notifications about events that match the

* event mask flags OBJECT_DESTROYED and EVENT_BADGE_CLOSED.

* Input parameter eventId defines the identifier of the

* "resource–event mask" entry in the notification receiver.

* Output parameter handle contains the handle of the

* resource transfer context.

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

*/

Retcode KnHandleCreateBadge(Notice notice, rtl_uintptr_t eventId,

void *context, Handle *handle);

Packaging data into the transport container of a handle

The nk_handle_desc() macro declared in the nk/types.h header file is used to package a handle, handle permissions mask and resource transfer context object handle into a handle transport container. This macro receives a variable number of arguments.

If no argument is passed to the macro, the NK_INVALID_HANDLE value will be written in the handle field of the nk_handle_desc_t structure.

If one argument is passed to the macro, this argument is interpreted as the handle.

If two arguments are passed to the macro, the first argument is interpreted as the handle and the second argument is interpreted as the handle permissions mask.

If three arguments are passed to the macro, the first argument is interpreted as the handle, the second argument is interpreted as the handle permissions mask, and the third argument is interpreted as the resource transfer context object handle.

Extracting data from the transport container of a handle

The nk_get_handle(), nk_get_rights() and nk_get_badge_op() (or nk_get_badge()) functions that are declared in the nk/types.h header file are used to extract the handle, handle permissions mask, and pointer to the resource transfer context, respectively, from the transport container of a handle. The nk_get_badge_op() and nk_get_badge() functions are used only when dereferencing handles.

Handle transfer scenarios

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

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

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

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

If the transferring program 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 made by the transferring or recipient client program or the Reply() system call made by the transferring server program ends with the rcSecurityDisallow error.

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.