Create a test ART apex that forces execution of JIT zygote. am: 4b762130d8
Original change: https://android-review.googlesource.com/c/platform/art/+/1906477
Change-Id: I3e0dd67a276f32a3c754f564143ea4799f6a19e3
diff --git a/compiler/art_standalone_compiler_tests.xml b/compiler/art_standalone_compiler_tests.xml
index c168677..4cf6e3d 100644
--- a/compiler/art_standalone_compiler_tests.xml
+++ b/compiler/art_standalone_compiler_tests.xml
@@ -42,4 +42,7 @@
<!-- ART Mainline Module (external (AOSP) version). -->
<option name="mainline-module-package-name" value="com.android.art" />
</object>
+
+ <!--- Only run tests if the device under test is SDK version 31 (Android 12) or above. -->
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController" />
</configuration>
diff --git a/dex2oat/art_standalone_dex2oat_tests.xml b/dex2oat/art_standalone_dex2oat_tests.xml
index be901b0..8f9689a 100644
--- a/dex2oat/art_standalone_dex2oat_tests.xml
+++ b/dex2oat/art_standalone_dex2oat_tests.xml
@@ -64,4 +64,7 @@
<!-- ART Mainline Module (external (AOSP) version). -->
<option name="mainline-module-package-name" value="com.android.art" />
</object>
+
+ <!--- Only run tests if the device under test is SDK version 31 (Android 12) or above. -->
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController" />
</configuration>
diff --git a/dexoptanalyzer/art_standalone_dexoptanalyzer_tests.xml b/dexoptanalyzer/art_standalone_dexoptanalyzer_tests.xml
index c931330..62cfcd2 100644
--- a/dexoptanalyzer/art_standalone_dexoptanalyzer_tests.xml
+++ b/dexoptanalyzer/art_standalone_dexoptanalyzer_tests.xml
@@ -50,4 +50,7 @@
<!-- ART Mainline Module (external (AOSP) version). -->
<option name="mainline-module-package-name" value="com.android.art" />
</object>
+
+ <!--- Only run tests if the device under test is SDK version 31 (Android 12) or above. -->
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController" />
</configuration>
diff --git a/libdexfile/art_standalone_libdexfile_tests.xml b/libdexfile/art_standalone_libdexfile_tests.xml
index 824dd92..d00235a 100644
--- a/libdexfile/art_standalone_libdexfile_tests.xml
+++ b/libdexfile/art_standalone_libdexfile_tests.xml
@@ -44,4 +44,7 @@
<!-- ART Mainline Module (external (AOSP) version). -->
<option name="mainline-module-package-name" value="com.android.art" />
</object>
+
+ <!--- Only run tests if the device under test is SDK version 31 (Android 12) or above. -->
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController" />
</configuration>
diff --git a/libprofile/art_standalone_libprofile_tests.xml b/libprofile/art_standalone_libprofile_tests.xml
index fbaa4b9..f113668 100644
--- a/libprofile/art_standalone_libprofile_tests.xml
+++ b/libprofile/art_standalone_libprofile_tests.xml
@@ -42,4 +42,7 @@
<!-- ART Mainline Module (external (AOSP) version). -->
<option name="mainline-module-package-name" value="com.android.art" />
</object>
+
+ <!--- Only run tests if the device under test is SDK version 31 (Android 12) or above. -->
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController" />
</configuration>
diff --git a/oatdump/art_standalone_oatdump_tests.xml b/oatdump/art_standalone_oatdump_tests.xml
index cf52de9..57e9163 100644
--- a/oatdump/art_standalone_oatdump_tests.xml
+++ b/oatdump/art_standalone_oatdump_tests.xml
@@ -40,4 +40,7 @@
<!-- ART Mainline Module (external (AOSP) version). -->
<option name="mainline-module-package-name" value="com.android.art" />
</object>
+
+ <!--- Only run tests if the device under test is SDK version 31 (Android 12) or above. -->
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController" />
</configuration>
diff --git a/profman/art_standalone_profman_tests.xml b/profman/art_standalone_profman_tests.xml
index 9750c23..b3c5120 100644
--- a/profman/art_standalone_profman_tests.xml
+++ b/profman/art_standalone_profman_tests.xml
@@ -51,4 +51,7 @@
<!-- ART Mainline Module (external (AOSP) version). -->
<option name="mainline-module-package-name" value="com.android.art" />
</object>
+
+ <!--- Only run tests if the device under test is SDK version 31 (Android 12) or above. -->
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController" />
</configuration>
diff --git a/runtime/art_standalone_runtime_compiler_tests.xml b/runtime/art_standalone_runtime_compiler_tests.xml
index 3c8b8c8..2bacda1 100644
--- a/runtime/art_standalone_runtime_compiler_tests.xml
+++ b/runtime/art_standalone_runtime_compiler_tests.xml
@@ -42,4 +42,7 @@
<!-- ART Mainline Module (external (AOSP) version). -->
<option name="mainline-module-package-name" value="com.android.art" />
</object>
+
+ <!--- Only run tests if the device under test is SDK version 31 (Android 12) or above. -->
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController" />
</configuration>
diff --git a/runtime/art_standalone_runtime_tests.xml b/runtime/art_standalone_runtime_tests.xml
index 85beef2..0b4b59a 100644
--- a/runtime/art_standalone_runtime_tests.xml
+++ b/runtime/art_standalone_runtime_tests.xml
@@ -108,4 +108,7 @@
<!-- ART Mainline Module (external (AOSP) version). -->
<option name="mainline-module-package-name" value="com.android.art" />
</object>
+
+ <!--- Only run tests if the device under test is SDK version 31 (Android 12) or above. -->
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController" />
</configuration>
diff --git a/runtime/jit/jit_memory_region.cc b/runtime/jit/jit_memory_region.cc
index 1592767..56407f5 100644
--- a/runtime/jit/jit_memory_region.cc
+++ b/runtime/jit/jit_memory_region.cc
@@ -20,6 +20,7 @@
#include <unistd.h>
#include <android-base/unique_fd.h>
+#include <log/log.h>
#include "base/bit_utils.h" // For RoundDown, RoundUp
#include "base/globals.h"
#include "base/logging.h" // For VLOG.
@@ -64,7 +65,15 @@
// File descriptor enabling dual-view mapping of code section.
unique_fd mem_fd;
+
+ // The memory mappings we are going to create.
+ MemMap data_pages;
+ MemMap exec_pages;
+ MemMap non_exec_pages;
+ MemMap writable_data_pages;
+
if (is_zygote) {
+ android_errorWriteLog(0x534e4554, "200284993"); // Report to SafetyNet.
// Because we are not going to GC code generated by the zygote, just use all available.
current_capacity_ = max_capacity;
mem_fd = unique_fd(CreateZygoteMemory(capacity, error_msg));
@@ -92,17 +101,12 @@
}
}
+ // Map name specific for android_os_Debug.cpp accounting.
std::string data_cache_name = is_zygote ? "zygote-data-code-cache" : "data-code-cache";
std::string exec_cache_name = is_zygote ? "zygote-jit-code-cache" : "jit-code-cache";
std::string error_str;
- // Map name specific for android_os_Debug.cpp accounting.
- // Map in low 4gb to simplify accessing root tables for x86_64.
- // We could do PC-relative addressing to avoid this problem, but that
- // would require reserving code and data area before submitting, which
- // means more windows for the code memory to be RWX.
int base_flags;
- MemMap data_pages;
if (mem_fd.get() >= 0) {
// Dual view of JIT code cache case. Create an initial mapping of data pages large enough
// for data and non-writable view of JIT code pages. We use the memory file descriptor to
@@ -131,7 +135,63 @@
// Additionally, the zyzote will create a dual view of the data portion of
// the cache. This mapping will be read-only, whereas the second mapping
// will be writable.
+
base_flags = MAP_SHARED;
+
+ // Create the writable mappings now, so that in case of the zygote, we can
+ // prevent any future writable mappings through sealing.
+ if (exec_capacity > 0) {
+ // For dual view, create the secondary view of code memory used for updating code. This view
+ // is never executable.
+ std::string name = exec_cache_name + "-rw";
+ non_exec_pages = MemMap::MapFile(exec_capacity,
+ kIsDebugBuild ? kProtR : kProtRW,
+ base_flags,
+ mem_fd,
+ /* start= */ data_capacity,
+ /* low_4GB= */ false,
+ name.c_str(),
+ &error_str);
+ if (!non_exec_pages.IsValid()) {
+ // This is unexpected.
+ *error_msg = "Failed to map non-executable view of JIT code cache";
+ return false;
+ }
+ // Create a dual view of the data cache.
+ name = data_cache_name + "-rw";
+ writable_data_pages = MemMap::MapFile(data_capacity,
+ kProtRW,
+ base_flags,
+ mem_fd,
+ /* start= */ 0,
+ /* low_4GB= */ false,
+ name.c_str(),
+ &error_str);
+ if (!writable_data_pages.IsValid()) {
+ std::ostringstream oss;
+ oss << "Failed to create dual data view: " << error_str;
+ *error_msg = oss.str();
+ return false;
+ }
+ if (writable_data_pages.MadviseDontFork() != 0) {
+ *error_msg = "Failed to MadviseDontFork the writable data view";
+ return false;
+ }
+ if (non_exec_pages.MadviseDontFork() != 0) {
+ *error_msg = "Failed to MadviseDontFork the writable code view";
+ return false;
+ }
+ // Now that we have created the writable and executable mappings, prevent creating any new
+ // ones.
+ if (is_zygote && !ProtectZygoteMemory(mem_fd.get(), error_msg)) {
+ return false;
+ }
+ }
+
+ // Map in low 4gb to simplify accessing root tables for x86_64.
+ // We could do PC-relative addressing to avoid this problem, but that
+ // would require reserving code and data area before submitting, which
+ // means more windows for the code memory to be RWX.
data_pages = MemMap::MapFile(
data_capacity + exec_capacity,
kProtR,
@@ -172,9 +232,6 @@
return false;
}
- MemMap exec_pages;
- MemMap non_exec_pages;
- MemMap writable_data_pages;
if (exec_capacity > 0) {
uint8_t* const divider = data_pages.Begin() + data_capacity;
// Set initial permission for executable view to catch any SELinux permission problems early
@@ -193,59 +250,6 @@
*error_msg = oss.str();
return false;
}
-
- if (mem_fd.get() >= 0) {
- // For dual view, create the secondary view of code memory used for updating code. This view
- // is never executable.
- std::string name = exec_cache_name + "-rw";
- non_exec_pages = MemMap::MapFile(exec_capacity,
- kIsDebugBuild ? kProtR : kProtRW,
- base_flags,
- mem_fd,
- /* start= */ data_capacity,
- /* low_4GB= */ false,
- name.c_str(),
- &error_str);
- if (!non_exec_pages.IsValid()) {
- static const char* kFailedNxView = "Failed to map non-executable view of JIT code cache";
- if (rwx_memory_allowed) {
- // Log and continue as single view JIT (requires RWX memory).
- VLOG(jit) << kFailedNxView;
- } else {
- *error_msg = kFailedNxView;
- return false;
- }
- }
- // Create a dual view of the data cache.
- name = data_cache_name + "-rw";
- writable_data_pages = MemMap::MapFile(data_capacity,
- kProtRW,
- base_flags,
- mem_fd,
- /* start= */ 0,
- /* low_4GB= */ false,
- name.c_str(),
- &error_str);
- if (!writable_data_pages.IsValid()) {
- std::ostringstream oss;
- oss << "Failed to create dual data view: " << error_str;
- *error_msg = oss.str();
- return false;
- }
- if (writable_data_pages.MadviseDontFork() != 0) {
- *error_msg = "Failed to madvise dont fork the writable data view";
- return false;
- }
- if (non_exec_pages.MadviseDontFork() != 0) {
- *error_msg = "Failed to madvise dont fork the writable code view";
- return false;
- }
- // Now that we have created the writable and executable mappings, prevent creating any new
- // ones.
- if (is_zygote && !ProtectZygoteMemory(mem_fd.get(), error_msg)) {
- return false;
- }
- }
} else {
// Profiling only. No memory for code required.
}
diff --git a/runtime/jit/jit_memory_region_test.cc b/runtime/jit/jit_memory_region_test.cc
index 21cb988..2a79777 100644
--- a/runtime/jit/jit_memory_region_test.cc
+++ b/runtime/jit/jit_memory_region_test.cc
@@ -493,6 +493,62 @@
munmap(addr, kPageSize);
munmap(shared, kPageSize);
}
+
+ // Test that a readable mapping created befire sealing future writes, can be
+ // changed into a writable mapping.
+ void TestVmMayWriteBefore() {
+ // Zygote JIT memory only works on kernels that don't segfault on flush.
+ TEST_DISABLED_FOR_KERNELS_WITH_CACHE_SEGFAULT();
+ std::string error_msg;
+ size_t size = kPageSize;
+ int32_t* addr = nullptr;
+ {
+ android::base::unique_fd fd(JitMemoryRegion::CreateZygoteMemory(size, &error_msg));
+ CHECK_NE(fd.get(), -1);
+
+ // Create a shared readable mapping.
+ addr = reinterpret_cast<int32_t*>(
+ mmap(nullptr, kPageSize, PROT_READ, MAP_SHARED, fd.get(), 0));
+ CHECK(addr != nullptr);
+ CHECK_NE(addr, MAP_FAILED);
+
+ // Protect the memory.
+ bool res = JitMemoryRegion::ProtectZygoteMemory(fd.get(), &error_msg);
+ CHECK(res);
+ }
+ // At this point, the fd has been dropped, but the memory mappings are still
+ // there.
+ int res = mprotect(addr, kPageSize, PROT_WRITE);
+ CHECK_EQ(res, 0);
+ }
+
+ // Test that we cannot create a writable mapping after sealing future writes.
+ void TestVmMayWriteAfter() {
+ // Zygote JIT memory only works on kernels that don't segfault on flush.
+ TEST_DISABLED_FOR_KERNELS_WITH_CACHE_SEGFAULT();
+ std::string error_msg;
+ size_t size = kPageSize;
+ int32_t* addr = nullptr;
+ {
+ android::base::unique_fd fd(JitMemoryRegion::CreateZygoteMemory(size, &error_msg));
+ CHECK_NE(fd.get(), -1);
+
+ // Protect the memory.
+ bool res = JitMemoryRegion::ProtectZygoteMemory(fd.get(), &error_msg);
+ CHECK(res);
+
+ // Create a shared readable mapping.
+ addr = reinterpret_cast<int32_t*>(
+ mmap(nullptr, kPageSize, PROT_READ, MAP_SHARED, fd.get(), 0));
+ CHECK(addr != nullptr);
+ CHECK_NE(addr, MAP_FAILED);
+ }
+ // At this point, the fd has been dropped, but the memory mappings are still
+ // there.
+ int res = mprotect(addr, kPageSize, PROT_WRITE);
+ CHECK_EQ(res, -1);
+ CHECK_EQ(errno, EACCES);
+ }
};
TEST_F(TestZygoteMemory, BasicTest) {
@@ -511,6 +567,14 @@
TestFromSharedToPrivate();
}
+TEST_F(TestZygoteMemory, TestVmMayWriteBefore) {
+ TestVmMayWriteBefore();
+}
+
+TEST_F(TestZygoteMemory, TestVmMayWriteAfter) {
+ TestVmMayWriteAfter();
+}
+
#endif // defined (__BIONIC__)
} // namespace jit
diff --git a/test/art-gtests-target-chroot.xml b/test/art-gtests-target-chroot.xml
index cb5095b..c461e9b 100644
--- a/test/art-gtests-target-chroot.xml
+++ b/test/art-gtests-target-chroot.xml
@@ -36,4 +36,7 @@
<!-- ART Mainline Module (external (AOSP) version). -->
<option name="mainline-module-package-name" value="com.android.art" />
</object>
+
+ <!--- Only run tests if the device under test is SDK version 31 (Android 12) or above. -->
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController" />
</configuration>
diff --git a/test/art-gtests-target-install-apex.xml b/test/art-gtests-target-install-apex.xml
index 39c46fb..5ca51e8 100644
--- a/test/art-gtests-target-install-apex.xml
+++ b/test/art-gtests-target-install-apex.xml
@@ -36,4 +36,7 @@
<!-- ART Mainline Module (external (AOSP) version). -->
<option name="mainline-module-package-name" value="com.android.art" />
</object>
+
+ <!--- Only run tests if the device under test is SDK version 31 (Android 12) or above. -->
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController" />
</configuration>
diff --git a/test/art-gtests-target-standalone-template.xml b/test/art-gtests-target-standalone-template.xml
index eed9033..015b60e 100644
--- a/test/art-gtests-target-standalone-template.xml
+++ b/test/art-gtests-target-standalone-template.xml
@@ -36,4 +36,7 @@
<!-- ART Mainline Module (external (AOSP) version). -->
<option name="mainline-module-package-name" value="com.android.art" />
</object>
+
+ <!--- Only run tests if the device under test is SDK version 31 (Android 12) or above. -->
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController" />
</configuration>
diff --git a/test/art-run-test-target-no-test-suite-tag-template.xml b/test/art-run-test-target-no-test-suite-tag-template.xml
index 7e7b592..6406626 100644
--- a/test/art-run-test-target-no-test-suite-tag-template.xml
+++ b/test/art-run-test-target-no-test-suite-tag-template.xml
@@ -35,4 +35,7 @@
<!-- ART Mainline Module (external (AOSP) version). -->
<option name="mainline-module-package-name" value="com.android.art" />
</object>
+
+ <!--- Only run tests if the device under test is SDK version 31 (Android 12) or above. -->
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController" />
</configuration>
diff --git a/test/art-run-test-target-template.xml b/test/art-run-test-target-template.xml
index 4084afa..433654a 100644
--- a/test/art-run-test-target-template.xml
+++ b/test/art-run-test-target-template.xml
@@ -38,4 +38,7 @@
<!-- ART Mainline Module (external (AOSP) version). -->
<option name="mainline-module-package-name" value="com.android.art" />
</object>
+
+ <!--- Only run tests if the device under test is SDK version 31 (Android 12) or above. -->
+ <object type="module_controller" class="com.android.tradefed.testtype.suite.module.Sdk31ModuleController" />
</configuration>