ART: Add version check for memfd_create()
Add a kernel version check in the ART shim for memfd_create().
Bug: b/116769556
Test: Tested on go/lem (3.14 kernel)
Change-Id: I1fd5cabc6705f856bea8044ca82274020ff84914
diff --git a/libartbase/base/memfd.cc b/libartbase/base/memfd.cc
index 1afcd7b..7c20401 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 @@
#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 4367198..91db0b2 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