android-8.1.0_r81 patches
This commit is contained in:
318
android-8.1.0_r81/system/core/0005-memfd-support.patch
Normal file
318
android-8.1.0_r81/system/core/0005-memfd-support.patch
Normal file
@@ -0,0 +1,318 @@
|
||||
From 5f3272be10ea27866e5e0b30bfc921befde70ab2 Mon Sep 17 00:00:00 2001
|
||||
From: Ziyang Zhou <ziyang.zhou@outlook.com>
|
||||
Date: Sun, 3 Jul 2022 11:22:31 +0800
|
||||
Subject: [PATCH 5/6] memfd support
|
||||
|
||||
---
|
||||
libcutils/Android.bp | 4 +-
|
||||
libcutils/{ashmem-dev.c => ashmem-dev.cpp} | 51 +++++-
|
||||
libcutils/ashmem-hack.inc | 172 +++++++++++++++++++++
|
||||
3 files changed, 223 insertions(+), 4 deletions(-)
|
||||
rename libcutils/{ashmem-dev.c => ashmem-dev.cpp} (79%)
|
||||
create mode 100644 libcutils/ashmem-hack.inc
|
||||
|
||||
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
|
||||
index d00ff5f96..93f2658c7 100644
|
||||
--- a/libcutils/Android.bp
|
||||
+++ b/libcutils/Android.bp
|
||||
@@ -106,7 +106,7 @@ cc_library {
|
||||
android: {
|
||||
srcs: libcutils_nonwindows_sources + [
|
||||
"android_reboot.c",
|
||||
- "ashmem-dev.c",
|
||||
+ "ashmem-dev.cpp",
|
||||
"klog.cpp",
|
||||
"partition_utils.c",
|
||||
"properties.cpp",
|
||||
@@ -148,7 +148,7 @@ cc_library {
|
||||
},
|
||||
},
|
||||
|
||||
- shared_libs: ["liblog"],
|
||||
+ shared_libs: ["liblog", "libbase"],
|
||||
header_libs: [
|
||||
"libcutils_headers",
|
||||
"libutils_headers",
|
||||
diff --git a/libcutils/ashmem-dev.c b/libcutils/ashmem-dev.cpp
|
||||
similarity index 79%
|
||||
rename from libcutils/ashmem-dev.c
|
||||
rename to libcutils/ashmem-dev.cpp
|
||||
index b4abb79d8..137c0280c 100644
|
||||
--- a/libcutils/ashmem-dev.c
|
||||
+++ b/libcutils/ashmem-dev.cpp
|
||||
@@ -135,8 +135,14 @@ static int __ashmem_is_ashmem(int fd, int fatal)
|
||||
return -1;
|
||||
}
|
||||
|
||||
+#include "ashmem-hack.inc"
|
||||
+
|
||||
int ashmem_valid(int fd)
|
||||
{
|
||||
+ if (has_memfd_support() && !memfd_is_ashmem(fd)) {
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
return __ashmem_is_ashmem(fd, 0) >= 0;
|
||||
}
|
||||
|
||||
@@ -151,6 +157,10 @@ int ashmem_create_region(const char *name, size_t size)
|
||||
{
|
||||
int ret, save_errno;
|
||||
|
||||
+ if (has_memfd_support()) {
|
||||
+ return memfd_create_region(name ? name : "none", size);
|
||||
+ }
|
||||
+
|
||||
int fd = __ashmem_open();
|
||||
if (fd < 0) {
|
||||
return fd;
|
||||
@@ -182,6 +192,10 @@ error:
|
||||
|
||||
int ashmem_set_prot_region(int fd, int prot)
|
||||
{
|
||||
+ if (has_memfd_support() && !memfd_is_ashmem(fd)) {
|
||||
+ return memfd_set_prot_region(fd, prot);
|
||||
+ }
|
||||
+
|
||||
int ret = __ashmem_is_ashmem(fd, 1);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
@@ -192,7 +206,16 @@ int ashmem_set_prot_region(int fd, int prot)
|
||||
|
||||
int ashmem_pin_region(int fd, size_t offset, size_t len)
|
||||
{
|
||||
- struct ashmem_pin pin = { offset, len };
|
||||
+ if (!pin_deprecation_warn || debug_log) {
|
||||
+ ALOGE("Pinning is deprecated since Android Q. Please use trim or other methods.\n");
|
||||
+ pin_deprecation_warn = true;
|
||||
+ }
|
||||
+
|
||||
+ if (has_memfd_support() && !memfd_is_ashmem(fd)) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ struct ashmem_pin pin = { static_cast<uint32_t>(offset), static_cast<uint32_t>(len) };
|
||||
|
||||
int ret = __ashmem_is_ashmem(fd, 1);
|
||||
if (ret < 0) {
|
||||
@@ -204,7 +227,16 @@ int ashmem_pin_region(int fd, size_t offset, size_t len)
|
||||
|
||||
int ashmem_unpin_region(int fd, size_t offset, size_t len)
|
||||
{
|
||||
- struct ashmem_pin pin = { offset, len };
|
||||
+ if (!pin_deprecation_warn || debug_log) {
|
||||
+ ALOGE("Pinning is deprecated since Android Q. Please use trim or other methods.\n");
|
||||
+ pin_deprecation_warn = true;
|
||||
+ }
|
||||
+
|
||||
+ if (has_memfd_support() && !memfd_is_ashmem(fd)) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ struct ashmem_pin pin = { static_cast<uint32_t>(offset), static_cast<uint32_t>(len) };
|
||||
|
||||
int ret = __ashmem_is_ashmem(fd, 1);
|
||||
if (ret < 0) {
|
||||
@@ -216,6 +248,21 @@ int ashmem_unpin_region(int fd, size_t offset, size_t len)
|
||||
|
||||
int ashmem_get_size_region(int fd)
|
||||
{
|
||||
+ if (has_memfd_support() && !memfd_is_ashmem(fd)) {
|
||||
+ struct stat sb;
|
||||
+
|
||||
+ if (fstat(fd, &sb) == -1) {
|
||||
+ ALOGE("ashmem_get_size_region(%d): fstat failed: %s\n", fd, strerror(errno));
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ if (debug_log) {
|
||||
+ ALOGD("ashmem_get_size_region(%d): %d\n", fd, static_cast<int>(sb.st_size));
|
||||
+ }
|
||||
+
|
||||
+ return sb.st_size;
|
||||
+ }
|
||||
+
|
||||
int ret = __ashmem_is_ashmem(fd, 1);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
diff --git a/libcutils/ashmem-hack.inc b/libcutils/ashmem-hack.inc
|
||||
new file mode 100644
|
||||
index 000000000..8526c85be
|
||||
--- /dev/null
|
||||
+++ b/libcutils/ashmem-hack.inc
|
||||
@@ -0,0 +1,172 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2008 The Android Open Source Project
|
||||
+ *
|
||||
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
||||
+ * you may not use this file except in compliance with the License.
|
||||
+ * You may obtain a copy of the License at
|
||||
+ *
|
||||
+ * http://www.apache.org/licenses/LICENSE-2.0
|
||||
+ *
|
||||
+ * Unless required by applicable law or agreed to in writing, software
|
||||
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
||||
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
+ * See the License for the specific language governing permissions and
|
||||
+ * limitations under the License.
|
||||
+ */
|
||||
+
|
||||
+#include <cutils/ashmem.h>
|
||||
+
|
||||
+#include <errno.h>
|
||||
+#include <fcntl.h>
|
||||
+#include <linux/ashmem.h>
|
||||
+#include <linux/memfd.h>
|
||||
+#include <log/log.h>
|
||||
+#include <pthread.h>
|
||||
+#include <stdio.h>
|
||||
+#include <string.h>
|
||||
+#include <sys/ioctl.h>
|
||||
+#include <sys/mman.h>
|
||||
+#include <sys/stat.h>
|
||||
+#include <sys/syscall.h>
|
||||
+#include <sys/sysmacros.h>
|
||||
+#include <sys/types.h>
|
||||
+#include <unistd.h>
|
||||
+
|
||||
+#include <android-base/file.h>
|
||||
+#include <android-base/properties.h>
|
||||
+#include <android-base/strings.h>
|
||||
+#include <android-base/unique_fd.h>
|
||||
+
|
||||
+/* Will be added to UAPI once upstream change is merged */
|
||||
+#define F_SEAL_FUTURE_WRITE 0x0010
|
||||
+
|
||||
+/*
|
||||
+ * The minimum vendor API level at and after which it is safe to use memfd.
|
||||
+ * This is to facilitate deprecation of ashmem.
|
||||
+ */
|
||||
+#define MIN_MEMFD_VENDOR_API_LEVEL 29
|
||||
+#define MIN_MEMFD_VENDOR_API_LEVEL_CHAR 'Q'
|
||||
+
|
||||
+/*
|
||||
+ * has_memfd_support() determines if the device can use memfd. memfd support
|
||||
+ * has been there for long time, but certain things in it may be missing. We
|
||||
+ * check for needed support in it. Also we check if the VNDK version of
|
||||
+ * libcutils being used is new enough, if its not, then we cannot use memfd
|
||||
+ * since the older copies may be using ashmem so we just use ashmem. Once all
|
||||
+ * Android devices that are getting updates are new enough (ex, they were
|
||||
+ * originally shipped with Android release > P), then we can just use memfd and
|
||||
+ * delete all ashmem code from libcutils (while preserving the interface).
|
||||
+ *
|
||||
+ * NOTE:
|
||||
+ * The sys.use_memfd property is set by default to false in Android
|
||||
+ * to temporarily disable memfd, till vendor and apps are ready for it.
|
||||
+ * The main issue: either apps or vendor processes can directly make ashmem
|
||||
+ * IOCTLs on FDs they receive by assuming they are ashmem, without going
|
||||
+ * through libcutils. Such fds could have very well be originally created with
|
||||
+ * libcutils hence they could be memfd. Thus the IOCTLs will break.
|
||||
+ *
|
||||
+ * Set default value of sys.use_memfd property to true once the issue is
|
||||
+ * resolved, so that the code can then self-detect if kernel support is present
|
||||
+ * on the device. The property can also set to true from adb shell, for
|
||||
+ * debugging.
|
||||
+ */
|
||||
+
|
||||
+static bool debug_log = false; /* set to true for verbose logging and other debug */
|
||||
+static bool pin_deprecation_warn = true; /* Log the pin deprecation warning only once */
|
||||
+
|
||||
+
|
||||
+/* Determine if memfd can be supported. This is just one-time hardwork
|
||||
+ * which will be cached by the caller.
|
||||
+ */
|
||||
+static bool __has_memfd_support() {
|
||||
+ /* Used to turn on/off the detection at runtime, in the future this
|
||||
+ * property will be removed once we switch everything over to ashmem.
|
||||
+ * Currently it is used only for debugging to switch the system over.
|
||||
+ */
|
||||
+ if (!android::base::GetBoolProperty("sys.use_memfd", false)) {
|
||||
+ if (debug_log) {
|
||||
+ ALOGD("sys.use_memfd=false so memfd disabled\n");
|
||||
+ }
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ // Check if kernel support exists, otherwise fall back to ashmem.
|
||||
+ // This code needs to build on old API levels, so we can't use the libc
|
||||
+ // wrapper.
|
||||
+ android::base::unique_fd fd(
|
||||
+ syscall(__NR_memfd_create, "test_android_memfd", MFD_CLOEXEC | MFD_ALLOW_SEALING));
|
||||
+ if (fd == -1) {
|
||||
+ ALOGE("memfd_create failed: %s, no memfd support.\n", strerror(errno));
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ if (fcntl(fd, F_ADD_SEALS, F_SEAL_FUTURE_WRITE) == -1) {
|
||||
+ ALOGE("fcntl(F_ADD_SEALS) failed: %s, no memfd support.\n", strerror(errno));
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ if (debug_log) {
|
||||
+ ALOGD("memfd: device has memfd support, using it\n");
|
||||
+ }
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+static bool has_memfd_support() {
|
||||
+ /* memfd_supported is the initial global per-process state of what is known
|
||||
+ * about memfd.
|
||||
+ */
|
||||
+ static bool memfd_supported = __has_memfd_support();
|
||||
+
|
||||
+ return memfd_supported;
|
||||
+}
|
||||
+
|
||||
+static bool memfd_is_ashmem(int fd) {
|
||||
+ static bool fd_check_error_once = false;
|
||||
+
|
||||
+ if (__ashmem_is_ashmem(fd, 0) == 0) {
|
||||
+ if (!fd_check_error_once) {
|
||||
+ ALOGE("memfd: memfd expected but ashmem fd used - please use libcutils.\n");
|
||||
+ fd_check_error_once = true;
|
||||
+ }
|
||||
+
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
+static int memfd_create_region(const char* name, size_t size) {
|
||||
+ // This code needs to build on old API levels, so we can't use the libc
|
||||
+ // wrapper.
|
||||
+ android::base::unique_fd fd(syscall(__NR_memfd_create, name, MFD_CLOEXEC | MFD_ALLOW_SEALING));
|
||||
+
|
||||
+ if (fd == -1) {
|
||||
+ ALOGE("memfd_create(%s, %zd) failed: %s\n", name, size, strerror(errno));
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ if (ftruncate(fd, size) == -1) {
|
||||
+ ALOGE("ftruncate(%s, %zd) failed for memfd creation: %s\n", name, size, strerror(errno));
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ if (debug_log) {
|
||||
+ ALOGE("memfd_create(%s, %zd) success. fd=%d\n", name, size, fd.get());
|
||||
+ }
|
||||
+ return fd.release();
|
||||
+}
|
||||
+
|
||||
+static int memfd_set_prot_region(int fd, int prot) {
|
||||
+ /* Only proceed if an fd needs to be write-protected */
|
||||
+ if (prot & PROT_WRITE) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ if (fcntl(fd, F_ADD_SEALS, F_SEAL_FUTURE_WRITE) == -1) {
|
||||
+ ALOGE("memfd_set_prot_region(%d, %d): F_SEAL_FUTURE_WRITE seal failed: %s\n", fd, prot,
|
||||
+ strerror(errno));
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
--
|
||||
2.34.1
|
||||
|
||||
Reference in New Issue
Block a user