tagged-address-abi.rst 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. ==========================
  2. AArch64 TAGGED ADDRESS ABI
  3. ==========================
  4. Authors: Vincenzo Frascino <vincenzo.frascino@arm.com>
  5. Catalin Marinas <catalin.marinas@arm.com>
  6. Date: 21 August 2019
  7. This document describes the usage and semantics of the Tagged Address
  8. ABI on AArch64 Linux.
  9. 1. Introduction
  10. ---------------
  11. On AArch64 the ``TCR_EL1.TBI0`` bit is set by default, allowing
  12. userspace (EL0) to perform memory accesses through 64-bit pointers with
  13. a non-zero top byte. This document describes the relaxation of the
  14. syscall ABI that allows userspace to pass certain tagged pointers to
  15. kernel syscalls.
  16. 2. AArch64 Tagged Address ABI
  17. -----------------------------
  18. From the kernel syscall interface perspective and for the purposes of
  19. this document, a "valid tagged pointer" is a pointer with a potentially
  20. non-zero top-byte that references an address in the user process address
  21. space obtained in one of the following ways:
  22. - ``mmap()`` syscall where either:
  23. - flags have the ``MAP_ANONYMOUS`` bit set or
  24. - the file descriptor refers to a regular file (including those
  25. returned by ``memfd_create()``) or ``/dev/zero``
  26. - ``brk()`` syscall (i.e. the heap area between the initial location of
  27. the program break at process creation and its current location).
  28. - any memory mapped by the kernel in the address space of the process
  29. during creation and with the same restrictions as for ``mmap()`` above
  30. (e.g. data, bss, stack).
  31. The AArch64 Tagged Address ABI has two stages of relaxation depending
  32. how the user addresses are used by the kernel:
  33. 1. User addresses not accessed by the kernel but used for address space
  34. management (e.g. ``mprotect()``, ``madvise()``). The use of valid
  35. tagged pointers in this context is allowed with these exceptions:
  36. - ``brk()``, ``mmap()`` and the ``new_address`` argument to
  37. ``mremap()`` as these have the potential to alias with existing
  38. user addresses.
  39. NOTE: This behaviour changed in v5.6 and so some earlier kernels may
  40. incorrectly accept valid tagged pointers for the ``brk()``,
  41. ``mmap()`` and ``mremap()`` system calls.
  42. - The ``range.start``, ``start`` and ``dst`` arguments to the
  43. ``UFFDIO_*`` ``ioctl()``s used on a file descriptor obtained from
  44. ``userfaultfd()``, as fault addresses subsequently obtained by reading
  45. the file descriptor will be untagged, which may otherwise confuse
  46. tag-unaware programs.
  47. NOTE: This behaviour changed in v5.14 and so some earlier kernels may
  48. incorrectly accept valid tagged pointers for this system call.
  49. 2. User addresses accessed by the kernel (e.g. ``write()``). This ABI
  50. relaxation is disabled by default and the application thread needs to
  51. explicitly enable it via ``prctl()`` as follows:
  52. - ``PR_SET_TAGGED_ADDR_CTRL``: enable or disable the AArch64 Tagged
  53. Address ABI for the calling thread.
  54. The ``(unsigned int) arg2`` argument is a bit mask describing the
  55. control mode used:
  56. - ``PR_TAGGED_ADDR_ENABLE``: enable AArch64 Tagged Address ABI.
  57. Default status is disabled.
  58. Arguments ``arg3``, ``arg4``, and ``arg5`` must be 0.
  59. - ``PR_GET_TAGGED_ADDR_CTRL``: get the status of the AArch64 Tagged
  60. Address ABI for the calling thread.
  61. Arguments ``arg2``, ``arg3``, ``arg4``, and ``arg5`` must be 0.
  62. The ABI properties described above are thread-scoped, inherited on
  63. clone() and fork() and cleared on exec().
  64. Calling ``prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE, 0, 0, 0)``
  65. returns ``-EINVAL`` if the AArch64 Tagged Address ABI is globally
  66. disabled by ``sysctl abi.tagged_addr_disabled=1``. The default
  67. ``sysctl abi.tagged_addr_disabled`` configuration is 0.
  68. When the AArch64 Tagged Address ABI is enabled for a thread, the
  69. following behaviours are guaranteed:
  70. - All syscalls except the cases mentioned in section 3 can accept any
  71. valid tagged pointer.
  72. - The syscall behaviour is undefined for invalid tagged pointers: it may
  73. result in an error code being returned, a (fatal) signal being raised,
  74. or other modes of failure.
  75. - The syscall behaviour for a valid tagged pointer is the same as for
  76. the corresponding untagged pointer.
  77. A definition of the meaning of tagged pointers on AArch64 can be found
  78. in Documentation/arm64/tagged-pointers.rst.
  79. 3. AArch64 Tagged Address ABI Exceptions
  80. -----------------------------------------
  81. The following system call parameters must be untagged regardless of the
  82. ABI relaxation:
  83. - ``prctl()`` other than pointers to user data either passed directly or
  84. indirectly as arguments to be accessed by the kernel.
  85. - ``ioctl()`` other than pointers to user data either passed directly or
  86. indirectly as arguments to be accessed by the kernel.
  87. - ``shmat()`` and ``shmdt()``.
  88. Any attempt to use non-zero tagged pointers may result in an error code
  89. being returned, a (fatal) signal being raised, or other modes of
  90. failure.
  91. 4. Example of correct usage
  92. ---------------------------
  93. .. code-block:: c
  94. #include <stdlib.h>
  95. #include <string.h>
  96. #include <unistd.h>
  97. #include <sys/mman.h>
  98. #include <sys/prctl.h>
  99. #define PR_SET_TAGGED_ADDR_CTRL 55
  100. #define PR_TAGGED_ADDR_ENABLE (1UL << 0)
  101. #define TAG_SHIFT 56
  102. int main(void)
  103. {
  104. int tbi_enabled = 0;
  105. unsigned long tag = 0;
  106. char *ptr;
  107. /* check/enable the tagged address ABI */
  108. if (!prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE, 0, 0, 0))
  109. tbi_enabled = 1;
  110. /* memory allocation */
  111. ptr = mmap(NULL, sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_WRITE,
  112. MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
  113. if (ptr == MAP_FAILED)
  114. return 1;
  115. /* set a non-zero tag if the ABI is available */
  116. if (tbi_enabled)
  117. tag = rand() & 0xff;
  118. ptr = (char *)((unsigned long)ptr | (tag << TAG_SHIFT));
  119. /* memory access to a tagged address */
  120. strcpy(ptr, "tagged pointer\n");
  121. /* syscall with a tagged pointer */
  122. write(1, ptr, strlen(ptr));
  123. return 0;
  124. }