PCuABI itself is defined by the PCuABI specification. However, the specification only documents the ABI itself and not internal kernel implementation aspects. To that effect, create a document under a new cheri/ subfolder, as well as an index file with some information about CHERI support in general.
Now that we have a generic PCuABI document, link to it from the related documents, and remove a now-redundant section from the user pointer doc. All CHERI / PCuABI-related documents are now reachable from Documentation/cheri/index.rst.
The PCuABI porting guide was initially added to the root of Documentation/ for lack of relevant subfolder, we can now move it to a more appropriate home.
Reviewed-by: Vincenzo Frascino vincenzo.frascino@arm.com Signed-off-by: Kevin Brodsky kevin.brodsky@arm.com ---
Rendered version:
https://git.morello-project.org/kbrodsky-arm/linux/-/tree/pcuabi_doc/Documen...
Documentation/arm64/morello.rst | 14 +- Documentation/cheri/index.rst | 22 +++ Documentation/{ => cheri}/pcuabi-porting.rst | 18 +- Documentation/cheri/pcuabi.rst | 177 +++++++++++++++++++ Documentation/core-api/user_ptr.rst | 25 +-- 5 files changed, 220 insertions(+), 36 deletions(-) create mode 100644 Documentation/cheri/index.rst rename Documentation/{ => cheri}/pcuabi-porting.rst (96%) create mode 100644 Documentation/cheri/pcuabi.rst
diff --git a/Documentation/arm64/morello.rst b/Documentation/arm64/morello.rst index bc0d98596762..00f28b76d1a6 100644 --- a/Documentation/arm64/morello.rst +++ b/Documentation/arm64/morello.rst @@ -231,12 +231,12 @@ ABIs In the default kernel configuration, existing aspects of the standard AArch64 kernel-user ABI remain unchanged.
-As a highly experimental feature, it is possible to choose a different -kernel-user ABI, the **pure-capability ABI** (PCuABI), by selecting the -``CONFIG_CHERI_PURECAP_UABI`` option. In this ABI, all pointers at the -kernel-user boundary are capabilities, providing a native interface for -pure-capability executables; see the CHERI C/C++ Programming Guide [4]_ -for an overview of this programming model. +As an experimental feature, it is possible to choose a different +kernel-user ABI, the `pure-capability kernel-user ABI`_ (PCuABI), by +selecting the ``CONFIG_CHERI_PURECAP_UABI`` option. In this ABI, all +pointers at the kernel-user boundary are capabilities, providing a +native interface for pure-capability executables; see the CHERI C/C++ +Programming Guide [4]_ for an overview of this programming model.
When ``CONFIG_CHERI_PURECAP_UABI`` is selected, the meaning of ``CONFIG_COMPAT`` is modified: instead of providing support for AArch32 @@ -280,6 +280,8 @@ ABI**. These extensions are also available in PCuABI, with a number of differences. The transitional PCuABI specification [5]_ takes precedence where it differs from the present document.
+.. _pure-capability kernel-user ABI: Documentation/cheri/pcuabi.rst + Register handling -----------------
diff --git a/Documentation/cheri/index.rst b/Documentation/cheri/index.rst new file mode 100644 index 000000000000..6955e298b88e --- /dev/null +++ b/Documentation/cheri/index.rst @@ -0,0 +1,22 @@ +============= +CHERI support +============= + +This directory contains documents related to the support of `CHERI`_. +CHERI is an architectural extension introducing the concept of hardware +capabilities. The CHERI model is available on a number of architectures; +many aspects of CHERI support are arch-agnostic, however lower-level +arch-specific enablement is also required. The following CHERI-enabled +architectures are currently supported in Linux: + +* `Morello`_ (arm64-based experimental architecture) + +Documentation in this directory pertains only to arch-agnostic aspects of +CHERI support. + +.. toctree:: + pcuabi + pcuabi-porting + +.. _CHERI: https://www.cl.cam.ac.uk/research/security/ctsrd/cheri/ +.. _Morello: Documentation/arm64/morello.rst diff --git a/Documentation/pcuabi-porting.rst b/Documentation/cheri/pcuabi-porting.rst similarity index 96% rename from Documentation/pcuabi-porting.rst rename to Documentation/cheri/pcuabi-porting.rst index a3ff0c98e6b0..2a38862e869a 100644 --- a/Documentation/pcuabi-porting.rst +++ b/Documentation/cheri/pcuabi-porting.rst @@ -3,12 +3,10 @@ Adding PCuABI support to drivers =================================
This document provides a non-exhaustive overview of the most common -changes required to support the pure-capability user ABI (PCuABI) in -arbitrary drivers. It may also be helpful for core subsystems, though -note that more extensive changes may be required compared to drivers -with straightforward interactions with userspace. - -.. _user pointer documentation: core-api/user_ptr.rst +changes required to support the `pure-capability kernel-user ABI`_ +(PCuABI) in arbitrary drivers. It may also be helpful for core +subsystems, though note that more extensive changes may be required +compared to drivers with straightforward interactions with userspace.
User pointer representation and conversions =========================================== @@ -342,8 +340,8 @@ typically throw the following error::
error: use of __capability is ambiguous
-A fixup is then required, as described in section "PCuABI-specific -changes" of the `user pointer documentation`_. For instance:: +A fixup is then required, as described in section "Leveraging ``__user``" +of the `PCuABI documentation`_. For instance::
diff --git a/net/socket.c b/net/socket.c index 8597fbacb089..ab2a610825cc 100644 @@ -364,3 +362,7 @@ changes" of the `user pointer documentation`_. For instance::
Fortunately, ``__user`` is mostly used in simple types, and such fixups are rarely needed in driver code. + +.. _user pointer documentation: Documentation/core-api/user_ptr.rst +.. _PCuABI documentation: Documentation/cheri/pcuabi.rst +.. _pure-capability kernel-user ABI: `PCuABI documentation`_ diff --git a/Documentation/cheri/pcuabi.rst b/Documentation/cheri/pcuabi.rst new file mode 100644 index 000000000000..90e8a4200826 --- /dev/null +++ b/Documentation/cheri/pcuabi.rst @@ -0,0 +1,177 @@ +=================================== +The pure-capability kernel-user ABI +=================================== + +CHERI capabilities can be used in many ways. In the so-called +pure-capability model, all pointers are represented as capabilities, +whether they are manipulated explicitly or not. This approach is highly +attractive as it leverages many of the CHERI mechanisms to strengthen +memory safety, without disrupting the vast majority of existing C/C++ +software. + +The pure-capability model requires a major ABI break, as the +representation of pointers is fundamentally different from "traditional" +ABIs, where pointers are simply integer addresses. Supporting such a +model in userspace therefore requires the introduction of a new +kernel-user ABI, the pure-capability kernel-user ABI (PCuABI). + +A specification for this new uABI, complemented with rationale about its +design and objectives, is available in the following document: + + `PCuABI specification`_ + +This specification is currently limited to the Morello architecture, as +it is the only CHERI-enabled architecture supported in Linux. Adding +support for other architectures would entail extending the specification +accordingly. + +The present document deals with implementation aspects that are beyond +the scope of the specification. It aims to provide kernel developers +with an overview of the changes that have been made to various internal +kernel APIs in order to support PCuABI. + +Note: current limitations + Support for PCuABI in Linux is a work in progress, and at this stage + it is mostly of a functional nature, with only limited enforcement of + capability-related restrictions. The variant of the ABI that is + currently implemented in Linux is documented in the `transitional + PCuABI specification`_, which is forward-compatible with the full + specification. Only **a limited set of syscalls** is supported in this + ABI. + +Config option +============= + +Selecting the option ``CONFIG_CHERI_PURECAP_UABI`` enables support for +the pure-capability uABI; in other words, the native userspace ABI +becomes PCuABI instead of the "traditional" uABI. This option is not +tied to any particular architecture, but naturally it is only available +on CHERI-enabled architectures. + + +The hybrid approach +=================== + +The way in which PCuABI is currently implemented in Linux is a hybrid +approach: the native userspace ABI becomes pure-capability while **the +in-kernel ABI remains unchanged**. Concretely, this means that kernel +pointers and user pointers are no longer intercompatible; specifically, +a kernel pointer - still an integer - cannot represent a user pointer - +now a capability. + +Note: different approaches + This is only one of a number of plausible strategies to support PCuABI. + A more natural approach is to change the in-kernel ABI in line with + the userspace ABI, that is to make the kernel itself a pure-capability + binary. While this simplifies the handling of user pointers compared + to the hybrid approach, and strengthens the kernel itself, building + the kernel in the pure-capability ABI is a major undertaking, mainly + due to the extremely widespread representation of kernel pointers as + ``long``-sized integers. To keep the level of effort reasonable and + achieve a complete implementation of PCuABI in a realistic timescale, + the hybrid approach has therefore been chosen as a starting point. + + +Leveraging __user +----------------- + +User pointers are currently turned into capabilities by redefining the +``__user`` macro to expand to ``__capability``. This is a convenient +approach as all user pointers should already be annotated with +``__user``, thereby avoiding the extensive changes a new annotation +would entail. + +Unfortunately, the ``_user`` annotation prefixes ``*``, for instance:: + + void __user * + +This is problematic as ``void __capability *`` is deprecated; +``__capability`` is only unambiguous when used as a suffix for ``*``. +In more complex cases, such as double pointers, the compiler is only +able to parse ``__capability`` as a suffix. + +It is therefore occasionally necessary to introduce PCuABI-specific fixup +blocks to remove that ambiguity by moving ``__capability`` from prefix to +suffix. It is typically done as follows:: + + #ifdef CONFIG_CHERI_PURECAP_UABI + void * __capability * __capability p; + #else + void __user * __user *p; + #endif + +Fortunately, in the vast majority of cases simple user pointers are used +and no such fixup is required. + + +Pointer and address types +========================= + +As mentioned previously, user pointers are larger than kernel pointers +when ``CONFIG_CHERI_PURECAP_UABI`` is selected. Indeed, user pointers +are represented as capabilities; they are therefore 129-bit wide on +64-bit architectures: twice the address size, plus an out-of-band tag +bit. This tag bit is an integral part of the user pointer and can only +be preserved by representing the user pointer with a compiler-provided +capability type, such as ``void * __capability`` or ``__uintcap_t``. + +For this reason, the representation of certain types changes when the +kernel is built to support PCuABI. The table below provides the +*representation* of various types **in the kernel** on a 64-bit +architecture, depending on the supported user ABI: + ++----------------------------------+------------------+----------------+--------------------------------------------------------------------------+ +| Type | Traditional uABI | PCuABI | Notes | ++==================================+==================+================+==========================================================================+ +| ``void *`` | 64-bit integer | 64-bit integer | | ++----------------------------------+------------------+----------------+--------------------------------------------------------------------------+ +| ``uintptr_t`` | 64-bit integer | 64-bit integer | | ++----------------------------------+------------------+----------------+--------------------------------------------------------------------------+ +| | ``(unsigned) long`` | 64-bit integer | 64-bit integer | ``ptraddr_t`` is a new generic type that represents an address. | +| | ``(unsigned) long long`` | | | | +| | ``ptraddr_t`` | | | | ++----------------------------------+------------------+----------------+--------------------------------------------------------------------------+ +| ``void __user *`` | 64-bit integer | Capability | | ++----------------------------------+------------------+----------------+--------------------------------------------------------------------------+ +| ``user_uintptr_t`` | 64-bit integer | Capability | Represented as ``uintcap_t`` in PCuABI, see below. | ++----------------------------------+------------------+----------------+--------------------------------------------------------------------------+ +| | ``__kernel_uintptr_t`` | 64-bit integer | Capability | * Represented as ``uintcap_t`` in PCuABI, see below. | +| | ``__kernel_aligned_uintptr_t`` | | | * At least 64-bit regardless of the ABI. | ++----------------------------------+------------------+----------------+--------------------------------------------------------------------------+ +| | ``void __capability *`` | Capability | Capability | Only available on CHERI-enabled architectures (``__CHERI__`` defined). | +| | ``void * __capability`` | | | | ++----------------------------------+------------------+----------------+--------------------------------------------------------------------------+ +| ``uintcap_t`` | Capability | Capability | * Only available on CHERI-enabled architectures (``__CHERI__`` defined). | +| | | | * Represented as a capability, but otherwise behaves as a 64-bit integer | +| | | | (when performing arithmetic, converting to other integer types, etc.). | ++----------------------------------+------------------+----------------+--------------------------------------------------------------------------+ + +For reference, the table below provides the representation of relevant +types **in userspace**, depending on the chosen ABI: + ++----------------------------------+-----------------+---------------------+------------------------------------------------------------------------+ +| Type | Traditional ABI | Pure-capability ABI | Notes | ++==================================+=================+=====================+========================================================================+ +| ``void *`` | 64-bit integer | Capability | | ++----------------------------------+-----------------+---------------------+------------------------------------------------------------------------+ +| ``uintptr_t`` | 64-bit integer | Capability | Represented as ``uintcap_t`` in purecap. | ++----------------------------------+-----------------+---------------------+------------------------------------------------------------------------+ +| | ``(unsigned) long`` | 64-bit integer | 64-bit integer | | +| | ``(unsigned) long long`` | | | | +| | ``ptraddr_t`` | | | | ++----------------------------------+-----------------+---------------------+------------------------------------------------------------------------+ +| | ``__kernel_uintptr_t`` | 64-bit integer | Capability | * Represented as ``uintcap_t`` in purecap. | +| | ``__kernel_aligned_uintptr_t`` | | | * At least 64-bit regardless of the ABI. | ++----------------------------------+-----------------+---------------------+------------------------------------------------------------------------+ +| | ``void __capability *`` | Capability | Capability | Only available on CHERI-enabled architectures (``__CHERI__`` defined). | +| | ``void * __capability`` | | | | ++----------------------------------+-----------------+---------------------+------------------------------------------------------------------------+ +| ``uintcap_t`` | Capability | Capability | Only available on CHERI-enabled architectures (``__CHERI__`` defined). | ++----------------------------------+-----------------+---------------------+------------------------------------------------------------------------+ + +For more information about user pointers and related conversions, please +refer to the `user pointer documentation`_. + +.. _PCuABI specification: https://git.morello-project.org/morello/kernel/linux/-/wikis/Morello-pure-ca... +.. _Transitional PCuABI specification: https://git.morello-project.org/morello/kernel/linux/-/wikis/Transitional-Mo... +.. _user pointer documentation: Documentation/core-api/user_ptr.rst diff --git a/Documentation/core-api/user_ptr.rst b/Documentation/core-api/user_ptr.rst index 21e02d4bd11b..0e14616c0499 100644 --- a/Documentation/core-api/user_ptr.rst +++ b/Documentation/core-api/user_ptr.rst @@ -12,7 +12,7 @@ regions: These two categories of pointers are not interchangeable and, in particular, the kernel should never directly dereference a user pointer.
-The introduction of the pure-capability kernel-user ABI (PCuABI) has +The introduction of the `pure-capability kernel-user ABI`_ (PCuABI) has made this distinction even more important, as in that configuration user pointers are of a different type altogether and cannot be represented by kernel pointers or most integer types. @@ -20,6 +20,8 @@ kernel pointers or most integer types. This document outlines the available API to represent and manipulate user pointers in a way that is safe in any kernel-user ABI.
+.. _pure-capability kernel-user ABI: Documentation/cheri/pcuabi.rst + Representing user pointers ==========================
@@ -52,27 +54,6 @@ integer types such as ``long``. User **addresses** may however still be represented like kernel addresses, e.g. using ``long``. The recommended type for addresses when writing new code is ``ptraddr_t``.
-PCuABI-specific changes ------------------------ - -When PCuABI is targeted by selecting the ``CONFIG_CHERI_PURECAP_UABI`` -option, user pointers are turned into capabilities by making the -``__user`` annotation expand to ``__capability``. Unfortunately, -``_user`` precedes ``*`` and using ``__capability`` as a prefix of ``*`` -is deprecated. It does work in most cases, but in more complex -situations, such as double pointers, it becomes ambiguous and fails to -compile. - -It is therefore occasionally necessary to have PCuABI-specific fixup -blocks to solve that ambiguity by moving ``__capability`` as a suffix of -``*``. It is typically done as follows:: - - #ifdef CONFIG_CHERI_PURECAP_UABI - void * __capability * __capability p; - #else - void __user * __user *p; - #endif -
Converting user pointers ========================