]>
Commit | Line | Data |
---|---|---|
60533874 | 1 | /* AArch64 BTI functions. |
2b778ceb | 2 | Copyright (C) 2020-2021 Free Software Foundation, Inc. |
60533874 SD |
3 | |
4 | The GNU C Library is free software; you can redistribute it and/or | |
5 | modify it under the terms of the GNU Lesser General Public | |
6 | License as published by the Free Software Foundation; either | |
7 | version 2.1 of the License, or (at your option) any later version. | |
8 | ||
9 | The GNU C Library is distributed in the hope that it will be useful, | |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
12 | Lesser General Public License for more details. | |
13 | ||
14 | You should have received a copy of the GNU Lesser General Public | |
15 | License along with the GNU C Library; if not, see | |
16 | <https://www.gnu.org/licenses/>. */ | |
17 | ||
18 | #include <unistd.h> | |
19 | #include <errno.h> | |
20 | #include <libintl.h> | |
21 | #include <ldsodefs.h> | |
cd543b5e | 22 | #include <sys/mman.h> |
60533874 | 23 | |
cd543b5e SN |
24 | /* See elf/dl-load.h. */ |
25 | #ifndef MAP_COPY | |
26 | # define MAP_COPY (MAP_PRIVATE | MAP_DENYWRITE) | |
27 | #endif | |
28 | ||
29 | /* Enable BTI protection for MAP. */ | |
30 | ||
31 | void | |
32 | _dl_bti_protect (struct link_map *map, int fd) | |
60533874 | 33 | { |
8b8f616e | 34 | const size_t pagesz = GLRO(dl_pagesize); |
60533874 | 35 | const ElfW(Phdr) *phdr; |
60533874 SD |
36 | |
37 | for (phdr = map->l_phdr; phdr < &map->l_phdr[map->l_phnum]; ++phdr) | |
38 | if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_X)) | |
39 | { | |
8b8f616e SN |
40 | size_t vstart = ALIGN_DOWN (phdr->p_vaddr, pagesz); |
41 | size_t vend = ALIGN_UP (phdr->p_vaddr + phdr->p_filesz, pagesz); | |
42 | off_t off = ALIGN_DOWN (phdr->p_offset, pagesz); | |
43 | void *start = (void *) (vstart + map->l_addr); | |
44 | size_t len = vend - vstart; | |
7ebd1142 | 45 | |
8b8f616e | 46 | unsigned prot = PROT_EXEC | PROT_BTI; |
7ebd1142 SN |
47 | if (phdr->p_flags & PF_R) |
48 | prot |= PROT_READ; | |
49 | if (phdr->p_flags & PF_W) | |
50 | prot |= PROT_WRITE; | |
51 | ||
cd543b5e SN |
52 | if (fd == -1) |
53 | /* Ignore failures for kernel mapped binaries. */ | |
54 | __mprotect (start, len, prot); | |
55 | else | |
56 | map->l_mach.bti_fail = __mmap (start, len, prot, | |
57 | MAP_FIXED|MAP_COPY|MAP_FILE, | |
58 | fd, off) == MAP_FAILED; | |
60533874 | 59 | } |
60533874 SD |
60 | } |
61 | ||
cd543b5e SN |
62 | |
63 | static void | |
64 | bti_failed (struct link_map *l, const char *program) | |
65 | { | |
66 | if (program) | |
67 | _dl_fatal_printf ("%s: %s: failed to turn on BTI protection\n", | |
68 | program, l->l_name); | |
69 | else | |
70 | /* Note: the errno value is not available any more. */ | |
71 | _dl_signal_error (0, l->l_name, "dlopen", | |
72 | N_("failed to turn on BTI protection")); | |
73 | } | |
74 | ||
75 | ||
72739c79 | 76 | /* Enable BTI for L and its dependencies. */ |
60533874 SD |
77 | |
78 | void | |
79 | _dl_bti_check (struct link_map *l, const char *program) | |
80 | { | |
72739c79 SN |
81 | if (!GLRO(dl_aarch64_cpu_features).bti) |
82 | return; | |
83 | ||
cd543b5e SN |
84 | if (l->l_mach.bti_fail) |
85 | bti_failed (l, program); | |
72739c79 SN |
86 | |
87 | unsigned int i = l->l_searchlist.r_nlist; | |
88 | while (i-- > 0) | |
89 | { | |
90 | struct link_map *dep = l->l_initfini[i]; | |
cd543b5e SN |
91 | if (dep->l_mach.bti_fail) |
92 | bti_failed (dep, program); | |
72739c79 | 93 | } |
60533874 | 94 | } |