Merge tag 'pwm/for-5.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry...
[linux-2.6-microblaze.git] / arch / arm64 / kernel / mte.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2020 ARM Ltd.
4  */
5
6 #include <linux/bitops.h>
7 #include <linux/kernel.h>
8 #include <linux/mm.h>
9 #include <linux/prctl.h>
10 #include <linux/sched.h>
11 #include <linux/sched/mm.h>
12 #include <linux/string.h>
13 #include <linux/swap.h>
14 #include <linux/swapops.h>
15 #include <linux/thread_info.h>
16 #include <linux/types.h>
17 #include <linux/uio.h>
18
19 #include <asm/barrier.h>
20 #include <asm/cpufeature.h>
21 #include <asm/mte.h>
22 #include <asm/mte-kasan.h>
23 #include <asm/ptrace.h>
24 #include <asm/sysreg.h>
25
26 u64 gcr_kernel_excl __ro_after_init;
27
28 static bool report_fault_once = true;
29
30 static void mte_sync_page_tags(struct page *page, pte_t *ptep, bool check_swap)
31 {
32         pte_t old_pte = READ_ONCE(*ptep);
33
34         if (check_swap && is_swap_pte(old_pte)) {
35                 swp_entry_t entry = pte_to_swp_entry(old_pte);
36
37                 if (!non_swap_entry(entry) && mte_restore_tags(entry, page))
38                         return;
39         }
40
41         page_kasan_tag_reset(page);
42         /*
43          * We need smp_wmb() in between setting the flags and clearing the
44          * tags because if another thread reads page->flags and builds a
45          * tagged address out of it, there is an actual dependency to the
46          * memory access, but on the current thread we do not guarantee that
47          * the new page->flags are visible before the tags were updated.
48          */
49         smp_wmb();
50         mte_clear_page_tags(page_address(page));
51 }
52
53 void mte_sync_tags(pte_t *ptep, pte_t pte)
54 {
55         struct page *page = pte_page(pte);
56         long i, nr_pages = compound_nr(page);
57         bool check_swap = nr_pages == 1;
58
59         /* if PG_mte_tagged is set, tags have already been initialised */
60         for (i = 0; i < nr_pages; i++, page++) {
61                 if (!test_and_set_bit(PG_mte_tagged, &page->flags))
62                         mte_sync_page_tags(page, ptep, check_swap);
63         }
64 }
65
66 int memcmp_pages(struct page *page1, struct page *page2)
67 {
68         char *addr1, *addr2;
69         int ret;
70
71         addr1 = page_address(page1);
72         addr2 = page_address(page2);
73         ret = memcmp(addr1, addr2, PAGE_SIZE);
74
75         if (!system_supports_mte() || ret)
76                 return ret;
77
78         /*
79          * If the page content is identical but at least one of the pages is
80          * tagged, return non-zero to avoid KSM merging. If only one of the
81          * pages is tagged, set_pte_at() may zero or change the tags of the
82          * other page via mte_sync_tags().
83          */
84         if (test_bit(PG_mte_tagged, &page1->flags) ||
85             test_bit(PG_mte_tagged, &page2->flags))
86                 return addr1 != addr2;
87
88         return ret;
89 }
90
91 u8 mte_get_mem_tag(void *addr)
92 {
93         if (!system_supports_mte())
94                 return 0xFF;
95
96         asm(__MTE_PREAMBLE "ldg %0, [%0]"
97             : "+r" (addr));
98
99         return mte_get_ptr_tag(addr);
100 }
101
102 u8 mte_get_random_tag(void)
103 {
104         void *addr;
105
106         if (!system_supports_mte())
107                 return 0xFF;
108
109         asm(__MTE_PREAMBLE "irg %0, %0"
110             : "+r" (addr));
111
112         return mte_get_ptr_tag(addr);
113 }
114
115 void *mte_set_mem_tag_range(void *addr, size_t size, u8 tag)
116 {
117         void *ptr = addr;
118
119         if ((!system_supports_mte()) || (size == 0))
120                 return addr;
121
122         /* Make sure that size is MTE granule aligned. */
123         WARN_ON(size & (MTE_GRANULE_SIZE - 1));
124
125         /* Make sure that the address is MTE granule aligned. */
126         WARN_ON((u64)addr & (MTE_GRANULE_SIZE - 1));
127
128         tag = 0xF0 | tag;
129         ptr = (void *)__tag_set(ptr, tag);
130
131         mte_assign_mem_tag_range(ptr, size);
132
133         return ptr;
134 }
135
136 void mte_init_tags(u64 max_tag)
137 {
138         static bool gcr_kernel_excl_initialized;
139
140         if (!gcr_kernel_excl_initialized) {
141                 /*
142                  * The format of the tags in KASAN is 0xFF and in MTE is 0xF.
143                  * This conversion extracts an MTE tag from a KASAN tag.
144                  */
145                 u64 incl = GENMASK(FIELD_GET(MTE_TAG_MASK >> MTE_TAG_SHIFT,
146                                              max_tag), 0);
147
148                 gcr_kernel_excl = ~incl & SYS_GCR_EL1_EXCL_MASK;
149                 gcr_kernel_excl_initialized = true;
150         }
151
152         /* Enable the kernel exclude mask for random tags generation. */
153         write_sysreg_s(SYS_GCR_EL1_RRND | gcr_kernel_excl, SYS_GCR_EL1);
154 }
155
156 void mte_enable_kernel(void)
157 {
158         /* Enable MTE Sync Mode for EL1. */
159         sysreg_clear_set(sctlr_el1, SCTLR_ELx_TCF_MASK, SCTLR_ELx_TCF_SYNC);
160         isb();
161 }
162
163 void mte_set_report_once(bool state)
164 {
165         WRITE_ONCE(report_fault_once, state);
166 }
167
168 bool mte_report_once(void)
169 {
170         return READ_ONCE(report_fault_once);
171 }
172
173 static void update_sctlr_el1_tcf0(u64 tcf0)
174 {
175         /* ISB required for the kernel uaccess routines */
176         sysreg_clear_set(sctlr_el1, SCTLR_EL1_TCF0_MASK, tcf0);
177         isb();
178 }
179
180 static void set_sctlr_el1_tcf0(u64 tcf0)
181 {
182         /*
183          * mte_thread_switch() checks current->thread.sctlr_tcf0 as an
184          * optimisation. Disable preemption so that it does not see
185          * the variable update before the SCTLR_EL1.TCF0 one.
186          */
187         preempt_disable();
188         current->thread.sctlr_tcf0 = tcf0;
189         update_sctlr_el1_tcf0(tcf0);
190         preempt_enable();
191 }
192
193 static void update_gcr_el1_excl(u64 excl)
194 {
195
196         /*
197          * Note that the mask controlled by the user via prctl() is an
198          * include while GCR_EL1 accepts an exclude mask.
199          * No need for ISB since this only affects EL0 currently, implicit
200          * with ERET.
201          */
202         sysreg_clear_set_s(SYS_GCR_EL1, SYS_GCR_EL1_EXCL_MASK, excl);
203 }
204
205 static void set_gcr_el1_excl(u64 excl)
206 {
207         current->thread.gcr_user_excl = excl;
208
209         /*
210          * SYS_GCR_EL1 will be set to current->thread.gcr_user_excl value
211          * by mte_set_user_gcr() in kernel_exit,
212          */
213 }
214
215 void flush_mte_state(void)
216 {
217         if (!system_supports_mte())
218                 return;
219
220         /* clear any pending asynchronous tag fault */
221         dsb(ish);
222         write_sysreg_s(0, SYS_TFSRE0_EL1);
223         clear_thread_flag(TIF_MTE_ASYNC_FAULT);
224         /* disable tag checking */
225         set_sctlr_el1_tcf0(SCTLR_EL1_TCF0_NONE);
226         /* reset tag generation mask */
227         set_gcr_el1_excl(SYS_GCR_EL1_EXCL_MASK);
228 }
229
230 void mte_thread_switch(struct task_struct *next)
231 {
232         if (!system_supports_mte())
233                 return;
234
235         /* avoid expensive SCTLR_EL1 accesses if no change */
236         if (current->thread.sctlr_tcf0 != next->thread.sctlr_tcf0)
237                 update_sctlr_el1_tcf0(next->thread.sctlr_tcf0);
238 }
239
240 void mte_suspend_exit(void)
241 {
242         if (!system_supports_mte())
243                 return;
244
245         update_gcr_el1_excl(gcr_kernel_excl);
246 }
247
248 long set_mte_ctrl(struct task_struct *task, unsigned long arg)
249 {
250         u64 tcf0;
251         u64 gcr_excl = ~((arg & PR_MTE_TAG_MASK) >> PR_MTE_TAG_SHIFT) &
252                        SYS_GCR_EL1_EXCL_MASK;
253
254         if (!system_supports_mte())
255                 return 0;
256
257         switch (arg & PR_MTE_TCF_MASK) {
258         case PR_MTE_TCF_NONE:
259                 tcf0 = SCTLR_EL1_TCF0_NONE;
260                 break;
261         case PR_MTE_TCF_SYNC:
262                 tcf0 = SCTLR_EL1_TCF0_SYNC;
263                 break;
264         case PR_MTE_TCF_ASYNC:
265                 tcf0 = SCTLR_EL1_TCF0_ASYNC;
266                 break;
267         default:
268                 return -EINVAL;
269         }
270
271         if (task != current) {
272                 task->thread.sctlr_tcf0 = tcf0;
273                 task->thread.gcr_user_excl = gcr_excl;
274         } else {
275                 set_sctlr_el1_tcf0(tcf0);
276                 set_gcr_el1_excl(gcr_excl);
277         }
278
279         return 0;
280 }
281
282 long get_mte_ctrl(struct task_struct *task)
283 {
284         unsigned long ret;
285         u64 incl = ~task->thread.gcr_user_excl & SYS_GCR_EL1_EXCL_MASK;
286
287         if (!system_supports_mte())
288                 return 0;
289
290         ret = incl << PR_MTE_TAG_SHIFT;
291
292         switch (task->thread.sctlr_tcf0) {
293         case SCTLR_EL1_TCF0_NONE:
294                 ret |= PR_MTE_TCF_NONE;
295                 break;
296         case SCTLR_EL1_TCF0_SYNC:
297                 ret |= PR_MTE_TCF_SYNC;
298                 break;
299         case SCTLR_EL1_TCF0_ASYNC:
300                 ret |= PR_MTE_TCF_ASYNC;
301                 break;
302         }
303
304         return ret;
305 }
306
307 /*
308  * Access MTE tags in another process' address space as given in mm. Update
309  * the number of tags copied. Return 0 if any tags copied, error otherwise.
310  * Inspired by __access_remote_vm().
311  */
312 static int __access_remote_tags(struct mm_struct *mm, unsigned long addr,
313                                 struct iovec *kiov, unsigned int gup_flags)
314 {
315         struct vm_area_struct *vma;
316         void __user *buf = kiov->iov_base;
317         size_t len = kiov->iov_len;
318         int ret;
319         int write = gup_flags & FOLL_WRITE;
320
321         if (!access_ok(buf, len))
322                 return -EFAULT;
323
324         if (mmap_read_lock_killable(mm))
325                 return -EIO;
326
327         while (len) {
328                 unsigned long tags, offset;
329                 void *maddr;
330                 struct page *page = NULL;
331
332                 ret = get_user_pages_remote(mm, addr, 1, gup_flags, &page,
333                                             &vma, NULL);
334                 if (ret <= 0)
335                         break;
336
337                 /*
338                  * Only copy tags if the page has been mapped as PROT_MTE
339                  * (PG_mte_tagged set). Otherwise the tags are not valid and
340                  * not accessible to user. Moreover, an mprotect(PROT_MTE)
341                  * would cause the existing tags to be cleared if the page
342                  * was never mapped with PROT_MTE.
343                  */
344                 if (!(vma->vm_flags & VM_MTE)) {
345                         ret = -EOPNOTSUPP;
346                         put_page(page);
347                         break;
348                 }
349                 WARN_ON_ONCE(!test_bit(PG_mte_tagged, &page->flags));
350
351                 /* limit access to the end of the page */
352                 offset = offset_in_page(addr);
353                 tags = min(len, (PAGE_SIZE - offset) / MTE_GRANULE_SIZE);
354
355                 maddr = page_address(page);
356                 if (write) {
357                         tags = mte_copy_tags_from_user(maddr + offset, buf, tags);
358                         set_page_dirty_lock(page);
359                 } else {
360                         tags = mte_copy_tags_to_user(buf, maddr + offset, tags);
361                 }
362                 put_page(page);
363
364                 /* error accessing the tracer's buffer */
365                 if (!tags)
366                         break;
367
368                 len -= tags;
369                 buf += tags;
370                 addr += tags * MTE_GRANULE_SIZE;
371         }
372         mmap_read_unlock(mm);
373
374         /* return an error if no tags copied */
375         kiov->iov_len = buf - kiov->iov_base;
376         if (!kiov->iov_len) {
377                 /* check for error accessing the tracee's address space */
378                 if (ret <= 0)
379                         return -EIO;
380                 else
381                         return -EFAULT;
382         }
383
384         return 0;
385 }
386
387 /*
388  * Copy MTE tags in another process' address space at 'addr' to/from tracer's
389  * iovec buffer. Return 0 on success. Inspired by ptrace_access_vm().
390  */
391 static int access_remote_tags(struct task_struct *tsk, unsigned long addr,
392                               struct iovec *kiov, unsigned int gup_flags)
393 {
394         struct mm_struct *mm;
395         int ret;
396
397         mm = get_task_mm(tsk);
398         if (!mm)
399                 return -EPERM;
400
401         if (!tsk->ptrace || (current != tsk->parent) ||
402             ((get_dumpable(mm) != SUID_DUMP_USER) &&
403              !ptracer_capable(tsk, mm->user_ns))) {
404                 mmput(mm);
405                 return -EPERM;
406         }
407
408         ret = __access_remote_tags(mm, addr, kiov, gup_flags);
409         mmput(mm);
410
411         return ret;
412 }
413
414 int mte_ptrace_copy_tags(struct task_struct *child, long request,
415                          unsigned long addr, unsigned long data)
416 {
417         int ret;
418         struct iovec kiov;
419         struct iovec __user *uiov = (void __user *)data;
420         unsigned int gup_flags = FOLL_FORCE;
421
422         if (!system_supports_mte())
423                 return -EIO;
424
425         if (get_user(kiov.iov_base, &uiov->iov_base) ||
426             get_user(kiov.iov_len, &uiov->iov_len))
427                 return -EFAULT;
428
429         if (request == PTRACE_POKEMTETAGS)
430                 gup_flags |= FOLL_WRITE;
431
432         /* align addr to the MTE tag granule */
433         addr &= MTE_GRANULE_MASK;
434
435         ret = access_remote_tags(child, addr, &kiov, gup_flags);
436         if (!ret)
437                 ret = put_user(kiov.iov_len, &uiov->iov_len);
438
439         return ret;
440 }