[compiler-rt] Use uname syscall in GetKernelAreaSize()

Commit 5f5fb56c68 ("[compiler-rt] Intercept the uname() function")
broke clang-cmake-thumbv7-full-sh build:

http://lab.llvm.org:8011/builders/clang-cmake-thumbv7-full-sh/builds/4296

This also affects i386.

The reason is that intercepted uname() is called by GetKernelAreaSize()
during ASAN initialization on 32-bit platforms, but the respective
interceptor is not initialized yet at this point, leading to null
pointer dereference.

Introduce internal_uname() wrapper around uname syscall, and use it in
GetKernelAreaSize() and in FixedCVE_2016_2143().

Author: Ilya Leoshkevich
Reviewed By: Evgenii Stepanov

Differential Revision: https://reviews.llvm.org/D76776
This commit is contained in:
Ilya Leoshkevich 2020-03-26 13:35:09 +01:00 committed by Ulrich Weigand
parent dc37287320
commit 2ca7fe3796
3 changed files with 11 additions and 8 deletions

View File

@ -1015,9 +1015,8 @@ static uptr GetKernelAreaSize() {
// is modified (e.g. under schroot) so check this as well.
struct utsname uname_info;
int pers = personality(0xffffffffUL);
if (!(pers & PER_MASK)
&& uname(&uname_info) == 0
&& internal_strstr(uname_info.machine, "64"))
if (!(pers & PER_MASK) && internal_uname(&uname_info) == 0 &&
internal_strstr(uname_info.machine, "64"))
return 0;
#endif // SANITIZER_ANDROID
@ -1629,6 +1628,12 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
}
#endif // defined(__x86_64__) && SANITIZER_LINUX
#if SANITIZER_LINUX
int internal_uname(struct utsname *buf) {
return internal_syscall(SYSCALL(uname), buf);
}
#endif
#if SANITIZER_ANDROID
#if __ANDROID_API__ < 21
extern "C" __attribute__((weak)) int dl_iterate_phdr(

View File

@ -25,6 +25,7 @@
#include "sanitizer_posix.h"
struct link_map; // Opaque type returned by dlopen().
struct utsname;
namespace __sanitizer {
// Dirent structure for getdents(). Note that this structure is different from
@ -64,6 +65,7 @@ void internal_sigdelset(__sanitizer_sigset_t *set, int signum);
|| defined(__arm__)
uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
int *parent_tidptr, void *newtls, int *child_tidptr);
int internal_uname(struct utsname *buf);
#endif
#elif SANITIZER_FREEBSD
void internal_sigdelset(__sanitizer_sigset_t *set, int signum);

View File

@ -123,12 +123,8 @@ static bool FixedCVE_2016_2143() {
// adjust this for their own kernels.
struct utsname buf;
unsigned int major, minor, patch = 0;
// Depending on the concrete sanitizer being used, uname may or may not
// be intercepted. Make sure we use the libc version in either case.
using Uname = int (*)(struct utsname *);
Uname uname = reinterpret_cast<Uname>(dlsym(RTLD_NEXT, "uname"));
// This should never fail, but just in case...
if (uname == nullptr || uname(&buf))
if (internal_uname(&buf))
return false;
const char *ptr = buf.release;
major = internal_simple_strtoll(ptr, &ptr, 10);