Module Name: src Committed By: kamil Date: Sat Apr 27 00:23:18 UTC 2019
Modified Files: src/external/gpl3/gcc/dist/libsanitizer/sanitizer_common: sanitizer_linux.cc Log Message: Backport improvements into GCC's sanitizer_linux.cc from more recent LLVM Backport fixups for syscall()/__syscall() routines from LLVM compiler-rt dated October 1st 2018. The commit beffore switching LLVM compiler-rt sycall calls to libc calls for NetBSD. GCC8 will get part of these changes from upstream and GCC9 will operate on libc calls directly for the NetBSD port. This is intended to correct misuse of parameters of syscall()/__syscall() that could break !x86 ports in UBSan. To generate a diff of this commit: cvs rdiff -u -r1.29 -r1.30 \ src/external/gpl3/gcc/dist/libsanitizer/sanitizer_common/sanitizer_linux.cc Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/external/gpl3/gcc/dist/libsanitizer/sanitizer_common/sanitizer_linux.cc diff -u src/external/gpl3/gcc/dist/libsanitizer/sanitizer_common/sanitizer_linux.cc:1.29 src/external/gpl3/gcc/dist/libsanitizer/sanitizer_common/sanitizer_linux.cc:1.30 --- src/external/gpl3/gcc/dist/libsanitizer/sanitizer_common/sanitizer_linux.cc:1.29 Tue Apr 16 07:34:54 2019 +++ src/external/gpl3/gcc/dist/libsanitizer/sanitizer_common/sanitizer_linux.cc Sat Apr 27 00:23:17 2019 @@ -42,6 +42,10 @@ #endif // !SANITIZER_FREEBSD && !SANITIZER_NETBSD +#if SANITIZER_NETBSD +#include <lwp.h> +#endif + #include <dlfcn.h> #include <errno.h> #include <fcntl.h> @@ -74,6 +78,8 @@ extern char **environ; // provided by c #if SANITIZER_NETBSD #include <limits.h> // For NAME_MAX #include <sys/sysctl.h> +#include <sys/exec.h> +extern struct ps_strings *__ps_strings; extern char **environ; // provided by crt1 #endif // SANITIZER_NETBSD @@ -147,11 +153,11 @@ uptr internal_mmap(void *addr, uptr leng #endif // !SANITIZER_S390 uptr internal_munmap(void *addr, uptr length) { - return internal_syscall(SYSCALL(munmap), (uptr)addr, length); + return internal_syscall_ptr(SYSCALL(munmap), (uptr)addr, length); } int internal_mprotect(void *addr, uptr length, int prot) { - return internal_syscall(SYSCALL(mprotect), (uptr)addr, length, prot); + return internal_syscall_ptr(SYSCALL(mprotect), (uptr)addr, length, prot); } uptr internal_close(fd_t fd) { @@ -162,7 +168,7 @@ uptr internal_open(const char *filename, #if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS return internal_syscall(SYSCALL(openat), AT_FDCWD, (uptr)filename, flags); #else - return internal_syscall(SYSCALL(open), (uptr)filename, flags); + return internal_syscall_ptr(SYSCALL(open), (uptr)filename, flags); #endif } @@ -171,7 +177,7 @@ uptr internal_open(const char *filename, return internal_syscall(SYSCALL(openat), AT_FDCWD, (uptr)filename, flags, mode); #else - return internal_syscall(SYSCALL(open), (uptr)filename, flags, mode); + return internal_syscall_ptr(SYSCALL(open), (uptr)filename, flags, mode); #endif } @@ -200,7 +206,7 @@ uptr internal_write(fd_t fd, const void uptr internal_ftruncate(fd_t fd, uptr size) { sptr res; #ifdef SANITIZER_NETBSD - HANDLE_EINTR(res, internal_syscall(SYSCALL(ftruncate), fd, 0, (s64)size)); + HANDLE_EINTR(res, internal_syscall64(SYSCALL(ftruncate), fd, 0, (s64)size)); #else HANDLE_EINTR(res, (sptr)internal_syscall(SYSCALL(ftruncate), fd, (OFF_T)size)); @@ -250,7 +256,7 @@ static void kernel_stat_to_stat(struct k uptr internal_stat(const char *path, void *buf) { #if SANITIZER_FREEBSD || SANITIZER_NETBSD - return internal_syscall(SYSCALL(stat), path, buf); + return internal_syscall_ptr(SYSCALL(fstatat), AT_FDCWD, (uptr)path, (uptr)buf, 0); #elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path, (uptr)buf, 0); @@ -274,7 +280,7 @@ uptr internal_stat(const char *path, voi uptr internal_lstat(const char *path, void *buf) { #if SANITIZER_FREEBSD || SANITIZER_NETBSD - return internal_syscall(SYSCALL(lstat), path, buf); + return internal_syscall_ptr(SYSCALL(lstat), path, buf); #elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path, (uptr)buf, AT_SYMLINK_NOFOLLOW); @@ -298,7 +304,7 @@ uptr internal_lstat(const char *path, vo uptr internal_fstat(fd_t fd, void *buf) { #if SANITIZER_FREEBSD || SANITIZER_NETBSD - return internal_syscall(SYSCALL(fstat), fd, (uptr)buf); + return internal_syscall_ptr(SYSCALL(fstat), fd, (uptr)buf); #elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS return = internal_syscall(SYSCALL(fstat), fd, &kbuf); #elif SANITIZER_LINUX_USES_64BIT_SYSCALLS @@ -336,7 +342,7 @@ uptr internal_dup2(int oldfd, int newfd) uptr internal_readlink(const char *path, char *buf, uptr bufsize) { #if SANITIZER_NETBSD - return internal_syscall_ptr(SYSCALL(readlink), path, buf, bufsize); + return internal_syscall_ptr(SYSCALL(readlink), (uptr)path, (uptr)buf, bufsize); #elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS return internal_syscall(SYSCALL(readlinkat), AT_FDCWD, (uptr)path, (uptr)buf, bufsize); @@ -349,7 +355,7 @@ uptr internal_unlink(const char *path) { #if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS return internal_syscall(SYSCALL(unlinkat), AT_FDCWD, (uptr)path, 0); #else - return internal_syscall(SYSCALL(unlink), (uptr)path); + return internal_syscall_ptr(SYSCALL(unlink), (uptr)path); #endif } @@ -358,7 +364,7 @@ uptr internal_rename(const char *oldpath return internal_syscall(SYSCALL(renameat), AT_FDCWD, (uptr)oldpath, AT_FDCWD, (uptr)newpath); #else - return internal_syscall(SYSCALL(rename), (uptr)oldpath, (uptr)newpath); + return internal_syscall_ptr(SYSCALL(rename), (uptr)oldpath, (uptr)newpath); #endif } @@ -379,14 +385,14 @@ unsigned int internal_sleep(unsigned int struct timespec ts; ts.tv_sec = 1; ts.tv_nsec = 0; - int res = internal_syscall(SYSCALL(nanosleep), &ts, &ts); + int res = internal_syscall_ptr(SYSCALL(nanosleep), &ts, &ts); if (res) return ts.tv_sec; return 0; } uptr internal_execve(const char *filename, char *const argv[], char *const envp[]) { - return internal_syscall(SYSCALL(execve), (uptr)filename, (uptr)argv, + return internal_syscall_ptr(SYSCALL(execve), (uptr)filename, (uptr)argv, (uptr)envp); } @@ -404,7 +410,9 @@ bool FileExists(const char *filename) { } uptr GetTid() { -#if SANITIZER_FREEBSD || SANITIZER_NETBSD +#if SANITIZER_NETBSD + return _lwp_self(); +#elif SANITIZER_FREEBSD return (uptr)pthread_self(); #else return internal_syscall(SYSCALL(gettid)); @@ -419,7 +427,7 @@ u64 NanoTime() { #endif internal_memset(&tv, 0, sizeof(tv)); #if SANITIZER_NETBSD - internal_syscall(SYSCALL(gettimeofday), &tv, NULL); + internal_syscall_ptr(SYSCALL(gettimeofday), &tv, NULL); #else internal_syscall(SYSCALL(gettimeofday), (uptr)&tv, 0); #endif @@ -468,13 +476,13 @@ const char *GetEnv(const char *name) { #endif } -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD extern "C" { SANITIZER_WEAK_ATTRIBUTE extern void *__libc_stack_end; } #endif -#if !SANITIZER_GO && !SANITIZER_FREEBSD +#if !SANITIZER_GO && !SANITIZER_FREEBSD && !SANITIZER_NETBSD static void ReadNullSepFileToArray(const char *path, char ***arr, int arr_size) { char *buff; @@ -499,11 +507,27 @@ static void ReadNullSepFileToArray(const } #endif +#if !SANITIZER_OPENBSD static void GetArgsAndEnv(char ***argv, char ***envp) { -#if !SANITIZER_FREEBSD +#if SANITIZER_FREEBSD + // On FreeBSD, retrieving the argument and environment arrays is done via the + // kern.ps_strings sysctl, which returns a pointer to a structure containing + // this information. See also <sys/exec.h>. + ps_strings *pss; + size_t sz = sizeof(pss); + if (sysctlbyname("kern.ps_strings", &pss, &sz, NULL, 0) == -1) { + Printf("sysctl kern.ps_strings failed\n"); + Die(); + } + *argv = pss->ps_argvstr; + *envp = pss->ps_envstr; +#elif SANITIZER_NETBSD + *argv = __ps_strings->ps_argvstr; + *envp = __ps_strings->ps_envstr; +#else // SANITIZER_FREEBSD #if !SANITIZER_GO if (&__libc_stack_end) { -#endif +#endif // !SANITIZER_GO uptr* stack_end = (uptr*)__libc_stack_end; int argc = *stack_end; *argv = (char**)(stack_end + 1); @@ -514,20 +538,8 @@ static void GetArgsAndEnv(char ***argv, ReadNullSepFileToArray("/proc/self/cmdline", argv, kMaxArgv); ReadNullSepFileToArray("/proc/self/environ", envp, kMaxEnvp); } -#endif -#else - // On FreeBSD, retrieving the argument and environment arrays is done via the - // kern.ps_strings sysctl, which returns a pointer to a structure containing - // this information. See also <sys/exec.h>. - ps_strings *pss; - size_t sz = sizeof(pss); - if (sysctlbyname("kern.ps_strings", &pss, &sz, NULL, 0) == -1) { - Printf("sysctl kern.ps_strings failed\n"); - Die(); - } - *argv = pss->ps_argvstr; - *envp = pss->ps_envstr; -#endif +#endif // !SANITIZER_GO +#endif // SANITIZER_FREEBSD } char **GetArgv() { @@ -538,13 +550,31 @@ char **GetArgv() { void ReExec() { char **argv, **envp; + const char *pathname = "/proc/self/exe"; + +#if SANITIZER_NETBSD + static const int name[] = { + CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME, + }; + char path[400]; + size_t len; + + len = sizeof(path); + if (sysctl(name, ARRAY_SIZE(name), path, &len, NULL, 0) != -1) + pathname = path; +#elif SANITIZER_SOLARIS + pathname = getexecname(); + CHECK_NE(pathname, NULL); +#endif + GetArgsAndEnv(&argv, &envp); - uptr rv = internal_execve("/proc/self/exe", argv, envp); + uptr rv = internal_execve(pathname, argv, envp); int rverrno; CHECK_EQ(internal_iserror(rv, &rverrno), true); Printf("execve failed, errno %d\n", rverrno); Die(); } +#endif enum MutexState { MtxUnlocked = 0, @@ -574,7 +604,7 @@ void BlockingMutex::Lock() { void BlockingMutex::Unlock() { atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_); - u32 v = atomic_exchange(m, MtxUnlocked, memory_order_relaxed); + u32 v = atomic_exchange(m, MtxUnlocked, memory_order_release); CHECK_NE(v, MtxUnlocked); if (v == MtxSleeping) { #if SANITIZER_FREEBSD @@ -643,7 +673,7 @@ uptr internal_ptrace(int request, int pi uptr internal_waitpid(int pid, int *status, int options) { #if SANITIZER_NETBSD - return internal_syscall(SYSCALL(wait4), pid, status, options, + return internal_syscall_ptr(SYSCALL(wait4), pid, status, options, NULL /* rusage */); #else return internal_syscall(SYSCALL(wait4), pid, (uptr)status, options, @@ -661,7 +691,7 @@ uptr internal_getppid() { uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count) { #if SANITIZER_NETBSD - return internal_syscall(SYSCALL(getdents), fd, dirp, (uptr)count); + return internal_syscall_ptr(SYSCALL(getdents), fd, dirp, (uptr)count); #elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS return internal_syscall(SYSCALL(getdents64), fd, (uptr)dirp, count); #else @@ -684,7 +714,7 @@ uptr internal_prctl(int option, uptr arg #endif uptr internal_sigaltstack(const void *ss, void *oss) { - return internal_syscall(SYSCALL(sigaltstack), (uptr)ss, (uptr)oss); + return internal_syscall_ptr(SYSCALL(sigaltstack), (uptr)ss, (uptr)oss); } int internal_fork() {