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