Designing the Key Protection in a Key-protected Kernel Extension

You must design the key protection so that any incorrect references to memmory can easily be detected and repaired.

To design key protection into a kernel extension, perform the following steps:

  1. Define memory classes. A memory class is a set of virtual pages that are associated with the same storage protection key. Ideally, each memory class is represented by a unique kernel key, although there are limits on both the actual number of kernel keys that can be used, and the actual number of hardware keys that are available for the kernel and kernel extensions.
  2. Allocate a kernel key for each memory class. You can use the kkey_assign_private kernel service to allocate unique kernel keys.
  3. Assign kernel keys to the (pages of) memory to be included in each memory class. You can use the heap_create kernel service to create a memory heap whose pages are protected with a specified kernel key. Your new heap can then be used by the xmalloc and xmfree kernel services as usual.

    When your program ends, use the heap_destroy kernel service to clean up any heaps you have created.

  4. Determine which kernel keys are required by the kernel extension to satisfy the requirements of other kernel extension data that is referred to. For the best result, add the access rights from one of these predefined key sets to your own, rather than build up your key set from scratch. See Kernel Keys and Kernel Key Sets.
  5. Create the kernel key sets defining the access authorities that are needed by your extension to refer to its private memory classes. You can use the following kernel services:
    kkeyset_create
    Allocates an empty key set.
    kkeyset_add_key
    Adds access rights for a kernel key to your key set.
    kkeyset_remove_key
    Removes access rights to a given kernel key from your key set.
    kkeyset_add_set
    Adds the access rights that are defined in one key set to another.
    kkeyset_remove_set
    Removes the access rights that are defined in one key set from another.
    kkeyset_delete
    Frees a key set after it has been used to create a hardware key set by 6.
  6. Create hardware key sets that you need to control access to the memory classes during execution. These hardware key sets are needed to implement your protection gates. The kkeyset_to_hkeyset service performs this translation.
    Attention: The HKEYSET_GLOBAL key set is defined to access any memory no matter which key protects it. Therefore, this hardware key set should be used with caution.
  7. Implement protection gates as needed to grant access to the memory classes, and to restore the prior authority mask register state. Typically, you can perform these steps at the entry and exit points of the major functions of the kernel extension. You can implement a replace gate at an entry point in your driver to grant access appropriately. Without one, the driver has the inappropriate access rights of its caller, typically the kernel. You can implement a restore gate at exit points to restore the access rights back to those of the calling program. See Protection Gates for more information about protection gates.
  8. Link the kernel extension using the new -b ras flag, so that the kernel can recognize it as a key-safe kernel extension.

If the extension must refer to user space memory, use the copyin, copyout, or one of the cross-memory kernel services. These services acquire the appropriate additional hardware keys necessary to access and protect user space. (The user-space application might use storage protect keys itself.) It is possible, but not suggested, to add user keys to the current authority mask register with the hkeyset_update_userkeys service, and to restore the previous state with the hkeyset_restore_userkeys service.

Any kernel keys can be used, with appropriate care, by any kernel extension. You can also remove keys that you do not need. For example, you can remove the KKEY_TRB key if your extension does not use services such as the tstart kernel service, which uses the trb structure. Though not required, the action can increase the benefit of using storage protect keys by minimizing the access rights of your kernel extension. Start with a predefined key set, and remove specific keys; rather than start with an empty key set, and figure out which ones you need to add.

In general, you do not need to test your code for the presence, absence, or number of available hardware keys. All key-protection kernel services work efficiently in all cases.