diff options
Diffstat (limited to 'runtime/jit/jit_memory_region.cc')
-rw-r--r-- | runtime/jit/jit_memory_region.cc | 130 |
1 files changed, 67 insertions, 63 deletions
diff --git a/runtime/jit/jit_memory_region.cc b/runtime/jit/jit_memory_region.cc index 58a4041abe..56407f58c0 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 @@ bool JitMemoryRegion::Initialize(size_t initial_capacity, // 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 @@ bool JitMemoryRegion::Initialize(size_t initial_capacity, } } + // 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 @@ bool JitMemoryRegion::Initialize(size_t initial_capacity, // 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 @@ bool JitMemoryRegion::Initialize(size_t initial_capacity, 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 @@ bool JitMemoryRegion::Initialize(size_t initial_capacity, *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. } @@ -552,7 +556,7 @@ bool JitMemoryRegion::ProtectZygoteMemory(int fd, std::string* error_msg) { return false; } } else { - palette_status_t status = PaletteAshmemSetProtRegion(fd, PROT_READ); + palette_status_t status = PaletteAshmemSetProtRegion(fd, PROT_READ | PROT_EXEC); if (status != PALETTE_STATUS_OK) { CHECK_EQ(status, PALETTE_STATUS_CHECK_ERRNO); std::ostringstream oss; |