1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "memfd.h" 18 19 #include <errno.h> 20 #include <stdio.h> 21 #if !defined(_WIN32) 22 #include <fcntl.h> 23 #include <sys/syscall.h> 24 #include <sys/utsname.h> 25 #include <unistd.h> 26 #endif 27 #if defined(__BIONIC__) 28 #include <linux/memfd.h> // To access memfd flags. 29 #endif 30 31 #include <android-base/logging.h> 32 #include <android-base/unique_fd.h> 33 34 #include "macros.h" 35 36 37 // When building for linux host, glibc in prebuilts does not include memfd_create system call 38 // number. As a temporary testing measure, we add the definition here. 39 #if defined(__linux__) && !defined(__NR_memfd_create) 40 #if defined(__x86_64__) 41 #define __NR_memfd_create 319 42 #elif defined(__i386__) 43 #define __NR_memfd_create 356 44 #endif // defined(__i386__) 45 #endif // defined(__linux__) && !defined(__NR_memfd_create) 46 47 namespace art { 48 49 #if defined(__NR_memfd_create) 50 51 int memfd_create(const char* name, unsigned int flags) { 52 // Check kernel version supports memfd_create(). Some older kernels segfault executing 53 // memfd_create() rather than returning ENOSYS (b/116769556). 54 static constexpr int kRequiredMajor = 3; 55 static constexpr int kRequiredMinor = 17; 56 struct utsname uts; 57 int major, minor; 58 if (uname(&uts) != 0 || 59 strcmp(uts.sysname, "Linux") != 0 || 60 sscanf(uts.release, "%d.%d", &major, &minor) != 2 || 61 (major < kRequiredMajor || (major == kRequiredMajor && minor < kRequiredMinor))) { 62 errno = ENOSYS; 63 return -1; 64 } 65 66 return syscall(__NR_memfd_create, name, flags); 67 } 68 69 #else // __NR_memfd_create 70 71 int memfd_create(const char* name ATTRIBUTE_UNUSED, unsigned int flags ATTRIBUTE_UNUSED) { 72 errno = ENOSYS; 73 return -1; 74 } 75 76 #endif // __NR_memfd_create 77 78 // This is a wrapper that will attempt to simulate memfd_create if normal running fails. 79 int memfd_create_compat(const char* name, unsigned int flags) { 80 int res = memfd_create(name, flags); 81 if (res >= 0) { 82 return res; 83 } 84 #if !defined(_WIN32) 85 // Try to create an anonymous file with tmpfile that we can use instead. 86 if (flags == 0) { 87 FILE* file = tmpfile(); 88 if (file != nullptr) { 89 // We want the normal 'dup' semantics since memfd_create without any flags isn't CLOEXEC. 90 // Unfortunately on some android targets we will compiler error if we use dup directly and so 91 // need to use fcntl. 92 int nfd = fcntl(fileno(file), F_DUPFD, /*lowest allowed fd*/ 0); 93 fclose(file); 94 return nfd; 95 } 96 } 97 #endif 98 return res; 99 } 100 101 #if defined(__BIONIC__) 102 103 static bool IsSealFutureWriteSupportedInternal() { 104 android::base::unique_fd fd(art::memfd_create("test_android_memfd", MFD_ALLOW_SEALING)); 105 if (fd == -1) { 106 LOG(INFO) << "memfd_create failed: " << strerror(errno) << ", no memfd support."; 107 return false; 108 } 109 110 if (fcntl(fd, F_ADD_SEALS, F_SEAL_FUTURE_WRITE) == -1) { 111 LOG(INFO) << "fcntl(F_ADD_SEALS) failed: " << strerror(errno) << ", no memfd support."; 112 return false; 113 } 114 115 LOG(INFO) << "Using memfd for future sealing"; 116 return true; 117 } 118 119 bool IsSealFutureWriteSupported() { 120 static bool is_seal_future_write_supported = IsSealFutureWriteSupportedInternal(); 121 return is_seal_future_write_supported; 122 } 123 124 #else 125 126 bool IsSealFutureWriteSupported() { 127 return false; 128 } 129 130 #endif 131 132 } // namespace art 133