sanitizer_common: Introduce internal_madvise and start using it.

A recent change to sanitizer_common caused us to issue the syscall
madvise(MADV_HUGEPAGE) during HWASAN initialization. This may lead to a
problem if madvise is instrumented (e.g. because libc is instrumented
or the user intercepted it). For example, on Android the syscall may
fail if the kernel does not support transparent hugepages, which leads
to an attempt to set errno in a HWASAN instrumented function. Avoid
this problem by introducing a syscall wrapper and using it to issue
this syscall.

Tested only on Linux; includes untested updates for the other
platforms.

Differential Revision: https://reviews.llvm.org/D85870
This commit is contained in:
Peter Collingbourne 2020-08-12 19:32:15 -07:00
parent 114c9fa0e4
commit 9f8c4039f2
7 changed files with 32 additions and 15 deletions

View File

@ -187,6 +187,10 @@ uptr internal_munmap(void *addr, uptr length) {
int internal_mprotect(void *addr, uptr length, int prot) {
return internal_syscall(SYSCALL(mprotect), (uptr)addr, length, prot);
}
int internal_madvise(uptr addr, uptr length, int advice) {
return internal_syscall(SYSCALL(madvise), addr, length, advice);
}
#endif
uptr internal_close(fd_t fd) {

View File

@ -137,6 +137,10 @@ int internal_mprotect(void *addr, uptr length, int prot) {
return mprotect(addr, length, prot);
}
int internal_madvise(uptr addr, uptr length, int advice) {
return madvise((void *)addr, length, advice);
}
uptr internal_close(fd_t fd) {
return close(fd);
}

View File

@ -110,6 +110,11 @@ int internal_mprotect(void *addr, uptr length, int prot) {
return _REAL(mprotect, addr, length, prot);
}
int internal_madvise(uptr addr, uptr length, int advice) {
DEFINE__REAL(int, madvise, void *a, uptr b, int c);
return _REAL(madvise, (void *)addr, length, advice);
}
uptr internal_close(fd_t fd) {
CHECK(&_sys_close);
return _sys_close(fd);

View File

@ -52,6 +52,10 @@ int internal_mprotect(void *addr, uptr length, int prot) {
return mprotect(addr, length, prot);
}
int internal_madvise(uptr addr, uptr length, int advice) {
return madvise((void *)addr, length, advice);
}
int internal_sysctlbyname(const char *sname, void *oldp, uptr *oldlenp,
const void *newp, uptr newlen) {
Printf("internal_sysctlbyname not implemented for OpenBSD");

View File

@ -42,6 +42,7 @@ uptr internal_mmap(void *addr, uptr length, int prot, int flags,
int fd, u64 offset);
uptr internal_munmap(void *addr, uptr length);
int internal_mprotect(void *addr, uptr length, int prot);
int internal_madvise(uptr addr, uptr length, int advice);
// OS
uptr internal_filesize(fd_t fd); // -1 on error.

View File

@ -44,12 +44,6 @@
#define MAP_NORESERVE 0
#endif
#if SANITIZER_SOLARIS
// Illumos' declaration of madvie cannot be made visible if _XOPEN_SOURCE
// is defined as g++ does on Solaris.
extern "C" int madvise(void *, size_t, int);
#endif
typedef void (*sa_sigaction_t)(int, siginfo_t *, void *);
namespace __sanitizer {
@ -67,27 +61,24 @@ void ReleaseMemoryPagesToOS(uptr beg, uptr end) {
uptr beg_aligned = RoundUpTo(beg, page_size);
uptr end_aligned = RoundDownTo(end, page_size);
if (beg_aligned < end_aligned)
// In the default Solaris compilation environment, madvise() is declared
// to take a caddr_t arg; casting it to void * results in an invalid
// conversion error, so use char * instead.
madvise((char *)beg_aligned, end_aligned - beg_aligned,
SANITIZER_MADVISE_DONTNEED);
internal_madvise(beg_aligned, end_aligned - beg_aligned,
SANITIZER_MADVISE_DONTNEED);
}
void SetShadowRegionHugePageMode(uptr addr, uptr size) {
#ifdef MADV_NOHUGEPAGE // May not be defined on old systems.
if (common_flags()->no_huge_pages_for_shadow)
madvise((char *)addr, size, MADV_NOHUGEPAGE);
internal_madvise(addr, size, MADV_NOHUGEPAGE);
else
madvise((char *)addr, size, MADV_HUGEPAGE);
internal_madvise(addr, size, MADV_HUGEPAGE);
#endif // MADV_NOHUGEPAGE
}
bool DontDumpShadowMemory(uptr addr, uptr length) {
#if defined(MADV_DONTDUMP)
return madvise((char *)addr, length, MADV_DONTDUMP) == 0;
return internal_madvise(addr, length, MADV_DONTDUMP) == 0;
#elif defined(MADV_NOCORE)
return madvise((char *)addr, length, MADV_NOCORE) == 0;
return internal_madvise(addr, length, MADV_NOCORE) == 0;
#else
return true;
#endif // MADV_DONTDUMP

View File

@ -74,6 +74,14 @@ DECLARE__REAL_AND_INTERNAL(int, mprotect, void *addr, uptr length, int prot) {
return _REAL(mprotect)(addr, length, prot);
}
// Illumos' declaration of madvise cannot be made visible if _XOPEN_SOURCE
// is defined as g++ does on Solaris.
extern "C" int madvise(caddr_t, size_t, int);
int internal_madvise(uptr addr, uptr length, int advice) {
return madvise((caddr_t)addr, length, advice);
}
DECLARE__REAL_AND_INTERNAL(uptr, close, fd_t fd) {
return _REAL(close)(fd);
}