diff options
| -rw-r--r-- | libartbase/base/memfd.cc | 16 | ||||
| -rw-r--r-- | libartbase/base/memfd.h | 3 |
2 files changed, 18 insertions, 1 deletions
diff --git a/libartbase/base/memfd.cc b/libartbase/base/memfd.cc index 1afcd7b311..7c2040147e 100644 --- a/libartbase/base/memfd.cc +++ b/libartbase/base/memfd.cc @@ -17,7 +17,9 @@ #include "memfd.h" #include <errno.h> +#include <stdio.h> #include <sys/syscall.h> +#include <sys/utsname.h> #include <unistd.h> #include "macros.h" @@ -37,6 +39,20 @@ namespace art { #if defined(__NR_memfd_create) int memfd_create(const char* name, unsigned int flags) { + // Check kernel version supports memfd_create(). Some older kernels segfault executing + // memfd_create() rather than returning ENOSYS (b/116769556). + static constexpr int kRequiredMajor = 3; + static constexpr int kRequiredMinor = 17; + struct utsname uts; + int major, minor; + if (uname(&uts) != 0 || + strcmp(uts.sysname, "Linux") != 0 || + sscanf(uts.release, "%d.%d", &major, &minor) != 2 || + (major < kRequiredMajor || (major == kRequiredMajor && minor < kRequiredMinor))) { + errno = ENOSYS; + return -1; + } + return syscall(__NR_memfd_create, name, flags); } diff --git a/libartbase/base/memfd.h b/libartbase/base/memfd.h index 4367198185..91db0b2d8f 100644 --- a/libartbase/base/memfd.h +++ b/libartbase/base/memfd.h @@ -19,7 +19,8 @@ namespace art { - // Call memfd(2) if available on platform and return result. +// Call memfd(2) if available on platform and return result. This call also makes a kernel version +// check for safety on older kernels (b/116769556).. int memfd_create(const char* name, unsigned int flags); } // namespace art |