Back to home page

OSCL-LXR

 
 

    


0001 ==========================
0002 AArch64 TAGGED ADDRESS ABI
0003 ==========================
0004 
0005 Authors: Vincenzo Frascino <vincenzo.frascino@arm.com>
0006          Catalin Marinas <catalin.marinas@arm.com>
0007 
0008 Date: 21 August 2019
0009 
0010 This document describes the usage and semantics of the Tagged Address
0011 ABI on AArch64 Linux.
0012 
0013 1. Introduction
0014 ---------------
0015 
0016 On AArch64 the ``TCR_EL1.TBI0`` bit is set by default, allowing
0017 userspace (EL0) to perform memory accesses through 64-bit pointers with
0018 a non-zero top byte. This document describes the relaxation of the
0019 syscall ABI that allows userspace to pass certain tagged pointers to
0020 kernel syscalls.
0021 
0022 2. AArch64 Tagged Address ABI
0023 -----------------------------
0024 
0025 From the kernel syscall interface perspective and for the purposes of
0026 this document, a "valid tagged pointer" is a pointer with a potentially
0027 non-zero top-byte that references an address in the user process address
0028 space obtained in one of the following ways:
0029 
0030 - ``mmap()`` syscall where either:
0031 
0032   - flags have the ``MAP_ANONYMOUS`` bit set or
0033   - the file descriptor refers to a regular file (including those
0034     returned by ``memfd_create()``) or ``/dev/zero``
0035 
0036 - ``brk()`` syscall (i.e. the heap area between the initial location of
0037   the program break at process creation and its current location).
0038 
0039 - any memory mapped by the kernel in the address space of the process
0040   during creation and with the same restrictions as for ``mmap()`` above
0041   (e.g. data, bss, stack).
0042 
0043 The AArch64 Tagged Address ABI has two stages of relaxation depending on
0044 how the user addresses are used by the kernel:
0045 
0046 1. User addresses not accessed by the kernel but used for address space
0047    management (e.g. ``mprotect()``, ``madvise()``). The use of valid
0048    tagged pointers in this context is allowed with these exceptions:
0049 
0050    - ``brk()``, ``mmap()`` and the ``new_address`` argument to
0051      ``mremap()`` as these have the potential to alias with existing
0052      user addresses.
0053 
0054      NOTE: This behaviour changed in v5.6 and so some earlier kernels may
0055      incorrectly accept valid tagged pointers for the ``brk()``,
0056      ``mmap()`` and ``mremap()`` system calls.
0057 
0058    - The ``range.start``, ``start`` and ``dst`` arguments to the
0059      ``UFFDIO_*`` ``ioctl()``s used on a file descriptor obtained from
0060      ``userfaultfd()``, as fault addresses subsequently obtained by reading
0061      the file descriptor will be untagged, which may otherwise confuse
0062      tag-unaware programs.
0063 
0064      NOTE: This behaviour changed in v5.14 and so some earlier kernels may
0065      incorrectly accept valid tagged pointers for this system call.
0066 
0067 2. User addresses accessed by the kernel (e.g. ``write()``). This ABI
0068    relaxation is disabled by default and the application thread needs to
0069    explicitly enable it via ``prctl()`` as follows:
0070 
0071    - ``PR_SET_TAGGED_ADDR_CTRL``: enable or disable the AArch64 Tagged
0072      Address ABI for the calling thread.
0073 
0074      The ``(unsigned int) arg2`` argument is a bit mask describing the
0075      control mode used:
0076 
0077      - ``PR_TAGGED_ADDR_ENABLE``: enable AArch64 Tagged Address ABI.
0078        Default status is disabled.
0079 
0080      Arguments ``arg3``, ``arg4``, and ``arg5`` must be 0.
0081 
0082    - ``PR_GET_TAGGED_ADDR_CTRL``: get the status of the AArch64 Tagged
0083      Address ABI for the calling thread.
0084 
0085      Arguments ``arg2``, ``arg3``, ``arg4``, and ``arg5`` must be 0.
0086 
0087    The ABI properties described above are thread-scoped, inherited on
0088    clone() and fork() and cleared on exec().
0089 
0090    Calling ``prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE, 0, 0, 0)``
0091    returns ``-EINVAL`` if the AArch64 Tagged Address ABI is globally
0092    disabled by ``sysctl abi.tagged_addr_disabled=1``. The default
0093    ``sysctl abi.tagged_addr_disabled`` configuration is 0.
0094 
0095 When the AArch64 Tagged Address ABI is enabled for a thread, the
0096 following behaviours are guaranteed:
0097 
0098 - All syscalls except the cases mentioned in section 3 can accept any
0099   valid tagged pointer.
0100 
0101 - The syscall behaviour is undefined for invalid tagged pointers: it may
0102   result in an error code being returned, a (fatal) signal being raised,
0103   or other modes of failure.
0104 
0105 - The syscall behaviour for a valid tagged pointer is the same as for
0106   the corresponding untagged pointer.
0107 
0108 
0109 A definition of the meaning of tagged pointers on AArch64 can be found
0110 in Documentation/arm64/tagged-pointers.rst.
0111 
0112 3. AArch64 Tagged Address ABI Exceptions
0113 -----------------------------------------
0114 
0115 The following system call parameters must be untagged regardless of the
0116 ABI relaxation:
0117 
0118 - ``prctl()`` other than pointers to user data either passed directly or
0119   indirectly as arguments to be accessed by the kernel.
0120 
0121 - ``ioctl()`` other than pointers to user data either passed directly or
0122   indirectly as arguments to be accessed by the kernel.
0123 
0124 - ``shmat()`` and ``shmdt()``.
0125 
0126 - ``brk()`` (since kernel v5.6).
0127 
0128 - ``mmap()`` (since kernel v5.6).
0129 
0130 - ``mremap()``, the ``new_address`` argument (since kernel v5.6).
0131 
0132 Any attempt to use non-zero tagged pointers may result in an error code
0133 being returned, a (fatal) signal being raised, or other modes of
0134 failure.
0135 
0136 4. Example of correct usage
0137 ---------------------------
0138 .. code-block:: c
0139 
0140    #include <stdlib.h>
0141    #include <string.h>
0142    #include <unistd.h>
0143    #include <sys/mman.h>
0144    #include <sys/prctl.h>
0145    
0146    #define PR_SET_TAGGED_ADDR_CTRL      55
0147    #define PR_TAGGED_ADDR_ENABLE        (1UL << 0)
0148    
0149    #define TAG_SHIFT            56
0150    
0151    int main(void)
0152    {
0153         int tbi_enabled = 0;
0154         unsigned long tag = 0;
0155         char *ptr;
0156    
0157         /* check/enable the tagged address ABI */
0158         if (!prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE, 0, 0, 0))
0159                 tbi_enabled = 1;
0160    
0161         /* memory allocation */
0162         ptr = mmap(NULL, sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_WRITE,
0163                    MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
0164         if (ptr == MAP_FAILED)
0165                 return 1;
0166    
0167         /* set a non-zero tag if the ABI is available */
0168         if (tbi_enabled)
0169                 tag = rand() & 0xff;
0170         ptr = (char *)((unsigned long)ptr | (tag << TAG_SHIFT));
0171    
0172         /* memory access to a tagged address */
0173         strcpy(ptr, "tagged pointer\n");
0174    
0175         /* syscall with a tagged pointer */
0176         write(1, ptr, strlen(ptr));
0177    
0178         return 0;
0179    }