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