Implement SharedFD::MemfdCreate.

This makes it convenient to create SharedFDs for in-memory-only files.

Android currently has host prebuilts of glibc 2.15 and 2.17, but
memfd_create was only added in glibc 2.27. It was defined in Linux 3.17,
so we consider it safe to use the low-level arbitrary syscall wrapper.

Test: N/A
Change-Id: Id7de8f89537b2b8d0ed9b171bfb37bf770596386
diff --git a/common/libs/fs/shared_fd.cpp b/common/libs/fs/shared_fd.cpp
index 2f6d100..b85cf7c 100644
--- a/common/libs/fs/shared_fd.cpp
+++ b/common/libs/fs/shared_fd.cpp
@@ -17,6 +17,8 @@
 
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/mman.h>
+#include <sys/syscall.h>
 #include <cstddef>
 #include <errno.h>
 #include <fcntl.h>
@@ -52,6 +54,34 @@
     }
   }
 }
+
+/*
+ * Android currently has host prebuilts of glibc 2.15 and 2.17, but
+ * memfd_create was only added in glibc 2.27. It was defined in Linux 3.17,
+ * so we consider it safe to use the low-level arbitrary syscall wrapper.
+ */
+#ifndef __NR_memfd_create
+# if defined(__x86_64__)
+#  define __NR_memfd_create 319
+# elif defined(__i386__)
+#  define __NR_memfd_create 356
+# elif defined(__aarch64__)
+#  define __NR_memfd_create 279
+# else
+/* No interest in other architectures. */
+#  error "Unknown architecture."
+# endif
+#endif
+
+int memfd_create_wrapper(const char* name, unsigned int flags) {
+#ifdef CUTTLEFISH_HOST
+  // TODO(schuffelen): Use memfd_create with a newer host libc.
+  return syscall(__NR_memfd_create, name, flags);
+#else
+  return memfd_create(name, flags);
+#endif
+}
+
 }  // namespace
 
 namespace cvd {
@@ -256,6 +286,12 @@
   return std::shared_ptr<FileInstance>(new FileInstance(fd, errno));
 }
 
+SharedFD SharedFD::MemfdCreate(const char* name, unsigned int flags) {
+  int fd = memfd_create_wrapper(name, flags);
+  int error_num = errno;
+  return std::shared_ptr<FileInstance>(new FileInstance(fd, error_num));
+}
+
 bool SharedFD::SocketPair(int domain, int type, int protocol,
                           SharedFD* fd0, SharedFD* fd1) {
   int fds[2];
diff --git a/common/libs/fs/shared_fd.h b/common/libs/fs/shared_fd.h
index eec17b1..044c7cc 100644
--- a/common/libs/fs/shared_fd.h
+++ b/common/libs/fs/shared_fd.h
@@ -145,6 +145,7 @@
   static bool Pipe(SharedFD* fd0, SharedFD* fd1);
   static SharedFD Event(int initval = 0, int flags = 0);
   static SharedFD Epoll(int flags = 0);
+  static SharedFD MemfdCreate(const char* name, unsigned int flags = 0);
   static bool SocketPair(int domain, int type, int protocol, SharedFD* fd0,
                          SharedFD* fd1);
   static SharedFD Socket(int domain, int socket_type, int protocol);