[sanitizer] Use canonical syscalls everywhere

These "new" syscalls have been added in 2.6.16, more than 16 years ago.
Surely that's enough time to migrate. Glibc 2.33 is using them on both
i386 and x86_64. Android has an selinux filter to block the legacy
syscalls in the apps.

Differential Revision: https://reviews.llvm.org/D124212
This commit is contained in:
Evgenii Stepanov 2022-04-21 15:17:29 -07:00
parent 3e8560f890
commit 34b676eb60
2 changed files with 37 additions and 61 deletions

View File

@ -233,7 +233,7 @@ uptr internal_close(fd_t fd) {
} }
uptr internal_open(const char *filename, int flags) { uptr internal_open(const char *filename, int flags) {
#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS # if SANITIZER_LINUX
return internal_syscall(SYSCALL(openat), AT_FDCWD, (uptr)filename, flags); return internal_syscall(SYSCALL(openat), AT_FDCWD, (uptr)filename, flags);
#else #else
return internal_syscall(SYSCALL(open), (uptr)filename, flags); return internal_syscall(SYSCALL(open), (uptr)filename, flags);
@ -241,7 +241,7 @@ uptr internal_open(const char *filename, int flags) {
} }
uptr internal_open(const char *filename, int flags, u32 mode) { uptr internal_open(const char *filename, int flags, u32 mode) {
#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS # if SANITIZER_LINUX
return internal_syscall(SYSCALL(openat), AT_FDCWD, (uptr)filename, flags, return internal_syscall(SYSCALL(openat), AT_FDCWD, (uptr)filename, flags,
mode); mode);
#else #else
@ -342,50 +342,46 @@ static void kernel_stat_to_stat(struct kernel_stat *in, struct stat *out) {
uptr internal_stat(const char *path, void *buf) { uptr internal_stat(const char *path, void *buf) {
#if SANITIZER_FREEBSD #if SANITIZER_FREEBSD
return internal_syscall(SYSCALL(fstatat), AT_FDCWD, (uptr)path, (uptr)buf, 0); return internal_syscall(SYSCALL(fstatat), AT_FDCWD, (uptr)path, (uptr)buf, 0);
#elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS # elif SANITIZER_LINUX
# if SANITIZER_WORDSIZE == 64
return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path, (uptr)buf, return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path, (uptr)buf,
0); 0);
#elif SANITIZER_LINUX_USES_64BIT_SYSCALLS # else
# if defined(__mips64) struct stat64 buf64;
// For mips64, stat syscall fills buffer in the format of kernel_stat int res = internal_syscall(SYSCALL(fstatat64), AT_FDCWD, (uptr)path,
struct kernel_stat kbuf; (uptr)&buf64, 0);
int res = internal_syscall(SYSCALL(stat), path, &kbuf); stat64_to_stat(&buf64, (struct stat *)buf);
kernel_stat_to_stat(&kbuf, (struct stat *)buf);
return res; return res;
# else # endif
return internal_syscall(SYSCALL(stat), (uptr)path, (uptr)buf); # else
# endif
#else
struct stat64 buf64; struct stat64 buf64;
int res = internal_syscall(SYSCALL(stat64), path, &buf64); int res = internal_syscall(SYSCALL(stat64), path, &buf64);
stat64_to_stat(&buf64, (struct stat *)buf); stat64_to_stat(&buf64, (struct stat *)buf);
return res; return res;
#endif # endif
} }
uptr internal_lstat(const char *path, void *buf) { uptr internal_lstat(const char *path, void *buf) {
#if SANITIZER_FREEBSD #if SANITIZER_FREEBSD
return internal_syscall(SYSCALL(fstatat), AT_FDCWD, (uptr)path, (uptr)buf, return internal_syscall(SYSCALL(fstatat), AT_FDCWD, (uptr)path, (uptr)buf,
AT_SYMLINK_NOFOLLOW); AT_SYMLINK_NOFOLLOW);
#elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS # elif SANITIZER_LINUX
# if defined(_LP64)
return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path, (uptr)buf, return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path, (uptr)buf,
AT_SYMLINK_NOFOLLOW); AT_SYMLINK_NOFOLLOW);
#elif SANITIZER_LINUX_USES_64BIT_SYSCALLS # else
# if SANITIZER_MIPS64 struct stat64 buf64;
// For mips64, lstat syscall fills buffer in the format of kernel_stat int res = internal_syscall(SYSCALL(fstatat64), AT_FDCWD, (uptr)path,
struct kernel_stat kbuf; (uptr)&buf64, AT_SYMLINK_NOFOLLOW);
int res = internal_syscall(SYSCALL(lstat), path, &kbuf); stat64_to_stat(&buf64, (struct stat *)buf);
kernel_stat_to_stat(&kbuf, (struct stat *)buf);
return res; return res;
# else # endif
return internal_syscall(SYSCALL(lstat), (uptr)path, (uptr)buf); # else
# endif
#else
struct stat64 buf64; struct stat64 buf64;
int res = internal_syscall(SYSCALL(lstat64), path, &buf64); int res = internal_syscall(SYSCALL(lstat64), path, &buf64);
stat64_to_stat(&buf64, (struct stat *)buf); stat64_to_stat(&buf64, (struct stat *)buf);
return res; return res;
#endif # endif
} }
uptr internal_fstat(fd_t fd, void *buf) { uptr internal_fstat(fd_t fd, void *buf) {
@ -419,7 +415,7 @@ uptr internal_dup(int oldfd) {
} }
uptr internal_dup2(int oldfd, int newfd) { uptr internal_dup2(int oldfd, int newfd) {
#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS # if SANITIZER_LINUX
return internal_syscall(SYSCALL(dup3), oldfd, newfd, 0); return internal_syscall(SYSCALL(dup3), oldfd, newfd, 0);
#else #else
return internal_syscall(SYSCALL(dup2), oldfd, newfd); return internal_syscall(SYSCALL(dup2), oldfd, newfd);
@ -427,7 +423,7 @@ uptr internal_dup2(int oldfd, int newfd) {
} }
uptr internal_readlink(const char *path, char *buf, uptr bufsize) { uptr internal_readlink(const char *path, char *buf, uptr bufsize) {
#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS # if SANITIZER_LINUX
return internal_syscall(SYSCALL(readlinkat), AT_FDCWD, (uptr)path, (uptr)buf, return internal_syscall(SYSCALL(readlinkat), AT_FDCWD, (uptr)path, (uptr)buf,
bufsize); bufsize);
#else #else
@ -436,7 +432,7 @@ uptr internal_readlink(const char *path, char *buf, uptr bufsize) {
} }
uptr internal_unlink(const char *path) { uptr internal_unlink(const char *path) {
#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS # if SANITIZER_LINUX
return internal_syscall(SYSCALL(unlinkat), AT_FDCWD, (uptr)path, 0); return internal_syscall(SYSCALL(unlinkat), AT_FDCWD, (uptr)path, 0);
#else #else
return internal_syscall(SYSCALL(unlink), (uptr)path); return internal_syscall(SYSCALL(unlink), (uptr)path);
@ -447,12 +443,12 @@ uptr internal_rename(const char *oldpath, const char *newpath) {
#if defined(__riscv) && defined(__linux__) #if defined(__riscv) && defined(__linux__)
return internal_syscall(SYSCALL(renameat2), AT_FDCWD, (uptr)oldpath, AT_FDCWD, return internal_syscall(SYSCALL(renameat2), AT_FDCWD, (uptr)oldpath, AT_FDCWD,
(uptr)newpath, 0); (uptr)newpath, 0);
#elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS # elif SANITIZER_LINUX
return internal_syscall(SYSCALL(renameat), AT_FDCWD, (uptr)oldpath, AT_FDCWD, return internal_syscall(SYSCALL(renameat), AT_FDCWD, (uptr)oldpath, AT_FDCWD,
(uptr)newpath); (uptr)newpath);
#else # else
return internal_syscall(SYSCALL(rename), (uptr)oldpath, (uptr)newpath); return internal_syscall(SYSCALL(rename), (uptr)oldpath, (uptr)newpath);
#endif # endif
} }
uptr internal_sched_yield() { uptr internal_sched_yield() {
@ -489,11 +485,7 @@ bool FileExists(const char *filename) {
if (ShouldMockFailureToOpen(filename)) if (ShouldMockFailureToOpen(filename))
return false; return false;
struct stat st; struct stat st;
#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
if (internal_syscall(SYSCALL(newfstatat), AT_FDCWD, filename, &st, 0))
#else
if (internal_stat(filename, &st)) if (internal_stat(filename, &st))
#endif
return false; return false;
// Sanity check: filename is a regular file. // Sanity check: filename is a regular file.
return S_ISREG(st.st_mode); return S_ISREG(st.st_mode);
@ -501,11 +493,7 @@ bool FileExists(const char *filename) {
bool DirExists(const char *path) { bool DirExists(const char *path) {
struct stat st; struct stat st;
# if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
if (internal_syscall(SYSCALL(newfstatat), AT_FDCWD, path, &st, 0))
# else
if (internal_stat(path, &st)) if (internal_stat(path, &st))
# endif
return false; return false;
return S_ISDIR(st.st_mode); return S_ISDIR(st.st_mode);
} }
@ -709,17 +697,17 @@ void FutexWake(atomic_uint32_t *p, u32 count) {
// Not used // Not used
#else #else
struct linux_dirent { struct linux_dirent {
#if SANITIZER_X32 || defined(__aarch64__) || SANITIZER_RISCV64 # if SANITIZER_X32 || SANITIZER_LINUX
u64 d_ino; u64 d_ino;
u64 d_off; u64 d_off;
#else # else
unsigned long d_ino; unsigned long d_ino;
unsigned long d_off; unsigned long d_off;
#endif # endif
unsigned short d_reclen; unsigned short d_reclen;
#if defined(__aarch64__) || SANITIZER_RISCV64 # if SANITIZER_LINUX
unsigned char d_type; unsigned char d_type;
#endif # endif
char d_name[256]; char d_name[256];
}; };
#endif #endif
@ -755,11 +743,11 @@ int internal_dlinfo(void *handle, int request, void *p) {
uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count) { uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count) {
#if SANITIZER_FREEBSD #if SANITIZER_FREEBSD
return internal_syscall(SYSCALL(getdirentries), fd, (uptr)dirp, count, NULL); return internal_syscall(SYSCALL(getdirentries), fd, (uptr)dirp, count, NULL);
#elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS # elif SANITIZER_LINUX
return internal_syscall(SYSCALL(getdents64), fd, (uptr)dirp, count); return internal_syscall(SYSCALL(getdents64), fd, (uptr)dirp, count);
#else # else
return internal_syscall(SYSCALL(getdents), fd, (uptr)dirp, count); return internal_syscall(SYSCALL(getdents), fd, (uptr)dirp, count);
#endif # endif
} }
uptr internal_lseek(fd_t fd, OFF_T offset, int whence) { uptr internal_lseek(fd_t fd, OFF_T offset, int whence) {
@ -777,7 +765,7 @@ uptr internal_sigaltstack(const void *ss, void *oss) {
} }
int internal_fork() { int internal_fork() {
#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS # if SANITIZER_LINUX
return internal_syscall(SYSCALL(clone), SIGCHLD, 0); return internal_syscall(SYSCALL(clone), SIGCHLD, 0);
#else #else
return internal_syscall(SYSCALL(fork)); return internal_syscall(SYSCALL(fork));

View File

@ -298,18 +298,6 @@
# define SANITIZER_SIGN_EXTENDED_ADDRESSES 0 # define SANITIZER_SIGN_EXTENDED_ADDRESSES 0
#endif #endif
// The AArch64 and RISC-V linux ports use the canonical syscall set as
// mandated by the upstream linux community for all new ports. Other ports
// may still use legacy syscalls.
#ifndef SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
# if (defined(__aarch64__) || defined(__riscv) || defined(__hexagon__)) && \
SANITIZER_LINUX
# define SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 1
# else
# define SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 0
# endif
#endif
// udi16 syscalls can only be used when the following conditions are // udi16 syscalls can only be used when the following conditions are
// met: // met:
// * target is one of arm32, x86-32, sparc32, sh or m68k // * target is one of arm32, x86-32, sparc32, sh or m68k