summaryrefslogtreecommitdiff
path: root/runtime/fault_handler.cc
diff options
context:
space:
mode:
author Lokesh Gidra <lokeshgidra@google.com> 2022-12-03 00:24:52 +0000
committer Lokesh Gidra <lokeshgidra@google.com> 2022-12-06 01:42:24 +0000
commitf716e21fb87e4fd1c875997cf11882352b9fbab5 (patch)
tree01516622bb3eb70e72c40249f74e35fdd47f6466 /runtime/fault_handler.cc
parentd4c19c9f9f3c931f46985518cdf092e9370305f4 (diff)
Avoid using SafeCopy on userfaultfd compacted spaces
Userfaultfd doesn't allow faults generating from kernel-space for unprivileged processes. Therefore, avoid using SafeCopy to fetch class in fault-handler. Also add a run-test to cause null-pointer exceptions which exercises fault-handler. Bug: 160737021 Test: ART_USE_READ_BARRIER=false art/test/testrunner/testrunner.py -t 2045-uffd-kernelfault Change-Id: If54bb01d441fab5489289e0ec195896700fac662
Diffstat (limited to 'runtime/fault_handler.cc')
-rw-r--r--runtime/fault_handler.cc26
1 files changed, 24 insertions, 2 deletions
diff --git a/runtime/fault_handler.cc b/runtime/fault_handler.cc
index f8bd213d53..c6940fa17b 100644
--- a/runtime/fault_handler.cc
+++ b/runtime/fault_handler.cc
@@ -25,6 +25,7 @@
#include "base/safe_copy.h"
#include "base/stl_util.h"
#include "dex/dex_file_types.h"
+#include "gc/space/bump_pointer_space.h"
#include "jit/jit.h"
#include "jit/jit_code_cache.h"
#include "mirror/class.h"
@@ -62,9 +63,20 @@ constexpr bool kVerifySafeImpls = false;
static mirror::Class* SafeGetDeclaringClass(ArtMethod* method)
REQUIRES_SHARED(Locks::mutator_lock_) {
+ if (gUseUserfaultfd) {
+ // Avoid SafeCopy on userfaultfd updated memory ranges as kernel-space
+ // userfaults are not allowed, which can otherwise happen if compaction is
+ // simultaneously going on.
+ Runtime* runtime = Runtime::Current();
+ DCHECK_NE(runtime->GetHeap()->MarkCompactCollector(), nullptr);
+ GcVisitedArenaPool* pool = static_cast<GcVisitedArenaPool*>(runtime->GetLinearAllocArenaPool());
+ if (pool->Contains(method)) {
+ return method->GetDeclaringClassUnchecked<kWithoutReadBarrier>().Ptr();
+ }
+ }
+
char* method_declaring_class =
reinterpret_cast<char*>(method) + ArtMethod::DeclaringClassOffset().SizeValue();
-
// ArtMethod::declaring_class_ is a GcRoot<mirror::Class>.
// Read it out into as a CompressedReference directly for simplicity's sake.
mirror::CompressedReference<mirror::Class> cls;
@@ -84,8 +96,18 @@ static mirror::Class* SafeGetDeclaringClass(ArtMethod* method)
}
static mirror::Class* SafeGetClass(mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_) {
- char* obj_cls = reinterpret_cast<char*>(obj) + mirror::Object::ClassOffset().SizeValue();
+ if (gUseUserfaultfd) {
+ // Avoid SafeCopy on userfaultfd updated memory ranges as kernel-space
+ // userfaults are not allowed, which can otherwise happen if compaction is
+ // simultaneously going on.
+ gc::Heap* heap = Runtime::Current()->GetHeap();
+ DCHECK_NE(heap->MarkCompactCollector(), nullptr);
+ if (heap->GetBumpPointerSpace()->Contains(obj)) {
+ return obj->GetClass();
+ }
+ }
+ char* obj_cls = reinterpret_cast<char*>(obj) + mirror::Object::ClassOffset().SizeValue();
mirror::HeapReference<mirror::Class> cls;
ssize_t rc = SafeCopy(&cls, obj_cls, sizeof(cls));
CHECK_NE(-1, rc);