xref: /aosp_15_r20/bionic/linker/linker_cfi.cpp (revision 8d67ca893c1523eb926b9080dbe4e2ffd2a27ba1)
1*8d67ca89SAndroid Build Coastguard Worker /*
2*8d67ca89SAndroid Build Coastguard Worker  * Copyright (C) 2008 The Android Open Source Project
3*8d67ca89SAndroid Build Coastguard Worker  * All rights reserved.
4*8d67ca89SAndroid Build Coastguard Worker  *
5*8d67ca89SAndroid Build Coastguard Worker  * Redistribution and use in source and binary forms, with or without
6*8d67ca89SAndroid Build Coastguard Worker  * modification, are permitted provided that the following conditions
7*8d67ca89SAndroid Build Coastguard Worker  * are met:
8*8d67ca89SAndroid Build Coastguard Worker  *  * Redistributions of source code must retain the above copyright
9*8d67ca89SAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer.
10*8d67ca89SAndroid Build Coastguard Worker  *  * Redistributions in binary form must reproduce the above copyright
11*8d67ca89SAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer in
12*8d67ca89SAndroid Build Coastguard Worker  *    the documentation and/or other materials provided with the
13*8d67ca89SAndroid Build Coastguard Worker  *    distribution.
14*8d67ca89SAndroid Build Coastguard Worker  *
15*8d67ca89SAndroid Build Coastguard Worker  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16*8d67ca89SAndroid Build Coastguard Worker  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17*8d67ca89SAndroid Build Coastguard Worker  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18*8d67ca89SAndroid Build Coastguard Worker  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19*8d67ca89SAndroid Build Coastguard Worker  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20*8d67ca89SAndroid Build Coastguard Worker  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21*8d67ca89SAndroid Build Coastguard Worker  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22*8d67ca89SAndroid Build Coastguard Worker  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23*8d67ca89SAndroid Build Coastguard Worker  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24*8d67ca89SAndroid Build Coastguard Worker  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25*8d67ca89SAndroid Build Coastguard Worker  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26*8d67ca89SAndroid Build Coastguard Worker  * SUCH DAMAGE.
27*8d67ca89SAndroid Build Coastguard Worker  */
28*8d67ca89SAndroid Build Coastguard Worker 
29*8d67ca89SAndroid Build Coastguard Worker #include "linker_cfi.h"
30*8d67ca89SAndroid Build Coastguard Worker 
31*8d67ca89SAndroid Build Coastguard Worker #include "linker_debug.h"
32*8d67ca89SAndroid Build Coastguard Worker #include "linker_globals.h"
33*8d67ca89SAndroid Build Coastguard Worker #include "platform/bionic/page.h"
34*8d67ca89SAndroid Build Coastguard Worker 
35*8d67ca89SAndroid Build Coastguard Worker #include <sys/mman.h>
36*8d67ca89SAndroid Build Coastguard Worker #include <sys/prctl.h>
37*8d67ca89SAndroid Build Coastguard Worker #include <sys/types.h>
38*8d67ca89SAndroid Build Coastguard Worker #include <cstdint>
39*8d67ca89SAndroid Build Coastguard Worker 
40*8d67ca89SAndroid Build Coastguard Worker // Update shadow without making it writable by preparing the data on the side and mremap-ing it in
41*8d67ca89SAndroid Build Coastguard Worker // place.
42*8d67ca89SAndroid Build Coastguard Worker class ShadowWrite {
43*8d67ca89SAndroid Build Coastguard Worker   char* shadow_start;
44*8d67ca89SAndroid Build Coastguard Worker   char* shadow_end;
45*8d67ca89SAndroid Build Coastguard Worker   char* aligned_start;
46*8d67ca89SAndroid Build Coastguard Worker   char* aligned_end;
47*8d67ca89SAndroid Build Coastguard Worker   char* tmp_start;
48*8d67ca89SAndroid Build Coastguard Worker 
49*8d67ca89SAndroid Build Coastguard Worker  public:
ShadowWrite(uint16_t * s,uint16_t * e)50*8d67ca89SAndroid Build Coastguard Worker   ShadowWrite(uint16_t* s, uint16_t* e) {
51*8d67ca89SAndroid Build Coastguard Worker     shadow_start = reinterpret_cast<char*>(s);
52*8d67ca89SAndroid Build Coastguard Worker     shadow_end = reinterpret_cast<char*>(e);
53*8d67ca89SAndroid Build Coastguard Worker     aligned_start = reinterpret_cast<char*>(page_start(reinterpret_cast<uintptr_t>(shadow_start)));
54*8d67ca89SAndroid Build Coastguard Worker     aligned_end = reinterpret_cast<char*>(page_end(reinterpret_cast<uintptr_t>(shadow_end)));
55*8d67ca89SAndroid Build Coastguard Worker     tmp_start =
56*8d67ca89SAndroid Build Coastguard Worker         reinterpret_cast<char*>(mmap(nullptr, aligned_end - aligned_start, PROT_READ | PROT_WRITE,
57*8d67ca89SAndroid Build Coastguard Worker                                      MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
58*8d67ca89SAndroid Build Coastguard Worker     CHECK(tmp_start != MAP_FAILED);
59*8d67ca89SAndroid Build Coastguard Worker     mprotect(aligned_start, aligned_end - aligned_start, PROT_READ);
60*8d67ca89SAndroid Build Coastguard Worker     memcpy(tmp_start, aligned_start, shadow_start - aligned_start);
61*8d67ca89SAndroid Build Coastguard Worker     memcpy(tmp_start + (shadow_end - aligned_start), shadow_end, aligned_end - shadow_end);
62*8d67ca89SAndroid Build Coastguard Worker   }
63*8d67ca89SAndroid Build Coastguard Worker 
begin()64*8d67ca89SAndroid Build Coastguard Worker   uint16_t* begin() {
65*8d67ca89SAndroid Build Coastguard Worker     return reinterpret_cast<uint16_t*>(tmp_start + (shadow_start - aligned_start));
66*8d67ca89SAndroid Build Coastguard Worker   }
67*8d67ca89SAndroid Build Coastguard Worker 
end()68*8d67ca89SAndroid Build Coastguard Worker   uint16_t* end() {
69*8d67ca89SAndroid Build Coastguard Worker     return reinterpret_cast<uint16_t*>(tmp_start + (shadow_end - aligned_start));
70*8d67ca89SAndroid Build Coastguard Worker   }
71*8d67ca89SAndroid Build Coastguard Worker 
~ShadowWrite()72*8d67ca89SAndroid Build Coastguard Worker   ~ShadowWrite() {
73*8d67ca89SAndroid Build Coastguard Worker     size_t size = aligned_end - aligned_start;
74*8d67ca89SAndroid Build Coastguard Worker     mprotect(tmp_start, size, PROT_READ);
75*8d67ca89SAndroid Build Coastguard Worker     void* res = mremap(tmp_start, size, size, MREMAP_MAYMOVE | MREMAP_FIXED,
76*8d67ca89SAndroid Build Coastguard Worker                        reinterpret_cast<void*>(aligned_start));
77*8d67ca89SAndroid Build Coastguard Worker     CHECK(res != MAP_FAILED);
78*8d67ca89SAndroid Build Coastguard Worker   }
79*8d67ca89SAndroid Build Coastguard Worker };
80*8d67ca89SAndroid Build Coastguard Worker 
FixupVmaName()81*8d67ca89SAndroid Build Coastguard Worker void CFIShadowWriter::FixupVmaName() {
82*8d67ca89SAndroid Build Coastguard Worker   prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, *shadow_start, kShadowSize, "cfi shadow");
83*8d67ca89SAndroid Build Coastguard Worker }
84*8d67ca89SAndroid Build Coastguard Worker 
AddConstant(uintptr_t begin,uintptr_t end,uint16_t v)85*8d67ca89SAndroid Build Coastguard Worker void CFIShadowWriter::AddConstant(uintptr_t begin, uintptr_t end, uint16_t v) {
86*8d67ca89SAndroid Build Coastguard Worker   uint16_t* shadow_begin = MemToShadow(begin);
87*8d67ca89SAndroid Build Coastguard Worker   uint16_t* shadow_end = MemToShadow(end - 1) + 1;
88*8d67ca89SAndroid Build Coastguard Worker 
89*8d67ca89SAndroid Build Coastguard Worker   ShadowWrite sw(shadow_begin, shadow_end);
90*8d67ca89SAndroid Build Coastguard Worker   std::fill(sw.begin(), sw.end(), v);
91*8d67ca89SAndroid Build Coastguard Worker }
92*8d67ca89SAndroid Build Coastguard Worker 
AddUnchecked(uintptr_t begin,uintptr_t end)93*8d67ca89SAndroid Build Coastguard Worker void CFIShadowWriter::AddUnchecked(uintptr_t begin, uintptr_t end) {
94*8d67ca89SAndroid Build Coastguard Worker   AddConstant(begin, end, kUncheckedShadow);
95*8d67ca89SAndroid Build Coastguard Worker }
96*8d67ca89SAndroid Build Coastguard Worker 
AddInvalid(uintptr_t begin,uintptr_t end)97*8d67ca89SAndroid Build Coastguard Worker void CFIShadowWriter::AddInvalid(uintptr_t begin, uintptr_t end) {
98*8d67ca89SAndroid Build Coastguard Worker   AddConstant(begin, end, kInvalidShadow);
99*8d67ca89SAndroid Build Coastguard Worker }
100*8d67ca89SAndroid Build Coastguard Worker 
Add(uintptr_t begin,uintptr_t end,uintptr_t cfi_check)101*8d67ca89SAndroid Build Coastguard Worker void CFIShadowWriter::Add(uintptr_t begin, uintptr_t end, uintptr_t cfi_check) {
102*8d67ca89SAndroid Build Coastguard Worker   CHECK((cfi_check & (kCfiCheckAlign - 1)) == 0);
103*8d67ca89SAndroid Build Coastguard Worker 
104*8d67ca89SAndroid Build Coastguard Worker   // Don't fill anything below cfi_check. We can not represent those addresses
105*8d67ca89SAndroid Build Coastguard Worker   // in the shadow, and must make sure at codegen to place all valid call
106*8d67ca89SAndroid Build Coastguard Worker   // targets above cfi_check.
107*8d67ca89SAndroid Build Coastguard Worker   begin = std::max(begin, cfi_check) & ~(kShadowAlign - 1);
108*8d67ca89SAndroid Build Coastguard Worker   uint16_t* shadow_begin = MemToShadow(begin);
109*8d67ca89SAndroid Build Coastguard Worker   uint16_t* shadow_end = MemToShadow(end - 1) + 1;
110*8d67ca89SAndroid Build Coastguard Worker 
111*8d67ca89SAndroid Build Coastguard Worker   ShadowWrite sw(shadow_begin, shadow_end);
112*8d67ca89SAndroid Build Coastguard Worker   uint16_t sv_begin = ((begin + kShadowAlign - cfi_check) >> kCfiCheckGranularity) + kRegularShadowMin;
113*8d67ca89SAndroid Build Coastguard Worker 
114*8d67ca89SAndroid Build Coastguard Worker   // With each step of the loop below, __cfi_check address computation base is increased by
115*8d67ca89SAndroid Build Coastguard Worker   // 2**ShadowGranularity.
116*8d67ca89SAndroid Build Coastguard Worker   // To compensate for that, each next shadow value must be increased by 2**ShadowGranularity /
117*8d67ca89SAndroid Build Coastguard Worker   // 2**CfiCheckGranularity.
118*8d67ca89SAndroid Build Coastguard Worker   uint16_t sv_step = 1 << (kShadowGranularity - kCfiCheckGranularity);
119*8d67ca89SAndroid Build Coastguard Worker   uint16_t sv = sv_begin;
120*8d67ca89SAndroid Build Coastguard Worker   for (uint16_t& s : sw) {
121*8d67ca89SAndroid Build Coastguard Worker     if (sv < sv_begin) {
122*8d67ca89SAndroid Build Coastguard Worker       // If shadow value wraps around, also fall back to unchecked. This means the binary is too
123*8d67ca89SAndroid Build Coastguard Worker       // large. FIXME: consider using a (slow) resolution function instead.
124*8d67ca89SAndroid Build Coastguard Worker       s = kUncheckedShadow;
125*8d67ca89SAndroid Build Coastguard Worker       continue;
126*8d67ca89SAndroid Build Coastguard Worker     }
127*8d67ca89SAndroid Build Coastguard Worker     // If there is something there already, fall back to unchecked. This may happen in rare cases
128*8d67ca89SAndroid Build Coastguard Worker     // with MAP_FIXED libraries. FIXME: consider using a (slow) resolution function instead.
129*8d67ca89SAndroid Build Coastguard Worker     s = (s == kInvalidShadow) ? sv : kUncheckedShadow;
130*8d67ca89SAndroid Build Coastguard Worker     sv += sv_step;
131*8d67ca89SAndroid Build Coastguard Worker   }
132*8d67ca89SAndroid Build Coastguard Worker }
133*8d67ca89SAndroid Build Coastguard Worker 
find_libdl(soinfo * solist)134*8d67ca89SAndroid Build Coastguard Worker static soinfo* find_libdl(soinfo* solist) {
135*8d67ca89SAndroid Build Coastguard Worker   for (soinfo* si = solist; si != nullptr; si = si->next) {
136*8d67ca89SAndroid Build Coastguard Worker     if (strcmp(si->get_soname(), "libdl.so") == 0) {
137*8d67ca89SAndroid Build Coastguard Worker       return si;
138*8d67ca89SAndroid Build Coastguard Worker     }
139*8d67ca89SAndroid Build Coastguard Worker   }
140*8d67ca89SAndroid Build Coastguard Worker   return nullptr;
141*8d67ca89SAndroid Build Coastguard Worker }
142*8d67ca89SAndroid Build Coastguard Worker 
soinfo_find_symbol(soinfo * si,const char * s)143*8d67ca89SAndroid Build Coastguard Worker static uintptr_t soinfo_find_symbol(soinfo* si, const char* s) {
144*8d67ca89SAndroid Build Coastguard Worker   SymbolName name(s);
145*8d67ca89SAndroid Build Coastguard Worker   if (const ElfW(Sym)* sym = si->find_symbol_by_name(name, nullptr)) {
146*8d67ca89SAndroid Build Coastguard Worker     return si->resolve_symbol_address(sym);
147*8d67ca89SAndroid Build Coastguard Worker   }
148*8d67ca89SAndroid Build Coastguard Worker   return 0;
149*8d67ca89SAndroid Build Coastguard Worker }
150*8d67ca89SAndroid Build Coastguard Worker 
soinfo_find_cfi_check(soinfo * si)151*8d67ca89SAndroid Build Coastguard Worker uintptr_t soinfo_find_cfi_check(soinfo* si) {
152*8d67ca89SAndroid Build Coastguard Worker   return soinfo_find_symbol(si, "__cfi_check");
153*8d67ca89SAndroid Build Coastguard Worker }
154*8d67ca89SAndroid Build Coastguard Worker 
MapShadow()155*8d67ca89SAndroid Build Coastguard Worker uintptr_t CFIShadowWriter::MapShadow() {
156*8d67ca89SAndroid Build Coastguard Worker   void* p =
157*8d67ca89SAndroid Build Coastguard Worker       mmap(nullptr, kShadowSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0);
158*8d67ca89SAndroid Build Coastguard Worker   CHECK(p != MAP_FAILED);
159*8d67ca89SAndroid Build Coastguard Worker   return reinterpret_cast<uintptr_t>(p);
160*8d67ca89SAndroid Build Coastguard Worker }
161*8d67ca89SAndroid Build Coastguard Worker 
AddLibrary(soinfo * si)162*8d67ca89SAndroid Build Coastguard Worker bool CFIShadowWriter::AddLibrary(soinfo* si) {
163*8d67ca89SAndroid Build Coastguard Worker   CHECK(shadow_start != nullptr);
164*8d67ca89SAndroid Build Coastguard Worker   if (si->base == 0 || si->size == 0) {
165*8d67ca89SAndroid Build Coastguard Worker     return true;
166*8d67ca89SAndroid Build Coastguard Worker   }
167*8d67ca89SAndroid Build Coastguard Worker   uintptr_t cfi_check = soinfo_find_cfi_check(si);
168*8d67ca89SAndroid Build Coastguard Worker   if (cfi_check == 0) {
169*8d67ca89SAndroid Build Coastguard Worker     LD_DEBUG(cfi, "[ CFI add 0x%zx + 0x%zx %s ]", static_cast<uintptr_t>(si->base),
170*8d67ca89SAndroid Build Coastguard Worker          static_cast<uintptr_t>(si->size), si->get_soname());
171*8d67ca89SAndroid Build Coastguard Worker     AddUnchecked(si->base, si->base + si->size);
172*8d67ca89SAndroid Build Coastguard Worker     return true;
173*8d67ca89SAndroid Build Coastguard Worker   }
174*8d67ca89SAndroid Build Coastguard Worker 
175*8d67ca89SAndroid Build Coastguard Worker   LD_DEBUG(cfi, "[ CFI add 0x%zx + 0x%zx %s: 0x%zx ]", static_cast<uintptr_t>(si->base),
176*8d67ca89SAndroid Build Coastguard Worker        static_cast<uintptr_t>(si->size), si->get_soname(), cfi_check);
177*8d67ca89SAndroid Build Coastguard Worker #ifdef __arm__
178*8d67ca89SAndroid Build Coastguard Worker   // Require Thumb encoding.
179*8d67ca89SAndroid Build Coastguard Worker   if ((cfi_check & 1UL) != 1UL) {
180*8d67ca89SAndroid Build Coastguard Worker     DL_ERR("__cfi_check in not a Thumb function in the library \"%s\"", si->get_soname());
181*8d67ca89SAndroid Build Coastguard Worker     return false;
182*8d67ca89SAndroid Build Coastguard Worker   }
183*8d67ca89SAndroid Build Coastguard Worker   cfi_check &= ~1UL;
184*8d67ca89SAndroid Build Coastguard Worker #endif
185*8d67ca89SAndroid Build Coastguard Worker   if ((cfi_check & (kCfiCheckAlign - 1)) != 0) {
186*8d67ca89SAndroid Build Coastguard Worker     DL_ERR("unaligned __cfi_check in the library \"%s\"", si->get_soname());
187*8d67ca89SAndroid Build Coastguard Worker     return false;
188*8d67ca89SAndroid Build Coastguard Worker   }
189*8d67ca89SAndroid Build Coastguard Worker   Add(si->base, si->base + si->size, cfi_check);
190*8d67ca89SAndroid Build Coastguard Worker   return true;
191*8d67ca89SAndroid Build Coastguard Worker }
192*8d67ca89SAndroid Build Coastguard Worker 
193*8d67ca89SAndroid Build Coastguard Worker // Pass the shadow mapping address to libdl.so. In return, we get an pointer to the location
194*8d67ca89SAndroid Build Coastguard Worker // libdl.so uses to store the address.
NotifyLibDl(soinfo * solist,uintptr_t p)195*8d67ca89SAndroid Build Coastguard Worker bool CFIShadowWriter::NotifyLibDl(soinfo* solist, uintptr_t p) {
196*8d67ca89SAndroid Build Coastguard Worker   soinfo* libdl = find_libdl(solist);
197*8d67ca89SAndroid Build Coastguard Worker   if (libdl == nullptr) {
198*8d67ca89SAndroid Build Coastguard Worker     DL_ERR("CFI could not find libdl");
199*8d67ca89SAndroid Build Coastguard Worker     return false;
200*8d67ca89SAndroid Build Coastguard Worker   }
201*8d67ca89SAndroid Build Coastguard Worker 
202*8d67ca89SAndroid Build Coastguard Worker   uintptr_t cfi_init = soinfo_find_symbol(libdl, "__cfi_init");
203*8d67ca89SAndroid Build Coastguard Worker   CHECK(cfi_init != 0);
204*8d67ca89SAndroid Build Coastguard Worker   shadow_start = reinterpret_cast<uintptr_t* (*)(uintptr_t)>(cfi_init)(p);
205*8d67ca89SAndroid Build Coastguard Worker   CHECK(shadow_start != nullptr);
206*8d67ca89SAndroid Build Coastguard Worker   CHECK(*shadow_start == p);
207*8d67ca89SAndroid Build Coastguard Worker   mprotect(shadow_start, page_size(), PROT_READ);
208*8d67ca89SAndroid Build Coastguard Worker   return true;
209*8d67ca89SAndroid Build Coastguard Worker }
210*8d67ca89SAndroid Build Coastguard Worker 
MaybeInit(soinfo * new_si,soinfo * solist)211*8d67ca89SAndroid Build Coastguard Worker bool CFIShadowWriter::MaybeInit(soinfo* new_si, soinfo* solist) {
212*8d67ca89SAndroid Build Coastguard Worker   CHECK(initial_link_done);
213*8d67ca89SAndroid Build Coastguard Worker   CHECK(shadow_start == nullptr);
214*8d67ca89SAndroid Build Coastguard Worker   // Check if CFI shadow must be initialized at this time.
215*8d67ca89SAndroid Build Coastguard Worker   bool found = false;
216*8d67ca89SAndroid Build Coastguard Worker   if (new_si == nullptr) {
217*8d67ca89SAndroid Build Coastguard Worker     // This is the case when we've just completed the initial link. There may have been earlier
218*8d67ca89SAndroid Build Coastguard Worker     // calls to MaybeInit that were skipped. Look though the entire solist.
219*8d67ca89SAndroid Build Coastguard Worker     for (soinfo* si = solist; si != nullptr; si = si->next) {
220*8d67ca89SAndroid Build Coastguard Worker       if (soinfo_find_cfi_check(si)) {
221*8d67ca89SAndroid Build Coastguard Worker         found = true;
222*8d67ca89SAndroid Build Coastguard Worker         break;
223*8d67ca89SAndroid Build Coastguard Worker       }
224*8d67ca89SAndroid Build Coastguard Worker     }
225*8d67ca89SAndroid Build Coastguard Worker   } else {
226*8d67ca89SAndroid Build Coastguard Worker     // See if the new library uses CFI.
227*8d67ca89SAndroid Build Coastguard Worker     found = soinfo_find_cfi_check(new_si);
228*8d67ca89SAndroid Build Coastguard Worker   }
229*8d67ca89SAndroid Build Coastguard Worker 
230*8d67ca89SAndroid Build Coastguard Worker   // Nothing found.
231*8d67ca89SAndroid Build Coastguard Worker   if (!found) {
232*8d67ca89SAndroid Build Coastguard Worker     return true;
233*8d67ca89SAndroid Build Coastguard Worker   }
234*8d67ca89SAndroid Build Coastguard Worker 
235*8d67ca89SAndroid Build Coastguard Worker   // Init shadow and add all currently loaded libraries (not just the new ones).
236*8d67ca89SAndroid Build Coastguard Worker   if (!NotifyLibDl(solist, MapShadow()))
237*8d67ca89SAndroid Build Coastguard Worker     return false;
238*8d67ca89SAndroid Build Coastguard Worker   for (soinfo* si = solist; si != nullptr; si = si->next) {
239*8d67ca89SAndroid Build Coastguard Worker     if (!AddLibrary(si))
240*8d67ca89SAndroid Build Coastguard Worker       return false;
241*8d67ca89SAndroid Build Coastguard Worker   }
242*8d67ca89SAndroid Build Coastguard Worker   FixupVmaName();
243*8d67ca89SAndroid Build Coastguard Worker   return true;
244*8d67ca89SAndroid Build Coastguard Worker }
245*8d67ca89SAndroid Build Coastguard Worker 
AfterLoad(soinfo * si,soinfo * solist)246*8d67ca89SAndroid Build Coastguard Worker bool CFIShadowWriter::AfterLoad(soinfo* si, soinfo* solist) {
247*8d67ca89SAndroid Build Coastguard Worker   if (!initial_link_done) {
248*8d67ca89SAndroid Build Coastguard Worker     // Too early.
249*8d67ca89SAndroid Build Coastguard Worker     return true;
250*8d67ca89SAndroid Build Coastguard Worker   }
251*8d67ca89SAndroid Build Coastguard Worker 
252*8d67ca89SAndroid Build Coastguard Worker   if (shadow_start == nullptr) {
253*8d67ca89SAndroid Build Coastguard Worker     return MaybeInit(si, solist);
254*8d67ca89SAndroid Build Coastguard Worker   }
255*8d67ca89SAndroid Build Coastguard Worker 
256*8d67ca89SAndroid Build Coastguard Worker   // Add the new library to the CFI shadow.
257*8d67ca89SAndroid Build Coastguard Worker   if (!AddLibrary(si))
258*8d67ca89SAndroid Build Coastguard Worker     return false;
259*8d67ca89SAndroid Build Coastguard Worker   FixupVmaName();
260*8d67ca89SAndroid Build Coastguard Worker   return true;
261*8d67ca89SAndroid Build Coastguard Worker }
262*8d67ca89SAndroid Build Coastguard Worker 
BeforeUnload(soinfo * si)263*8d67ca89SAndroid Build Coastguard Worker void CFIShadowWriter::BeforeUnload(soinfo* si) {
264*8d67ca89SAndroid Build Coastguard Worker   if (shadow_start == nullptr) return;
265*8d67ca89SAndroid Build Coastguard Worker   if (si->base == 0 || si->size == 0) return;
266*8d67ca89SAndroid Build Coastguard Worker   LD_DEBUG(cfi, "[ CFI remove 0x%zx + 0x%zx: %s ]", static_cast<uintptr_t>(si->base),
267*8d67ca89SAndroid Build Coastguard Worker            static_cast<uintptr_t>(si->size), si->get_soname());
268*8d67ca89SAndroid Build Coastguard Worker   AddInvalid(si->base, si->base + si->size);
269*8d67ca89SAndroid Build Coastguard Worker   FixupVmaName();
270*8d67ca89SAndroid Build Coastguard Worker }
271*8d67ca89SAndroid Build Coastguard Worker 
InitialLinkDone(soinfo * solist)272*8d67ca89SAndroid Build Coastguard Worker bool CFIShadowWriter::InitialLinkDone(soinfo* solist) {
273*8d67ca89SAndroid Build Coastguard Worker   CHECK(!initial_link_done);
274*8d67ca89SAndroid Build Coastguard Worker   initial_link_done = true;
275*8d67ca89SAndroid Build Coastguard Worker   return MaybeInit(nullptr, solist);
276*8d67ca89SAndroid Build Coastguard Worker }
277*8d67ca89SAndroid Build Coastguard Worker 
278*8d67ca89SAndroid Build Coastguard Worker // Find __cfi_check in the caller and let it handle the problem. Since caller_pc is likely not a
279*8d67ca89SAndroid Build Coastguard Worker // valid CFI target, we can not use CFI shadow for lookup. This does not need to be fast, do the
280*8d67ca89SAndroid Build Coastguard Worker // regular symbol lookup.
CfiFail(uint64_t CallSiteTypeId,void * Ptr,void * DiagData,void * CallerPc)281*8d67ca89SAndroid Build Coastguard Worker void CFIShadowWriter::CfiFail(uint64_t CallSiteTypeId, void* Ptr, void* DiagData, void* CallerPc) {
282*8d67ca89SAndroid Build Coastguard Worker   soinfo* si = find_containing_library(CallerPc);
283*8d67ca89SAndroid Build Coastguard Worker   if (!si) {
284*8d67ca89SAndroid Build Coastguard Worker     __builtin_trap();
285*8d67ca89SAndroid Build Coastguard Worker   }
286*8d67ca89SAndroid Build Coastguard Worker 
287*8d67ca89SAndroid Build Coastguard Worker   uintptr_t cfi_check = soinfo_find_cfi_check(si);
288*8d67ca89SAndroid Build Coastguard Worker   if (!cfi_check) {
289*8d67ca89SAndroid Build Coastguard Worker     __builtin_trap();
290*8d67ca89SAndroid Build Coastguard Worker   }
291*8d67ca89SAndroid Build Coastguard Worker 
292*8d67ca89SAndroid Build Coastguard Worker   reinterpret_cast<CFICheckFn>(cfi_check)(CallSiteTypeId, Ptr, DiagData);
293*8d67ca89SAndroid Build Coastguard Worker }
294