diff options
author | android-build-team Robot <android-build-team-robot@google.com> | 2017-08-08 00:17:58 +0000 |
---|---|---|
committer | android-build-team Robot <android-build-team-robot@google.com> | 2017-08-08 00:17:58 +0000 |
commit | fca8af7684ff93aaa1ba31f3c468ea015180fc85 (patch) | |
tree | 26d640bbe8ff088340064f895cf9d17f203c94cb | |
parent | 699cb9a11b1dce1515a4f591274b90269962cfec (diff) | |
parent | 3f74fd50a8e05d996e3e04a960ced4dc1e1822cf (diff) | |
download | art-oreo-r2-release.tar.gz |
Merge cherrypicks of [2680667, 2680866, 2680867, 2679663, 2679664, 2680868, 2680869, 2680870, 2680668, 2680669, 2679480, 2679789, 2679790, 2679791, 2679792, 2679793, 2680914, 2680915, 2679481, 2680916, 2680670, 2680671, 2680672, 2680673, 2680974, 2680975, 2680976, 2680977] into oc-r2-releaseandroid-8.0.0_r29oreo-r2-release
Change-Id: Ie8c4b4b63ef8a8937225a4f25b61191ded5ab7f8
-rw-r--r-- | runtime/thread.cc | 46 |
1 files changed, 33 insertions, 13 deletions
diff --git a/runtime/thread.cc b/runtime/thread.cc index 201701a510..6b10dfcd68 100644 --- a/runtime/thread.cc +++ b/runtime/thread.cc @@ -545,27 +545,47 @@ void Thread::InstallImplicitProtection() { // // We map in the stack by reading every page from the stack bottom (highest address) // to the stack top. (We then madvise this away.) This must be done by reading from the - // current stack pointer downwards. Any access more than a page below the current SP - // might cause a segv. - // TODO: This comment may be out of date. It seems possible to speed this up. As - // this is normally done once in the zygote on startup, ignore for now. + // current stack pointer downwards. // - // AddressSanitizer does not like the part of this functions that reads every stack page. - // Looks a lot like an out-of-bounds access. + // Accesses too far below the current machine register corresponding to the stack pointer (e.g., + // ESP on x86[-32], SP on ARM) might cause a SIGSEGV (at least on x86 with newer kernels). We + // thus have to move the stack pointer. We do this portably by using a recursive function with a + // large stack frame size. - // (Defensively) first remove the protection on the protected region as will want to read + // (Defensively) first remove the protection on the protected region as we'll want to read // and write it. Ignore errors. UnprotectStack(); VLOG(threads) << "Need to map in stack for thread at " << std::hex << static_cast<void*>(pregion); - // Read every page from the high address to the low. - volatile uint8_t dont_optimize_this; - UNUSED(dont_optimize_this); - for (uint8_t* p = stack_top; p >= pregion; p -= kPageSize) { - dont_optimize_this = *p; - } + struct RecurseDownStack { + // This function has an intentionally large stack size. +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wframe-larger-than=" + NO_INLINE + static void Touch(uintptr_t target) { + volatile size_t zero = 0; + // Use a large local volatile array to ensure a large frame size. Do not use anything close + // to a full page for ASAN. It would be nice to ensure the frame size is at most a page, but + // there is no pragma support for this. + // Note: for ASAN we need to shrink the array a bit, as there's other overhead. + constexpr size_t kAsanMultiplier = +#ifdef ADDRESS_SANITIZER + 2u; +#else + 1u; +#endif + volatile char space[kPageSize - (kAsanMultiplier * 256)]; + char sink ATTRIBUTE_UNUSED = space[zero]; + if (reinterpret_cast<uintptr_t>(space) >= target + kPageSize) { + Touch(target); + } + zero *= 2; // Try to avoid tail recursion. + } +#pragma GCC diagnostic pop + }; + RecurseDownStack::Touch(reinterpret_cast<uintptr_t>(pregion)); VLOG(threads) << "(again) installing stack protected region at " << std::hex << static_cast<void*>(pregion) << " to " << |