xref: /third_party/musl/porting/linux/user/ldso/cfi.c (revision 570af302)
1/*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#define _GNU_SOURCE
17#include <sys/mman.h>
18#include <sys/prctl.h>
19#include "cfi.h"
20#include "ld_log.h"
21#include "namespace.h"
22
23/* This module provides support for LLVM CFI Cross-DSO by implementing the __cfi_slowpath() and __cfi_slowpath_diag()
24 * functions. These two functions will be called before visiting other dso's resources. The responsibility is to
25 * calculate the __cfi_check() of the target dso, and call it. So use CFI shadow and shadow value to store the
26 * relationship between dso and its __cfi_check addr while loading a dso. CFI shadow is an array which stores shadow
27 * values. Shadow value is used to store the relationship. A shadow value can map 1 LIBRARY_ALIGNMENT memory range. So
28 * each dso will be mapped to one or more shadow values in the CFI shadow, this depends on the address range of the
29 * dso.
30 * There are 3 types for shadow value:
31 * - invalid(0) : the target addr does not belongs to any loaded dso.
32 * - uncheck(1) : this LIBRARY_ALIGNMENT memory range belongs to a dso but it is no need to do the CFI check.
33 * - valid(2 - 0xFFFF) : this LIBRARY_ALIGNMENT memory range belongs to a dso and need to do the CFI check.
34 * The valid shadow value records the distance from the end of a LIBRARY_ALIGNMENT memory range to the __cfi_check addr
35 * of the dso (The unit is 4096, because the __cfi_check is aligned with 4096).
36 * The valid shadow value is calculated as below:
37 *      sv = (AlignUp(__cfi_check, LIBRARY_ALIGNMENT) - __cfi_check + N * LIBRARY_ALIGNMENT) / 4096 + 2;
38 *
39 *      N   : starts at 0, is the index of LIBRARY_ALIGNMENT memory range that belongs to a dso.
40 *      + 2 : to avoid conflict with invalid and uncheck shadow value.
41 *
42 * Below is a example for calculating shadow values of a dso.
43 *                                               liba.so
44 *                                                /\
45 *           /''''''''''''''''''''''''''''''''''''  '''''''''''''''''''''''''''''''''''''\
46 *           0x40000  __cfi_check addr = 0x42000               0x80000                  0xA0000                0xC0000
47 *           +---------^----------------------------------------^-------------------------^-------------------------+
48 *  Memory   |         |                                        |                         |                         |
49 *           +------------------------------------------------------------------------------------------------------+
50 *           \........... LIBRARY_ALIGNMENT ..................../\........... LIBRARY_ALIGNMENT ..................../
51 *             \                                              /                                               /
52 *               \                                          /                                          /
53 *                 \                                      /                                     /
54 *                   \                                  /                                /
55 *                     \                              /                            /
56 *            +-----------------------------------------------------------------------------------------------------+
57 * CFI shadow |  invalid |           sv1              |           sv2              |            invalid             |
58 *            +-----------------------------------------------------------------------------------------------------+
59 *                          sv1 = (0x80000 - 0x42000 + 0 * LIBRARY_ALIGNMENT) / 4096 + 2 = 64
60 *                          sv2 = (0x80000 - 0x42000 + 1 * LIBRARY_ALIGNMENT) / 4096 + 2 = 126
61 *
62 * Calculating the __cfi_check address is a reverse process:
63 * - First align up the target addr with LIBRARY_ALIGNMENT to locate the corresponding shadow value.
64 * - Then calculate the __cfi_check addr.
65 *
66 * In order for the algorithm to work well, the start addr of each dso should be aligned with LIBRARY_ALIGNMENT. */
67
68#define MAX(a,b)                (((a) > (b)) ? (a) : (b))
69#define MIN(a,b)                (((a) < (b)) ? (a) : (b))
70#define ALIGN_UP(a, b)          (((a) + (b) - 1) & -(b))
71#define ALIGN_DOWN(a, b)        ((a) & -(b))
72#if DL_FDPIC
73#define LADDR(p, v)             laddr((p), (v))
74#else
75#define LADDR(p, v)             (void *)((p)->base + (v))
76#endif
77
78/* Function ptr for __cfi_check() */
79typedef int (*cfi_check_t)(uint64_t, void *, void *);
80
81static const uintptr_t shadow_granularity = LIBRARY_ALIGNMENT_BITS;
82static const uintptr_t cfi_check_granularity = 12;
83static const uintptr_t shadow_alignment = 1UL << shadow_granularity;
84static uintptr_t shadow_size = 0;
85/* Start addr of the CFI shadow */
86static char *cfi_shadow_start = NULL;
87/* List head of all the DSOs loaded by the process */
88static struct dso *dso_list_head = NULL;
89static struct dso *pldso = NULL;
90
91/* Shadow value */
92/* The related shadow value(s) will be set to `sv_invalid` when:
93 * - init CFI shadow.
94 * - removing a dso. */
95static const uint16_t sv_invalid = 0;
96/* The related shadow value(s) will be set to `sv_uncheck` if:
97 * - the DSO does not enable CFI Cross-Dso.
98 * - the DSO enabled CFI Cross-Dso, but this DSO is larger than 16G, for the part of the dso that exceeds 16G,
99 *   its shadow value will be set to `sv_uncheck`. */
100static const uint16_t sv_uncheck = 1;
101/* If a DSO enabled CFI Cross-Dso, the DSO's shadow value should be valid. Because of the defination of `sv_invalid`
102 * and `sv_unchecked`, the valid shadow value should be at least 2. */
103static const uint16_t sv_valid_min = 2;
104
105#if defined(__LP64__)
106static const uintptr_t max_target_addr = 0xffffffffffff;
107#else
108static const uintptr_t max_target_addr = 0xffffffff;
109#endif
110
111/* Create a cfi shadow */
112static int create_cfi_shadow(void);
113
114/* Map dsos to CFI shadow */
115static int add_dso_to_cfi_shadow(struct dso *dso);
116static int fill_shadow_value_to_shadow(uintptr_t begin, uintptr_t end, uintptr_t cfi_check, uint16_t type);
117
118/* Find the __cfi_check() of target dso and call it */
119void __cfi_slowpath(uint64_t call_site_type_id, void *func_ptr);
120void __cfi_slowpath_diag(uint64_t call_site_type_id, void *func_ptr, void *diag_data);
121
122static inline uintptr_t addr_to_offset(uintptr_t addr, int bits)
123{
124    /* Convert addr to CFI shadow offset.
125     * Shift left 1 bit because the shadow value is uint16_t. */
126    return (addr >> bits) << 1;
127}
128
129static struct symdef find_cfi_check_sym(struct dso *p)
130{
131    LD_LOGD("[CFI] [%{public}s] start!\n", __FUNCTION__);
132
133    struct verinfo verinfo = { .s = "__cfi_check", .v = "", .use_vna_hash = false };
134    struct sym_info_pair s_info_p = gnu_hash(verinfo.s);
135    return find_sym_impl(p, &verinfo, s_info_p, 0, p->namespace);
136}
137
138static int is_addr_in_ldso(size_t a)
139{
140    size_t i = 0;
141    if (DL_FDPIC) {
142        i = count_syms(pldso);
143        if (a - (size_t)pldso->funcdescs < i * sizeof(*pldso->funcdescs))
144            return 1;
145    }
146    if (DL_FDPIC && pldso->loadmap) {
147        for (i = 0; i < pldso->loadmap->nsegs; i++) {
148            if (a-pldso->loadmap->segs[i].p_vaddr
149                < pldso->loadmap->segs[i].p_memsz)
150                return 1;
151        }
152    } else {
153        Phdr *ph = pldso->phdr;
154        size_t phcnt = pldso->phnum;
155        size_t entsz = pldso->phentsize;
156        size_t base = (size_t)pldso->base;
157        for (; phcnt--; ph = (void *)((char *)ph + entsz)) {
158            if (ph->p_type != PT_LOAD) continue;
159            if (a - base - ph->p_vaddr < ph->p_memsz)
160                return 1;
161        }
162        if (a - (size_t)pldso->map < pldso->map_len)
163            return 0;
164    }
165    return 0;
166}
167
168static uintptr_t get_cfi_check_addr(uint16_t value, void* func_ptr)
169{
170    LD_LOGD("[CFI] [%{public}s] start!\n", __FUNCTION__);
171
172    uintptr_t addr = (uintptr_t)func_ptr;
173    uintptr_t aligned_addr = ALIGN_DOWN(addr, shadow_alignment) + shadow_alignment;
174    uintptr_t cfi_check_func_addr = aligned_addr - ((uintptr_t)(value - sv_valid_min) << cfi_check_granularity);
175#ifdef __arm__
176    LD_LOGD("[CFI] [%{public}s] __arm__ defined!\n", __FUNCTION__);
177    cfi_check_func_addr++;
178#endif
179    LD_LOGD("[CFI] [%{public}s] cfi_check_func_addr[%{public}p] in dso[%{public}s]\n",
180            __FUNCTION__, cfi_check_func_addr, ((struct dso *)addr2dso((size_t)cfi_check_func_addr))->name);
181
182    return cfi_check_func_addr;
183}
184
185static inline void cfi_slowpath_common(uint64_t call_site_type_id, void *func_ptr, void *diag_data)
186{
187    uint16_t value = sv_invalid;
188
189    if (func_ptr == NULL) {
190        return;
191    }
192
193#if defined(__aarch64__)
194    LD_LOGD("[CFI] [%{public}s] __aarch64__ defined!\n", __FUNCTION__);
195    uintptr_t addr = (uintptr_t)func_ptr & ((1ULL << 56) - 1);
196#else
197    LD_LOGD("[CFI] [%{public}s] __aarch64__ not defined!\n", __FUNCTION__);
198    uintptr_t addr = func_ptr;
199#endif
200
201    /* Get shadow value */
202    uintptr_t offset = addr_to_offset(addr, shadow_granularity);
203
204    if (cfi_shadow_start == NULL) {
205        LD_LOGE("[CFI] [%{public}s] the cfi_shadow_start is null!\n", __FUNCTION__);
206        __builtin_trap();
207    }
208
209    if (offset > shadow_size) {
210        value = sv_invalid;
211    } else {
212        value = *((uint16_t*)(cfi_shadow_start + offset));
213    }
214    LD_LOGD("[CFI] [%{public}s] called from %{public}s to %{public}s func_ptr:0x%{public}p shadow value:%{public}d diag_data:0x%{public}p call_site_type_id[%{public}p.\n",
215             __FUNCTION__,
216             ((struct dso *)addr2dso((size_t)__builtin_return_address(0)))->name,
217             ((struct dso *)addr2dso((size_t)func_ptr))->name,
218             func_ptr, value, diag_data, call_site_type_id);
219
220    struct dso *dso = NULL;
221    switch (value)
222    {
223    case sv_invalid:
224        /* The ldso is an exception because it is loaded by kernel and is not mapped to the CFI shadow.
225         * Do not check it. */
226        if (is_addr_in_ldso((size_t)func_ptr)) {
227            LD_LOGI("[CFI] [%{public}s] uncheck for ldso\n", __FUNCTION__);
228            return;
229        }
230
231        dso = (struct dso *)addr2dso((size_t)__builtin_return_address(0));
232        if (dso == NULL) {
233            LD_LOGE("[CFI] [%{public}s] can not find the dso from address:%{public}p  func_ptr:0x%{public}p shadow value:%{public}d  call_site_type_id[%{public}p!\n",
234		__FUNCTION__,
235		(size_t)__builtin_return_address(0),
236		func_ptr, value, call_site_type_id);
237            __builtin_trap();
238        }
239        LD_LOGD("[CFI] [%{public}s] dso name[%{public}s]!\n", __FUNCTION__, dso->name);
240
241        struct symdef cfi_check_sym = find_cfi_check_sym(dso);
242        if (!cfi_check_sym.sym) {
243            LD_LOGE("[CFI] [%{public}s] can not find the __cfi_check in the dso: %{public}s func_ptr:0x%{public}p shadow value:%{public}d  call_site_type_id[%{public}p!\n",
244		__FUNCTION__,
245		((struct dso *)addr2dso((size_t)__builtin_return_address(0)))->name,
246		func_ptr, value, call_site_type_id);
247            __builtin_trap();
248        }
249        LD_LOGD("[CFI] [%{public}s] cfi_check addr[%{public}p]!\n", __FUNCTION__,
250                LADDR(cfi_check_sym.dso, cfi_check_sym.sym->st_value));
251        ((cfi_check_t)LADDR(cfi_check_sym.dso, cfi_check_sym.sym->st_value))(call_site_type_id, func_ptr, diag_data);
252        break;
253    case sv_uncheck:
254        break;
255    default:
256        ((cfi_check_t)get_cfi_check_addr(value, func_ptr))(call_site_type_id, func_ptr, diag_data);
257        break;
258    }
259
260    return;
261}
262
263int init_cfi_shadow(struct dso *dso_list, struct dso *ldso)
264{
265    LD_LOGD("[CFI] [%{public}s] start!\n", __FUNCTION__);
266
267    if (dso_list == NULL) {
268        LD_LOGW("[CFI] [%{public}s] has null param!\n", __FUNCTION__);
269        return CFI_SUCCESS;
270    }
271
272    /* Save the head node of dso list */
273    dso_list_head = dso_list;
274    pldso = ldso;
275
276    return map_dso_to_cfi_shadow(dso_list);
277}
278
279int map_dso_to_cfi_shadow(struct dso *dso)
280{
281    bool has_cfi_check = false;
282
283    if (dso == NULL) {
284        LD_LOGW("[CFI] [%{public}s] has null param!\n", __FUNCTION__);
285        return CFI_SUCCESS;
286    }
287
288    /* If the cfi shadow does not exist, create it and map all the dsos and its dependents to it. */
289    if (cfi_shadow_start == NULL) {
290        /* Find __cfi_check symbol in dso list */
291        for (struct dso *p = dso; p; p = p->next) {
292            if (find_cfi_check_sym(p).sym) {
293                LD_LOGD("[CFI] [%{public}s] find __cfi_check function in dso %{public}s!\n", __FUNCTION__, p->name);
294                has_cfi_check = true;
295                break;
296            }
297        }
298
299        if (has_cfi_check) {
300            if (create_cfi_shadow() == CFI_FAILED) {
301                LD_LOGE("[CFI] [%{public}s] create cfi shadow failed!\n", __FUNCTION__);
302                return CFI_FAILED;
303            }
304            add_dso_to_cfi_shadow(dso_list_head);
305            prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, cfi_shadow_start, shadow_size, "cfi_shadow:musl");
306        }
307    /* If the cfi shadow exists, map the current dso and its dependents to it. */
308    } else {
309        add_dso_to_cfi_shadow(dso);
310        prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, cfi_shadow_start, shadow_size, "cfi_shadow:musl");
311    }
312
313    return CFI_SUCCESS;
314}
315
316void unmap_dso_from_cfi_shadow(struct dso *dso)
317{
318    if (dso == NULL) {
319        LD_LOGD("[CFI] [%{public}s] has null param!\n", __FUNCTION__);
320        return;
321    }
322
323    LD_LOGD("[CFI] [%{public}s] unmap dso %{public}s from shadow!\n", __FUNCTION__, dso->name);
324
325    if (cfi_shadow_start == NULL)
326        return;
327
328    if (dso->map == 0 || dso->map_len == 0)
329        return;
330
331    if (dso->is_mapped_to_shadow == false)
332        return;
333
334    /* Set the dso's shadow value as invalid. */
335    fill_shadow_value_to_shadow(dso->map, dso->map + dso->map_len, 0, sv_invalid);
336    dso->is_mapped_to_shadow = false;
337    prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, cfi_shadow_start, shadow_size, "cfi_shadow:musl");
338
339    return;
340}
341
342static int create_cfi_shadow(void)
343{
344    LD_LOGD("[CFI] [%{public}s] start!\n", __FUNCTION__);
345
346    /* Each process can load up to (max_target_addr >> shadow_granularity) dsos. Shift left 1 bit because the shadow
347     * value is uint16_t. The size passed to mmap() should be aligned with 4096, so shadow_size should be aligned. */
348    shadow_size = ALIGN_UP(((max_target_addr >> shadow_granularity) << 1), PAGE_SIZE);
349
350    uintptr_t *mmap_addr = mmap(NULL, shadow_size, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0);
351
352    if (mmap_addr == MAP_FAILED) {
353        LD_LOGE("[CFI] [%{public}s] mmap failed!\n", __FUNCTION__);
354        return CFI_FAILED;
355    }
356
357    cfi_shadow_start = (char*)mmap_addr;
358    LD_LOGD("[CFI] [%{public}s] the cfi_shadow_start addr is %{public}p!\n", __FUNCTION__, cfi_shadow_start);
359
360    return CFI_SUCCESS;
361}
362
363static int add_dso_to_cfi_shadow(struct dso *dso)
364{
365    LD_LOGD("[CFI] [%{public}s] start with %{public}s !\n", __FUNCTION__, dso->name);
366    for (struct dso *p = dso; p; p = p->next) {
367        LD_LOGD("[CFI] [%{public}s] adding %{public}s to cfi shadow!\n", __FUNCTION__, p->name);
368        if (p->map == 0 || p->map_len == 0) {
369            LD_LOGW("[CFI] [%{public}s] the dso has no data! map[%{public}p] map_len[0x%{public}x]\n",
370                    __FUNCTION__, p->map, p->map_len);
371            continue;
372        }
373
374        if (p->is_mapped_to_shadow == true) {
375            LD_LOGW("[CFI] [%{public}s] %{public}s is already in shadow!\n", __FUNCTION__, p->name);
376            continue;
377        }
378
379        struct symdef cfi_check_sym = find_cfi_check_sym(p);
380        /* If the dso doesn't have __cfi_check(), set it's shadow value unchecked. */
381        if (!cfi_check_sym.sym) {
382            LD_LOGD("[CFI] [%{public}s] %{public}s has no __cfi_check()!\n", __FUNCTION__, p->name);
383            if (fill_shadow_value_to_shadow(p->map, p->map + p->map_len, 0, sv_uncheck) == CFI_FAILED) {
384                LD_LOGE("[CFI] [%{public}s] add dso to cfi shadow failed!\n", __FUNCTION__);
385                return CFI_FAILED;
386            }
387        /* If the dso has __cfi_check(), set it's shadow value valid. */
388        } else {
389            LD_LOGD("[CFI] [%{public}s] %{public}s has __cfi_check()!\n", __FUNCTION__, p->name);
390            uintptr_t end = p->map + p->map_len;
391            uintptr_t cfi_check = LADDR(cfi_check_sym.dso, cfi_check_sym.sym->st_value);
392
393            if (cfi_check == 0) {
394                LD_LOGE("[CFI] [%{public}s] %{public}s has null cfi_check func!\n", __FUNCTION__, p->name);
395                return CFI_FAILED;
396            }
397            if (fill_shadow_value_to_shadow(p->map, end, cfi_check, sv_valid_min) == CFI_FAILED) {
398                LD_LOGE("[CFI] [%{public}s] add %{public}s to cfi shadow failed!\n", __FUNCTION__, p->name);
399                return CFI_FAILED;
400            }
401        }
402        p->is_mapped_to_shadow = true;
403        LD_LOGD("[CFI] [%{public}s] add %{public}s to cfi shadow succeed.\n", __FUNCTION__, p->name);
404    }
405    LD_LOGD("[CFI] [%{public}s] %{public}s done.\n", __FUNCTION__, dso->name);
406
407    return CFI_SUCCESS;
408}
409
410static int fill_shadow_value_to_shadow(uintptr_t begin, uintptr_t end, uintptr_t cfi_check, uint16_t type)
411{
412    LD_LOGD("[CFI] [%{public}s] begin[%{public}x] end[%{public}x] cfi_check[%{public}x] type[%{public}x]!\n",
413            __FUNCTION__, begin, end, cfi_check, type);
414
415    /* To ensure the atomicity of the CFI shadow operation, we create a temp_shadow, write the shadow value to
416     * the temp_shadow, and then write it back to the CFI shadow by mremap(). */
417    begin = ALIGN_DOWN(MAX(begin, cfi_check), shadow_alignment);
418    char* shadow_begin = cfi_shadow_start + addr_to_offset(begin, LIBRARY_ALIGNMENT_BITS);
419    char* shadow_end = (char*)(((uint16_t*)(cfi_shadow_start + addr_to_offset(end - 1, LIBRARY_ALIGNMENT_BITS))) + 1);
420    char* aligned_shadow_begin = (char*)ALIGN_DOWN((uintptr_t)shadow_begin, PAGE_SIZE);
421    char* aligned_shadow_end = (char*)ALIGN_UP((uintptr_t)shadow_end, PAGE_SIZE);
422
423    uint16_t tmp_shadow_size = aligned_shadow_end - aligned_shadow_begin;
424    uint16_t offset_begin = shadow_begin - aligned_shadow_begin;
425    uint16_t offset_end = shadow_end - aligned_shadow_begin;
426
427    char* tmp_shadow_start = (char*)mmap(NULL, tmp_shadow_size,
428        PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
429
430    if (tmp_shadow_start == MAP_FAILED) {
431        LD_LOGE("[CFI] [%{public}s] mmap failed!\n", __FUNCTION__);
432        return CFI_FAILED;
433    }
434
435    LD_LOGD("[CFI] [%{public}s] tmp_shadow_start is %{public}p\t tmp_shadow_size is 0x%{public}x!\n",
436        __FUNCTION__, tmp_shadow_start, tmp_shadow_size);
437    memcpy(tmp_shadow_start, aligned_shadow_begin, offset_begin);
438    memcpy(tmp_shadow_start + offset_end, shadow_end, aligned_shadow_end - shadow_end);
439
440    /* If the dso has __cfi_check(), calculate valid shadow value */
441    if (type == sv_valid_min) {
442#ifdef __arm__
443        uint16_t shadow_value_begin = ((begin + shadow_alignment - (cfi_check - 1))
444            >> cfi_check_granularity) + sv_valid_min;
445#else
446        uint16_t shadow_value_begin = ((begin + shadow_alignment - cfi_check)
447            >> cfi_check_granularity) + sv_valid_min;
448#endif
449        LD_LOGD("[CFI] [%{public}s] shadow_value_begin is 0x%{public}x!\n", __FUNCTION__, shadow_value_begin);
450        uint16_t shadow_value_step = 1 << (shadow_granularity - cfi_check_granularity);
451        uint16_t shadow_value = shadow_value_begin;
452
453        /* Set shadow_value */
454        for (uint16_t *shadow_addr = tmp_shadow_start + offset_begin;
455            shadow_addr != tmp_shadow_start + offset_end; shadow_addr++) {
456            /* If a dso is larger than 16G( = max_shadow_value * shadow_alignment / 1G),
457             * the excess is not checked. */
458            if (shadow_value < shadow_value_begin) {
459                *shadow_addr = sv_uncheck;
460                continue;
461            }
462            *shadow_addr = (*shadow_addr == sv_invalid) ? shadow_value : sv_uncheck;
463            shadow_value += shadow_value_step;
464        }
465    /* in these cases, shadow_value will always be sv_uncheck or sv_invalid */
466    } else if (type == sv_uncheck || type == sv_invalid) {
467        /* Set shadow_value */
468        for (uint16_t *shadow_addr = tmp_shadow_start + offset_begin;
469            shadow_addr != tmp_shadow_start + offset_end; shadow_addr++) {
470            *shadow_addr = type;
471        }
472    } else {
473        LD_LOGE("[CFI] [%{public}s] has error param!\n", __FUNCTION__);
474        munmap(tmp_shadow_start, tmp_shadow_size);
475        return CFI_FAILED;
476    }
477
478    mprotect(tmp_shadow_start, tmp_shadow_size, PROT_READ);
479    /* Remap temp_shadow to CFI shadow. */
480    uint16_t* mremap_addr = mremap(tmp_shadow_start, tmp_shadow_size, tmp_shadow_size,
481        MREMAP_MAYMOVE | MREMAP_FIXED, aligned_shadow_begin);
482
483    if (mremap_addr == MAP_FAILED) {
484        LD_LOGE("[CFI] [%{public}s] mremap failed!\n", __FUNCTION__);
485        munmap(tmp_shadow_start, tmp_shadow_size);
486        return CFI_FAILED;
487    }
488
489    LD_LOGD("[CFI] [%{public}s] fill completed!\n", __FUNCTION__);
490    return CFI_SUCCESS;
491}
492
493void __cfi_slowpath(uint64_t call_site_type_id, void *func_ptr)
494{
495    LD_LOGD("[CFI] [%{public}s] called from dso[%{public}s] to dso[%{public}s] func_ptr[%{public}p]\n",
496            __FUNCTION__,
497            ((struct dso *)addr2dso((size_t)__builtin_return_address(0)))->name,
498            ((struct dso *)addr2dso((size_t)func_ptr))->name,
499            func_ptr);
500
501    cfi_slowpath_common(call_site_type_id, func_ptr, NULL);
502    return;
503}
504
505void __cfi_slowpath_diag(uint64_t call_site_type_id, void *func_ptr, void *diag_data)
506{
507    LD_LOGD("[CFI] [%{public}s] called from dso[%{public}s] to dso[%{public}s] func_ptr[%{public}p]\n",
508            __FUNCTION__,
509            ((struct dso *)addr2dso((size_t)__builtin_return_address(0)))->name,
510            ((struct dso *)addr2dso((size_t)func_ptr))->name,
511            func_ptr);
512
513    cfi_slowpath_common(call_site_type_id, func_ptr, diag_data);
514    return;
515}
516