KasperskyOS Community Edition 1.3

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]