1 //===-- safestack_platform.h ----------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file implements platform specific parts of SafeStack runtime. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef SAFESTACK_PLATFORM_H 14 #define SAFESTACK_PLATFORM_H 15 16 #include "safestack_util.h" 17 #include "sanitizer_common/sanitizer_platform.h" 18 19 #include <dlfcn.h> 20 #include <stdint.h> 21 #include <stdio.h> 22 #include <stdlib.h> 23 #include <sys/mman.h> 24 #include <sys/syscall.h> 25 #include <sys/types.h> 26 #include <unistd.h> 27 28 #if !(SANITIZER_NETBSD || SANITIZER_FREEBSD || SANITIZER_LINUX) 29 #error "Support for your platform has not been implemented" 30 #endif 31 32 #if SANITIZER_NETBSD 33 #include <lwp.h> 34 35 extern "C" void *__mmap(void *, size_t, int, int, int, int, off_t); 36 #endif 37 38 #if SANITIZER_FREEBSD 39 #include <sys/thr.h> 40 #endif 41 42 namespace safestack { 43 44 #if SANITIZER_NETBSD 45 static void *GetRealLibcAddress(const char *symbol) { 46 void *real = dlsym(RTLD_NEXT, symbol); 47 if (!real) 48 real = dlsym(RTLD_DEFAULT, symbol); 49 if (!real) { 50 fprintf(stderr, "safestack GetRealLibcAddress failed for symbol=%s", 51 symbol); 52 abort(); 53 } 54 return real; 55 } 56 57 #define _REAL(func, ...) real##_##func(__VA_ARGS__) 58 #define DEFINE__REAL(ret_type, func, ...) \ 59 static ret_type (*real_##func)(__VA_ARGS__) = NULL; \ 60 if (!real_##func) { \ 61 real_##func = (ret_type(*)(__VA_ARGS__))GetRealLibcAddress(#func); \ 62 } \ 63 SFS_CHECK(real_##func); 64 #endif 65 66 using ThreadId = uint64_t; 67 68 inline ThreadId GetTid() { 69 #if SANITIZER_NETBSD 70 DEFINE__REAL(int, _lwp_self); 71 return _REAL(_lwp_self); 72 #elif SANITIZER_FREEBSD 73 long Tid; 74 thr_self(&Tid); 75 return Tid; 76 #else 77 return syscall(SYS_gettid); 78 #endif 79 } 80 81 inline int TgKill(pid_t pid, ThreadId tid, int sig) { 82 #if SANITIZER_NETBSD 83 DEFINE__REAL(int, _lwp_kill, int a, int b); 84 (void)pid; 85 return _REAL(_lwp_kill, tid, sig); 86 #elif SANITIZER_FREEBSD 87 return syscall(SYS_thr_kill2, pid, tid, sig); 88 #else 89 return syscall(SYS_tgkill, pid, tid, sig); 90 #endif 91 } 92 93 inline void *Mmap(void *addr, size_t length, int prot, int flags, int fd, 94 off_t offset) { 95 #if SANITIZER_NETBSD 96 return __mmap(addr, length, prot, flags, fd, 0, offset); 97 #elif defined(__x86_64__) && (SANITIZER_FREEBSD) 98 return (void *)__syscall(SYS_mmap, addr, length, prot, flags, fd, offset); 99 #else 100 return (void *)syscall(SYS_mmap, addr, length, prot, flags, fd, offset); 101 #endif 102 } 103 104 inline int Munmap(void *addr, size_t length) { 105 #if SANITIZER_NETBSD 106 DEFINE__REAL(int, munmap, void *a, size_t b); 107 return _REAL(munmap, addr, length); 108 #else 109 return syscall(SYS_munmap, addr, length); 110 #endif 111 } 112 113 inline int Mprotect(void *addr, size_t length, int prot) { 114 #if SANITIZER_NETBSD 115 DEFINE__REAL(int, mprotect, void *a, size_t b, int c); 116 return _REAL(mprotect, addr, length, prot); 117 #else 118 return syscall(SYS_mprotect, addr, length, prot); 119 #endif 120 } 121 122 } // namespace safestack 123 124 #endif // SAFESTACK_PLATFORM_H 125