llvm/compiler-rt/lib/cfi/cfi.cpp

//===-------- cfi.cpp -----------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements the runtime support for the cross-DSO CFI.
//
//===----------------------------------------------------------------------===//

#include <assert.h>
#include <elf.h>

#include "sanitizer_common/sanitizer_common.h"
#if SANITIZER_FREEBSD
#include <sys/link_elf.h>
#endif
#include <link.h>
#include <string.h>
#include <stdlib.h>
#include <sys/mman.h>

#if SANITIZER_LINUX
Elf_Phdr;
Elf_Ehdr;
Elf_Addr;
Elf_Sym;
Elf_Dyn;
#elif SANITIZER_FREEBSD
#if SANITIZER_WORDSIZE == 64
#define ElfW64_Dyn
#define ElfW64_Sym
#else
#define ElfW32_Dyn
#define ElfW32_Sym
#endif
#endif

#include "interception/interception.h"
#include "sanitizer_common/sanitizer_flag_parser.h"
#include "ubsan/ubsan_init.h"
#include "ubsan/ubsan_flags.h"

#ifdef CFI_ENABLE_DIAG
#include "ubsan/ubsan_handlers.h"
#endif

usingnamespace__sanitizer;

namespace __cfi {

#if SANITIZER_LOONGARCH64
#define kCfiShadowLimitsStorageSize
#else
#define kCfiShadowLimitsStorageSize
#endif
// Lets hope that the data segment is mapped with 4K pages.
// The pointer to the cfi shadow region is stored at the start of this page.
// The rest of the page is unused and re-mapped read-only.
static union {} cfi_shadow_limits_storage
    __attribute__((aligned));
static constexpr uptr kShadowGranularity =;
static constexpr uptr kShadowAlign =; // 4096

static constexpr uint16_t kInvalidShadow =;
static constexpr uint16_t kUncheckedShadow =;

// Get the start address of the CFI shadow region.
uptr GetShadow() {}

uptr GetShadowSize() {}

// This will only work while the shadow is not allocated.
void SetShadowSize(uptr size) {}

uptr MemToShadowOffset(uptr x) {}

uint16_t *MemToShadow(uptr x, uptr shadow_base) {}

CFICheckFn;

// This class reads and decodes the shadow contents.
class ShadowValue {};

class ShadowBuilder {};

void ShadowBuilder::Start() {}

void ShadowBuilder::AddUnchecked(uptr begin, uptr end) {}

void ShadowBuilder::Add(uptr begin, uptr end, uptr cfi_check) {}

#if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD
void ShadowBuilder::Install() {}
#else
#error not implemented
#endif

// This is a workaround for a glibc bug:
// https://sourceware.org/bugzilla/show_bug.cgi?id=15199
// Other platforms can, hopefully, just do
//    dlopen(RTLD_NOLOAD | RTLD_LAZY)
//    dlsym("__cfi_check").
uptr find_cfi_check_in_dso(dl_phdr_info *info) {}

int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *data) {}

// Init or update shadow for the current set of loaded libraries.
void UpdateShadow() {}

void InitShadow() {}

THREADLOCAL int in_loader;
Mutex shadow_update_lock;

void EnterLoader() SANITIZER_NO_THREAD_SAFETY_ANALYSIS {}

void ExitLoader() SANITIZER_NO_THREAD_SAFETY_ANALYSIS {}

ALWAYS_INLINE void CfiSlowPathCommon(u64 CallSiteTypeId, void *Ptr,
                                     void *DiagData) {}

void InitializeFlags() {}

} // namespace __cfi

usingnamespace__cfi;

extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
__cfi_slowpath(u64 CallSiteTypeId, void *Ptr) {}

#ifdef CFI_ENABLE_DIAG
extern "C" SANITIZER_INTERFACE_ATTRIBUTE void
__cfi_slowpath_diag(u64 CallSiteTypeId, void *Ptr, void *DiagData) {
  CfiSlowPathCommon(CallSiteTypeId, Ptr, DiagData);
}
#endif

static void EnsureInterceptorsInitialized();

// Setup shadow for dlopen()ed libraries.
// The actual shadow setup happens after dlopen() returns, which means that
// a library can not be a target of any CFI checks while its constructors are
// running. It's unclear how to fix this without some extra help from libc.
// In glibc, mmap inside dlopen is not interceptable.
// Maybe a seccomp-bpf filter?
// We could insert a high-priority constructor into the library, but that would
// not help with the uninstrumented libraries.
INTERCEPTOR(void*, dlopen, const char *filename, int flag) {}

INTERCEPTOR(int, dlclose, void *handle) {}

static Mutex interceptor_init_lock;
static bool interceptors_inited =;

static void EnsureInterceptorsInitialized() {}

extern "C" SANITIZER_INTERFACE_ATTRIBUTE
#if !SANITIZER_CAN_USE_PREINIT_ARRAY
// On ELF platforms, the constructor is invoked using .preinit_array (see below)
__attribute__((constructor(0)))
#endif
void __cfi_init() {}

#if SANITIZER_CAN_USE_PREINIT_ARRAY
// On ELF platforms, run cfi initialization before any other constructors.
// On other platforms we use the constructor attribute to arrange to run our
// initialization early.
extern "C" {
__attribute__((section(".preinit_array"),
               used)) void (*__cfi_preinit)(void) =;
}
#endif