Prevent AV in processinfo2 while suspended (#55379)
authorJohn Salem <josalem@microsoft.com>
Mon, 12 Jul 2021 20:02:28 +0000 (13:02 -0700)
committerGitHub <noreply@github.com>
Mon, 12 Jul 2021 20:02:28 +0000 (13:02 -0700)
src/coreclr/vm/eventing/eventpipe/ep-rt-coreclr.h
src/tests/tracing/eventpipe/diagnosticport/diagnosticport.cs

index 607286d..7ee83ae 100644 (file)
@@ -1169,7 +1169,22 @@ ep_rt_entrypoint_assembly_name_get_utf8 (void)
 {
        STATIC_CONTRACT_NOTHROW;
 
-       return reinterpret_cast<const ep_char8_t*>(GetAppDomain ()->GetRootAssembly ()->GetSimpleName ());
+       AppDomain *app_domain_ref = nullptr;
+       Assembly *assembly_ref = nullptr;
+
+       app_domain_ref = GetAppDomain ();
+       if (app_domain_ref != nullptr)
+       {
+               assembly_ref = app_domain_ref->GetRootAssembly ();
+               if (assembly_ref != nullptr)
+               {
+                       return reinterpret_cast<const ep_char8_t*>(assembly_ref->GetSimpleName ());
+               }
+       }
+
+       // fallback to the empty string if we can't get assembly info, e.g., if the runtime is
+       // suspended before an assembly is loaded.
+       return reinterpret_cast<const ep_char8_t*>("");
 }
 
 static
index a4e6bd6..b1455d0 100644 (file)
@@ -388,6 +388,42 @@ namespace Tracing.Tests.DiagnosticPortValidation
             return fSuccess;
         }
 
+        public static async Task<bool> TEST_CanGetProcessInfo2WhileSuspended()
+        {
+            bool fSuccess = true;
+            Task<bool> subprocessTask = Utils.RunSubprocess(
+                currentAssembly: Assembly.GetExecutingAssembly(),
+                environment: new Dictionary<string,string> 
+                {
+                    { Utils.DiagnosticPortSuspend, "1" }
+                },
+                duringExecution: (int pid) =>
+                {
+                    Stream stream = ConnectionHelper.GetStandardTransport(pid);
+
+                    // 0x04 = ProcessCommandSet, 0x04 = ProcessInfo2
+                    var processInfoMessage = new IpcMessage(0x04, 0x04);
+                    Logger.logger.Log($"Wrote: {processInfoMessage}");
+                    IpcMessage response = IpcClient.SendMessage(stream, processInfoMessage);
+                    Logger.logger.Log($"Received: [{response.Payload.Select(b => b.ToString("X2") + " ").Aggregate(string.Concat)}]");
+                    ProcessInfo2 processInfo2 = ProcessInfo2.TryParse(response.Payload);
+                    Utils.Assert(String.IsNullOrEmpty(processInfo2.ManagedEntrypointAssemblyName));
+
+                    // send resume command on this connection
+                    var message = new IpcMessage(0x04,0x01);
+                    Logger.logger.Log($"Sent: {message.ToString()}");
+                    response = IpcClient.SendMessage(ConnectionHelper.GetStandardTransport(pid), message);
+                    Logger.logger.Log($"Received: {response.ToString()}");
+
+                    return Task.FromResult(true);
+                }
+            );
+
+            fSuccess &= await subprocessTask;
+
+            return fSuccess;
+        }
+
         public static async Task<int> Main(string[] args)
         {
             if (args.Length >= 1)