// Update shadow without making it writable by preparing the data on the side and mremap-ing it in // place. class ShadowWrite { char* shadow_start; char* shadow_end; char* aligned_start; char* aligned_end; char* tmp_start;
// Don't fill anything below cfi_check. We can not represent those addresses // in the shadow, and must make sure at codegen to place all valid call // targets above cfi_check.
begin = std::max(begin, cfi_check) & ~(kShadowAlign - 1);
uint16_t* shadow_begin = MemToShadow(begin);
uint16_t* shadow_end = MemToShadow(end - 1) + 1;
// With each step of the loop below, __cfi_check address computation base is increased by // 2**ShadowGranularity. // To compensate for that, each next shadow value must be increased by 2**ShadowGranularity / // 2**CfiCheckGranularity.
uint16_t sv_step = 1 << (kShadowGranularity - kCfiCheckGranularity);
uint16_t sv = sv_begin; for (uint16_t& s : sw) { if (sv < sv_begin) { // If shadow value wraps around, also fall back to unchecked. This means the binary is too // large. FIXME: consider using a (slow) resolution function instead.
s = kUncheckedShadow; continue;
} // If there is something there already, fall back to unchecked. This may happen in rare cases // with MAP_FIXED libraries. FIXME: consider using a (slow) resolution function instead.
s = (s == kInvalidShadow) ? sv : kUncheckedShadow;
sv += sv_step;
}
}
static soinfo* find_libdl(soinfo* solist) { for (soinfo* si = solist; si != nullptr; si = si->next) { if (strcmp(si->get_soname(), "libdl.so") == 0) { return si;
}
} return nullptr;
}
LD_DEBUG(cfi, "[ CFI add 0x%zx + 0x%zx %s: 0x%zx ]", static_cast<uintptr_t>(si->base), static_cast<uintptr_t>(si->size), si->get_soname(), cfi_check); #ifdef __arm__ // Require Thumb encoding. if ((cfi_check & 1UL) != 1UL) {
DL_ERR("__cfi_check in not a Thumb function in the library \"%s\"", si->get_soname()); returnfalse;
}
cfi_check &= ~1UL; #endif if ((cfi_check & (kCfiCheckAlign - 1)) != 0) {
DL_ERR("unaligned __cfi_check in the library \"%s\"", si->get_soname()); returnfalse;
}
Add(si->base, si->base + si->size, cfi_check); returntrue;
}
// Pass the shadow mapping address to libdl.so. In return, we get an pointer to the location // libdl.so uses to store the address. bool CFIShadowWriter::NotifyLibDl(soinfo* solist, uintptr_t p) {
soinfo* libdl = find_libdl(solist); if (libdl == nullptr) {
DL_ERR("CFI could not find libdl"); returnfalse;
}
bool CFIShadowWriter::MaybeInit(soinfo* new_si, soinfo* solist) {
CHECK(initial_link_done);
CHECK(shadow_start == nullptr); // Check if CFI shadow must be initialized at this time. bool found = false; if (new_si == nullptr) { // This is the case when we've just completed the initial link. There may have been earlier // calls to MaybeInit that were skipped. Look though the entire solist. for (soinfo* si = solist; si != nullptr; si = si->next) { if (soinfo_find_cfi_check(si)) {
found = true; break;
}
}
} else { // See if the new library uses CFI.
found = soinfo_find_cfi_check(new_si);
}
// Nothing found. if (!found) { returntrue;
}
// Init shadow and add all currently loaded libraries (not just the new ones). if (!NotifyLibDl(solist, MapShadow())) returnfalse; for (soinfo* si = solist; si != nullptr; si = si->next) { if (!AddLibrary(si)) returnfalse;
}
FixupVmaName(); returntrue;
}
bool CFIShadowWriter::AfterLoad(soinfo* si, soinfo* solist) { if (!initial_link_done) { // Too early. returntrue;
}
if (shadow_start == nullptr) { return MaybeInit(si, solist);
}
// Add the new library to the CFI shadow. if (!AddLibrary(si)) returnfalse;
FixupVmaName(); returntrue;
}
// Find __cfi_check in the caller and let it handle the problem. Since caller_pc is likely not a // valid CFI target, we can not use CFI shadow for lookup. This does not need to be fast, do the // regular symbol lookup. void CFIShadowWriter::CfiFail(uint64_t CallSiteTypeId, void* Ptr, void* DiagData, void* CallerPc) {
soinfo* si = find_containing_library(CallerPc); if (!si) {
__builtin_trap();
}
uintptr_t cfi_check = soinfo_find_cfi_check(si); if (!cfi_check) {
__builtin_trap();
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.