Skip to content

Commit ecbdd34

Browse files
author
Alex Menkov
committed
8361103: java_lang_Thread::async_get_stack_trace does not properly protect JavaThread
Reviewed-by: sspitsyn, dholmes
1 parent 38a2614 commit ecbdd34

File tree

3 files changed

+27
-30
lines changed

3 files changed

+27
-30
lines changed

src/hotspot/share/classfile/javaClasses.cpp

Lines changed: 25 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1899,33 +1899,29 @@ oop java_lang_Thread::park_blocker(oop java_thread) {
18991899
return java_thread->obj_field_access<MO_RELAXED>(_park_blocker_offset);
19001900
}
19011901

1902-
oop java_lang_Thread::async_get_stack_trace(oop java_thread, TRAPS) {
1903-
ThreadsListHandle tlh(JavaThread::current());
1904-
JavaThread* thread;
1905-
bool is_virtual = java_lang_VirtualThread::is_instance(java_thread);
1906-
if (is_virtual) {
1907-
oop carrier_thread = java_lang_VirtualThread::carrier_thread(java_thread);
1908-
if (carrier_thread == nullptr) {
1909-
return nullptr;
1910-
}
1911-
thread = java_lang_Thread::thread(carrier_thread);
1912-
} else {
1913-
thread = java_lang_Thread::thread(java_thread);
1914-
}
1915-
if (thread == nullptr) {
1902+
// Obtain stack trace for platform or mounted virtual thread.
1903+
// If jthread is a virtual thread and it has been unmounted (or remounted to different carrier) the method returns null.
1904+
// The caller (java.lang.VirtualThread) handles returned nulls via retry.
1905+
oop java_lang_Thread::async_get_stack_trace(jobject jthread, TRAPS) {
1906+
ThreadsListHandle tlh(THREAD);
1907+
JavaThread* java_thread = nullptr;
1908+
oop thread_oop;
1909+
1910+
bool has_java_thread = tlh.cv_internal_thread_to_JavaThread(jthread, &java_thread, &thread_oop);
1911+
if (!has_java_thread) {
19161912
return nullptr;
19171913
}
19181914

19191915
class GetStackTraceHandshakeClosure : public HandshakeClosure {
19201916
public:
1921-
const Handle _java_thread;
1917+
const Handle _thread_h;
19221918
int _depth;
19231919
bool _retry_handshake;
19241920
GrowableArray<Method*>* _methods;
19251921
GrowableArray<int>* _bcis;
19261922

1927-
GetStackTraceHandshakeClosure(Handle java_thread) :
1928-
HandshakeClosure("GetStackTraceHandshakeClosure"), _java_thread(java_thread), _depth(0), _retry_handshake(false),
1923+
GetStackTraceHandshakeClosure(Handle thread_h) :
1924+
HandshakeClosure("GetStackTraceHandshakeClosure"), _thread_h(thread_h), _depth(0), _retry_handshake(false),
19291925
_methods(nullptr), _bcis(nullptr) {
19301926
}
19311927
~GetStackTraceHandshakeClosure() {
@@ -1947,21 +1943,22 @@ oop java_lang_Thread::async_get_stack_trace(oop java_thread, TRAPS) {
19471943
return;
19481944
}
19491945

1950-
JavaThread* thread = JavaThread::cast(th);
1946+
JavaThread* java_thread = JavaThread::cast(th);
19511947

1952-
if (!thread->has_last_Java_frame()) {
1948+
if (!java_thread->has_last_Java_frame()) {
19531949
return;
19541950
}
19551951

19561952
bool carrier = false;
1957-
if (java_lang_VirtualThread::is_instance(_java_thread())) {
1958-
// if (thread->vthread() != _java_thread()) // We might be inside a System.executeOnCarrierThread
1959-
const ContinuationEntry* ce = thread->vthread_continuation();
1960-
if (ce == nullptr || ce->cont_oop(thread) != java_lang_VirtualThread::continuation(_java_thread())) {
1961-
return; // not mounted
1953+
if (java_lang_VirtualThread::is_instance(_thread_h())) {
1954+
// Ensure _thread_h is still mounted to java_thread.
1955+
const ContinuationEntry* ce = java_thread->vthread_continuation();
1956+
if (ce == nullptr || ce->cont_oop(java_thread) != java_lang_VirtualThread::continuation(_thread_h())) {
1957+
// Target thread has been unmounted.
1958+
return;
19621959
}
19631960
} else {
1964-
carrier = (thread->vthread_continuation() != nullptr);
1961+
carrier = (java_thread->vthread_continuation() != nullptr);
19651962
}
19661963

19671964
const int max_depth = MaxJavaStackTraceDepth;
@@ -1973,7 +1970,7 @@ oop java_lang_Thread::async_get_stack_trace(oop java_thread, TRAPS) {
19731970
_bcis = new (mtInternal) GrowableArray<int>(init_length, mtInternal);
19741971

19751972
int total_count = 0;
1976-
for (vframeStream vfst(thread, false, false, carrier); // we don't process frames as we don't care about oops
1973+
for (vframeStream vfst(java_thread, false, false, carrier); // we don't process frames as we don't care about oops
19771974
!vfst.at_end() && (max_depth == 0 || max_depth != total_count);
19781975
vfst.next()) {
19791976

@@ -1994,9 +1991,9 @@ oop java_lang_Thread::async_get_stack_trace(oop java_thread, TRAPS) {
19941991
// Handshake with target
19951992
ResourceMark rm(THREAD);
19961993
HandleMark hm(THREAD);
1997-
GetStackTraceHandshakeClosure gsthc(Handle(THREAD, java_thread));
1994+
GetStackTraceHandshakeClosure gsthc(Handle(THREAD, thread_oop));
19981995
do {
1999-
Handshake::execute(&gsthc, &tlh, thread);
1996+
Handshake::execute(&gsthc, &tlh, java_thread);
20001997
} while (gsthc.read_reset_retry());
20011998

20021999
// Stop if no stack trace is found.

src/hotspot/share/classfile/javaClasses.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,7 @@ class java_lang_Thread : AllStatic {
463463
static const char* thread_status_name(oop java_thread_oop);
464464

465465
// Fill in current stack trace, can cause GC
466-
static oop async_get_stack_trace(oop java_thread, TRAPS);
466+
static oop async_get_stack_trace(jobject jthread, TRAPS);
467467

468468
JFR_ONLY(static u2 jfr_epoch(oop java_thread);)
469469
JFR_ONLY(static void set_jfr_epoch(oop java_thread, u2 epoch);)

src/hotspot/share/prims/jvm.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2945,7 +2945,7 @@ JVM_ENTRY(jboolean, JVM_HoldsLock(JNIEnv* env, jclass threadClass, jobject obj))
29452945
JVM_END
29462946

29472947
JVM_ENTRY(jobject, JVM_GetStackTrace(JNIEnv *env, jobject jthread))
2948-
oop trace = java_lang_Thread::async_get_stack_trace(JNIHandles::resolve(jthread), THREAD);
2948+
oop trace = java_lang_Thread::async_get_stack_trace(jthread, THREAD);
29492949
return JNIHandles::make_local(THREAD, trace);
29502950
JVM_END
29512951

0 commit comments

Comments
 (0)