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 ========================
On Thu, Jan 12, 2023, at 13:50, Kevin Brodsky wrote:
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
Thanks, this helps clarify things a lot, and would have helped me in the initial review. I'm sure the question of what the types should be for an eventual mainline kernel version (and also how the compat interface should be used) will keep coming up in the future, but documenting what you have decided to do for the Morello version is an important step.
+| | ``(unsigned) long`` | 64-bit integer | 64-bit integer | | +| | ``(unsigned) long long`` | | | | +| | ``ptraddr_t`` | | | |
I only recently realized that 'long long' is also just 64-bit, not just 'long'. I think this is the most surprising bit here, though I can see how redefining it as a 128-bit type would mess things up in the kernel as well.
There is clearly no good solution here, and I saw that the informal rv128 ABI does the same thing, with the addition of a new 128-bit 'long long long' type.[1]
Arnd
[1] https://github.com/brucehoult/riscv-meta/blob/master/doc/src/rv128.md
On 12/01/2023 13:50, Kevin Brodsky wrote:
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
Now applied on morello/next, thanks Arnd for having a look at it!
Kevin
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 ========================
linux-morello@op-lists.linaro.org