1 //===-- sanitizer_netbsd.cpp ----------------------------------------------===// 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 is shared between Sanitizer run-time libraries and implements 10 // NetBSD-specific functions from sanitizer_libc.h. 11 //===----------------------------------------------------------------------===// 12 13 #include "sanitizer_platform.h" 14 15 #if SANITIZER_NETBSD 16 17 #include "sanitizer_common.h" 18 #include "sanitizer_flags.h" 19 #include "sanitizer_getauxval.h" 20 #include "sanitizer_internal_defs.h" 21 #include "sanitizer_libc.h" 22 #include "sanitizer_linux.h" 23 #include "sanitizer_mutex.h" 24 #include "sanitizer_placement_new.h" 25 #include "sanitizer_procmaps.h" 26 27 #include <sys/param.h> 28 #include <sys/types.h> 29 30 #include <sys/exec.h> 31 #include <sys/mman.h> 32 #include <sys/ptrace.h> 33 #include <sys/resource.h> 34 #include <sys/stat.h> 35 #include <sys/syscall.h> 36 #include <sys/sysctl.h> 37 #include <sys/time.h> 38 39 #include <dlfcn.h> 40 #include <errno.h> 41 #include <fcntl.h> 42 #include <limits.h> 43 #include <link.h> 44 #include <lwp.h> 45 #include <pthread.h> 46 #include <sched.h> 47 #include <signal.h> 48 #include <ucontext.h> 49 #include <unistd.h> 50 51 extern "C" void *__mmap(void *, size_t, int, int, int, int, 52 off_t) SANITIZER_WEAK_ATTRIBUTE; 53 extern "C" int __sysctl(const int *, unsigned int, void *, size_t *, 54 const void *, size_t) SANITIZER_WEAK_ATTRIBUTE; 55 extern "C" int _sys_close(int) SANITIZER_WEAK_ATTRIBUTE; 56 extern "C" int _sys_open(const char *, int, ...) SANITIZER_WEAK_ATTRIBUTE; 57 extern "C" ssize_t _sys_read(int, void *, size_t) SANITIZER_WEAK_ATTRIBUTE; 58 extern "C" ssize_t _sys_write(int, const void *, 59 size_t) SANITIZER_WEAK_ATTRIBUTE; 60 extern "C" int __ftruncate(int, int, off_t) SANITIZER_WEAK_ATTRIBUTE; 61 extern "C" ssize_t _sys_readlink(const char *, char *, 62 size_t) SANITIZER_WEAK_ATTRIBUTE; 63 extern "C" int _sys_sched_yield() SANITIZER_WEAK_ATTRIBUTE; 64 extern "C" int _sys___nanosleep50(const void *, 65 void *) SANITIZER_WEAK_ATTRIBUTE; 66 extern "C" int _sys_execve(const char *, char *const[], 67 char *const[]) SANITIZER_WEAK_ATTRIBUTE; 68 extern "C" off_t __lseek(int, int, off_t, int) SANITIZER_WEAK_ATTRIBUTE; 69 extern "C" int __fork() SANITIZER_WEAK_ATTRIBUTE; 70 extern "C" int _sys___sigprocmask14(int, const void *, 71 void *) SANITIZER_WEAK_ATTRIBUTE; 72 extern "C" int _sys___wait450(int wpid, int *, int, 73 void *) SANITIZER_WEAK_ATTRIBUTE; 74 75 namespace __sanitizer { 76 77 static void *GetRealLibcAddress(const char *symbol) { 78 void *real = dlsym(RTLD_NEXT, symbol); 79 if (!real) 80 real = dlsym(RTLD_DEFAULT, symbol); 81 if (!real) { 82 Printf("GetRealLibcAddress failed for symbol=%s", symbol); 83 Die(); 84 } 85 return real; 86 } 87 88 #define _REAL(func, ...) real##_##func(__VA_ARGS__) 89 #define DEFINE__REAL(ret_type, func, ...) \ 90 static ret_type (*real_##func)(__VA_ARGS__) = NULL; \ 91 if (!real_##func) { \ 92 real_##func = (ret_type(*)(__VA_ARGS__))GetRealLibcAddress(#func); \ 93 } \ 94 CHECK(real_##func); 95 96 // --------------- sanitizer_libc.h 97 uptr internal_mmap(void *addr, uptr length, int prot, int flags, int fd, 98 u64 offset) { 99 CHECK(&__mmap); 100 return (uptr)__mmap(addr, length, prot, flags, fd, 0, offset); 101 } 102 103 uptr internal_munmap(void *addr, uptr length) { 104 DEFINE__REAL(int, munmap, void *a, uptr b); 105 return _REAL(munmap, addr, length); 106 } 107 108 uptr internal_mremap(void *old_address, uptr old_size, uptr new_size, int flags, 109 void *new_address) { 110 CHECK(false && "internal_mremap is unimplemented on NetBSD"); 111 return 0; 112 } 113 114 int internal_mprotect(void *addr, uptr length, int prot) { 115 DEFINE__REAL(int, mprotect, void *a, uptr b, int c); 116 return _REAL(mprotect, addr, length, prot); 117 } 118 119 int internal_madvise(uptr addr, uptr length, int advice) { 120 DEFINE__REAL(int, madvise, void *a, uptr b, int c); 121 return _REAL(madvise, (void *)addr, length, advice); 122 } 123 124 uptr internal_close(fd_t fd) { 125 CHECK(&_sys_close); 126 return _sys_close(fd); 127 } 128 129 uptr internal_open(const char *filename, int flags) { 130 CHECK(&_sys_open); 131 return _sys_open(filename, flags); 132 } 133 134 uptr internal_open(const char *filename, int flags, u32 mode) { 135 CHECK(&_sys_open); 136 return _sys_open(filename, flags, mode); 137 } 138 139 uptr internal_read(fd_t fd, void *buf, uptr count) { 140 sptr res; 141 CHECK(&_sys_read); 142 HANDLE_EINTR(res, (sptr)_sys_read(fd, buf, (size_t)count)); 143 return res; 144 } 145 146 uptr internal_write(fd_t fd, const void *buf, uptr count) { 147 sptr res; 148 CHECK(&_sys_write); 149 HANDLE_EINTR(res, (sptr)_sys_write(fd, buf, count)); 150 return res; 151 } 152 153 uptr internal_ftruncate(fd_t fd, uptr size) { 154 sptr res; 155 CHECK(&__ftruncate); 156 HANDLE_EINTR(res, __ftruncate(fd, 0, (s64)size)); 157 return res; 158 } 159 160 uptr internal_stat(const char *path, void *buf) { 161 DEFINE__REAL(int, __stat50, const char *a, void *b); 162 return _REAL(__stat50, path, buf); 163 } 164 165 uptr internal_lstat(const char *path, void *buf) { 166 DEFINE__REAL(int, __lstat50, const char *a, void *b); 167 return _REAL(__lstat50, path, buf); 168 } 169 170 uptr internal_fstat(fd_t fd, void *buf) { 171 DEFINE__REAL(int, __fstat50, int a, void *b); 172 return _REAL(__fstat50, fd, buf); 173 } 174 175 uptr internal_filesize(fd_t fd) { 176 struct stat st; 177 if (internal_fstat(fd, &st)) 178 return -1; 179 return (uptr)st.st_size; 180 } 181 182 uptr internal_dup(int oldfd) { 183 DEFINE__REAL(int, dup, int a); 184 return _REAL(dup, oldfd); 185 } 186 187 uptr internal_dup2(int oldfd, int newfd) { 188 DEFINE__REAL(int, dup2, int a, int b); 189 return _REAL(dup2, oldfd, newfd); 190 } 191 192 uptr internal_readlink(const char *path, char *buf, uptr bufsize) { 193 CHECK(&_sys_readlink); 194 return (uptr)_sys_readlink(path, buf, bufsize); 195 } 196 197 uptr internal_unlink(const char *path) { 198 DEFINE__REAL(int, unlink, const char *a); 199 return _REAL(unlink, path); 200 } 201 202 uptr internal_rename(const char *oldpath, const char *newpath) { 203 DEFINE__REAL(int, rename, const char *a, const char *b); 204 return _REAL(rename, oldpath, newpath); 205 } 206 207 uptr internal_sched_yield() { 208 CHECK(&_sys_sched_yield); 209 return _sys_sched_yield(); 210 } 211 212 void internal__exit(int exitcode) { 213 DEFINE__REAL(void, _exit, int a); 214 _REAL(_exit, exitcode); 215 Die(); // Unreachable. 216 } 217 218 void internal_usleep(u64 useconds) { 219 struct timespec ts; 220 ts.tv_sec = useconds / 1000000; 221 ts.tv_nsec = (useconds % 1000000) * 1000; 222 CHECK(&_sys___nanosleep50); 223 _sys___nanosleep50(&ts, &ts); 224 } 225 226 uptr internal_execve(const char *filename, char *const argv[], 227 char *const envp[]) { 228 CHECK(&_sys_execve); 229 return _sys_execve(filename, argv, envp); 230 } 231 232 tid_t GetTid() { 233 DEFINE__REAL(int, _lwp_self); 234 return _REAL(_lwp_self); 235 } 236 237 int TgKill(pid_t pid, tid_t tid, int sig) { 238 DEFINE__REAL(int, _lwp_kill, int a, int b); 239 (void)pid; 240 return _REAL(_lwp_kill, tid, sig); 241 } 242 243 u64 NanoTime() { 244 timeval tv; 245 DEFINE__REAL(int, __gettimeofday50, void *a, void *b); 246 internal_memset(&tv, 0, sizeof(tv)); 247 _REAL(__gettimeofday50, &tv, 0); 248 return (u64)tv.tv_sec * 1000 * 1000 * 1000 + tv.tv_usec * 1000; 249 } 250 251 uptr internal_clock_gettime(__sanitizer_clockid_t clk_id, void *tp) { 252 DEFINE__REAL(int, __clock_gettime50, __sanitizer_clockid_t a, void *b); 253 return _REAL(__clock_gettime50, clk_id, tp); 254 } 255 256 uptr internal_ptrace(int request, int pid, void *addr, int data) { 257 DEFINE__REAL(int, ptrace, int a, int b, void *c, int d); 258 return _REAL(ptrace, request, pid, addr, data); 259 } 260 261 uptr internal_waitpid(int pid, int *status, int options) { 262 CHECK(&_sys___wait450); 263 return _sys___wait450(pid, status, options, 0 /* rusage */); 264 } 265 266 uptr internal_getpid() { 267 DEFINE__REAL(int, getpid); 268 return _REAL(getpid); 269 } 270 271 uptr internal_getppid() { 272 DEFINE__REAL(int, getppid); 273 return _REAL(getppid); 274 } 275 276 int internal_dlinfo(void *handle, int request, void *p) { 277 DEFINE__REAL(int, dlinfo, void *a, int b, void *c); 278 return _REAL(dlinfo, handle, request, p); 279 } 280 281 uptr internal_getdents(fd_t fd, void *dirp, unsigned int count) { 282 DEFINE__REAL(int, __getdents30, int a, void *b, size_t c); 283 return _REAL(__getdents30, fd, dirp, count); 284 } 285 286 uptr internal_lseek(fd_t fd, OFF_T offset, int whence) { 287 CHECK(&__lseek); 288 return __lseek(fd, 0, offset, whence); 289 } 290 291 uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5) { 292 Printf("internal_prctl not implemented for NetBSD"); 293 Die(); 294 return 0; 295 } 296 297 uptr internal_sigaltstack(const void *ss, void *oss) { 298 DEFINE__REAL(int, __sigaltstack14, const void *a, void *b); 299 return _REAL(__sigaltstack14, ss, oss); 300 } 301 302 int internal_fork() { 303 CHECK(&__fork); 304 return __fork(); 305 } 306 307 int internal_sysctl(const int *name, unsigned int namelen, void *oldp, 308 uptr *oldlenp, const void *newp, uptr newlen) { 309 CHECK(&__sysctl); 310 return __sysctl(name, namelen, oldp, (size_t *)oldlenp, newp, (size_t)newlen); 311 } 312 313 int internal_sysctlbyname(const char *sname, void *oldp, uptr *oldlenp, 314 const void *newp, uptr newlen) { 315 DEFINE__REAL(int, sysctlbyname, const char *a, void *b, size_t *c, 316 const void *d, size_t e); 317 return _REAL(sysctlbyname, sname, oldp, (size_t *)oldlenp, newp, 318 (size_t)newlen); 319 } 320 321 uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set, 322 __sanitizer_sigset_t *oldset) { 323 CHECK(&_sys___sigprocmask14); 324 return _sys___sigprocmask14(how, set, oldset); 325 } 326 327 void internal_sigfillset(__sanitizer_sigset_t *set) { 328 DEFINE__REAL(int, __sigfillset14, const void *a); 329 (void)_REAL(__sigfillset14, set); 330 } 331 332 void internal_sigemptyset(__sanitizer_sigset_t *set) { 333 DEFINE__REAL(int, __sigemptyset14, const void *a); 334 (void)_REAL(__sigemptyset14, set); 335 } 336 337 void internal_sigdelset(__sanitizer_sigset_t *set, int signo) { 338 DEFINE__REAL(int, __sigdelset14, const void *a, int b); 339 (void)_REAL(__sigdelset14, set, signo); 340 } 341 342 uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, 343 void *arg) { 344 DEFINE__REAL(int, clone, int (*a)(void *b), void *c, int d, void *e); 345 346 return _REAL(clone, fn, child_stack, flags, arg); 347 } 348 349 } // namespace __sanitizer 350 351 #endif 352