summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libartbase/base/memfd.cc16
-rw-r--r--libartbase/base/memfd.h3
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