[DllImport(RuntimeHelpers.QCall, CharSet = CharSet.Unicode)]
private static extern void InformThreadNameChange(ThreadHandle t, string? name, int len);
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern DeserializationTracker GetThreadDeserializationTracker(ref StackCrawlMark stackMark);
-
/// <summary>Returns true if the thread has been started and is not dead.</summary>
public extern bool IsAlive
{
return ret;
}
-FCIMPL1(Object*, ThreadNative::GetThreadDeserializationTracker, StackCrawlMark* stackMark)
-{
- FCALL_CONTRACT;
- OBJECTREF refRetVal = NULL;
- HELPER_METHOD_FRAME_BEGIN_RET_1(refRetVal)
-
- // To avoid reflection trying to bypass deserialization tracking, check the caller
- // and only allow SerializationInfo to call into this method.
- MethodTable* pCallerMT = SystemDomain::GetCallersType(stackMark);
- if (pCallerMT != CoreLibBinder::GetClass(CLASS__SERIALIZATION_INFO))
- {
- COMPlusThrowArgumentException(W("stackMark"), NULL);
- }
-
- Thread* pThread = GetThread();
-
- refRetVal = ObjectFromHandle(pThread->GetOrCreateDeserializationTracker());
-
- HELPER_METHOD_FRAME_END();
-
- return OBJECTREFToObject(refRetVal);
-}
-FCIMPLEND
-
FCIMPL0(INT32, ThreadNative::GetCurrentProcessorNumber)
{
FCALL_CONTRACT;
#endif //FEATURE_COMINTEROP
static FCDECL1(FC_BOOL_RET,IsThreadpoolThread, ThreadBaseObject* thread);
static FCDECL1(void, SetIsThreadpoolThread, ThreadBaseObject* thread);
- static FCDECL1(Object*, GetThreadDeserializationTracker, StackCrawlMark* stackMark);
static FCDECL0(INT32, GetCurrentProcessorNumber);
DEFINE_METHOD(COMWRAPPERS, CALL_ICUSTOMQUERYINTERFACE, CallICustomQueryInterface, SM_Obj_RefGuid_RefIntPtr_RetInt)
#endif //FEATURE_COMINTEROP
-DEFINE_CLASS(SERIALIZATION_INFO, Serialization, SerializationInfo)
-DEFINE_CLASS(DESERIALIZATION_TRACKER, Serialization, DeserializationTracker)
-
DEFINE_CLASS(IENUMERATOR, Collections, IEnumerator)
DEFINE_CLASS(IENUMERABLE, Collections, IEnumerable)
FCFuncElement("Join", ThreadNative::Join)
QCFuncElement("GetOptimalMaxSpinWaitsPerSpinIterationInternal", ThreadNative::GetOptimalMaxSpinWaitsPerSpinIteration)
FCFuncElement("GetCurrentProcessorNumber", ThreadNative::GetCurrentProcessorNumber)
- FCFuncElement("GetThreadDeserializationTracker", ThreadNative::GetThreadDeserializationTracker)
FCFuncEnd()
FCFuncStart(gThreadPoolFuncs)
memset(&m_activityId, 0, sizeof(m_activityId));
#endif // FEATURE_PERFTRACING
m_HijackReturnKind = RT_Illegal;
- m_DeserializationTracker = NULL;
m_currentPrepareCodeConfig = nullptr;
m_isInForbidSuspendForDebuggerRegion = false;
// Destroy any handles that we're using to hold onto exception objects
SafeSetThrowables(NULL);
- if (m_DeserializationTracker != NULL)
- {
- DestroyGlobalStrongHandle(m_DeserializationTracker);
- }
-
DestroyShortWeakHandle(m_ExposedObject);
DestroyStrongHandle(m_StrongHndToExposedObject);
}
}
#endif // #ifdef DACCESS_COMPILE
-
-OBJECTHANDLE Thread::GetOrCreateDeserializationTracker()
-{
- CONTRACTL
- {
- THROWS;
- GC_TRIGGERS;
- MODE_COOPERATIVE;
- }
- CONTRACTL_END;
-
-#if !defined (DACCESS_COMPILE)
- if (m_DeserializationTracker != NULL)
- {
- return m_DeserializationTracker;
- }
-
- _ASSERTE(this == GetThread());
-
- MethodTable* pMT = CoreLibBinder::GetClass(CLASS__DESERIALIZATION_TRACKER);
- m_DeserializationTracker = CreateGlobalStrongHandle(AllocateObject(pMT));
-
- _ASSERTE(m_DeserializationTracker != NULL);
-#endif // !defined (DACCESS_COMPILE)
-
- return m_DeserializationTracker;
-}
#endif // FEATURE_HIJACK
public:
- OBJECTHANDLE GetOrCreateDeserializationTracker();
-
-private:
- OBJECTHANDLE m_DeserializationTracker;
-
-public:
static uint64_t dead_threads_non_alloc_bytes;
#ifndef DACCESS_COMPILE
{
internal static AsyncLocal<bool> AsyncDeserializationInProgress { get; } = new AsyncLocal<bool>();
-#if !CORECLR
- // On AoT, assume private members are reflection blocked, so there's no further protection required
- // for the thread's DeserializationTracker
[ThreadStatic]
private static DeserializationTracker? t_deserializationTracker;
private static DeserializationTracker GetThreadDeserializationTracker() =>
t_deserializationTracker ??= new DeserializationTracker();
-#endif // !CORECLR
// Returns true if deserialization is currently in progress
public static bool DeserializationInProgress
{
-#if CORECLR
- [DynamicSecurityMethod] // Methods containing StackCrawlMark local var must be marked DynamicSecurityMethod
-#endif
get
{
if (AsyncDeserializationInProgress.Value)
return true;
}
-#if CORECLR
- StackCrawlMark stackMark = StackCrawlMark.LookForMe;
- DeserializationTracker tracker = Thread.GetThreadDeserializationTracker(ref stackMark);
-#else
DeserializationTracker tracker = GetThreadDeserializationTracker();
-#endif
bool result = tracker.DeserializationInProgress;
return result;
}
// In this state, if the SerializationGuard or other related AppContext switches are set,
// actions likely to be dangerous during deserialization, such as starting a process will be blocked.
// Returns a DeserializationToken that must be disposed to remove the deserialization state.
-#if CORECLR
- [DynamicSecurityMethod] // Methods containing StackCrawlMark local var must be marked DynamicSecurityMethod
-#endif
public static DeserializationToken StartDeserialization()
{
if (LocalAppContextSwitches.SerializationGuard)
{
-#if CORECLR
- StackCrawlMark stackMark = StackCrawlMark.LookForMe;
- DeserializationTracker tracker = Thread.GetThreadDeserializationTracker(ref stackMark);
-#else
DeserializationTracker tracker = GetThreadDeserializationTracker();
-#endif
if (!tracker.DeserializationInProgress)
{
lock (tracker)
}
[Fact]
- [ActiveIssue("https://github.com/mono/mono/issues/15112", TestRuntimes.Mono)]
- public static void BlockReflectionDodging()
- {
- // Ensure that the deserialization tracker cannot be called by reflection.
- MethodInfo trackerMethod = typeof(Thread).GetMethod(
- "GetThreadDeserializationTracker",
- BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
-
- Assert.NotNull(trackerMethod);
-
- Assert.Equal(1, trackerMethod.GetParameters().Length);
- object[] args = new object[1];
- args[0] = Enum.ToObject(typeof(Thread).Assembly.GetType("System.Threading.StackCrawlMark"), 0);
-
- try
- {
- object tracker = trackerMethod.Invoke(null, args);
- throw new InvalidOperationException(tracker?.ToString() ?? "(null tracker returned)");
- }
- catch (TargetInvocationException ex)
- {
- Exception baseEx = ex.GetBaseException();
- AssertExtensions.Throws<ArgumentException>("stackMark", () => throw baseEx);
- }
- }
-
- [Fact]
public static void BlockAsyncDodging()
{
TryPayload(new AsyncDodger());