diff --git a/src/libraries/Common/src/System/Diagnostics/NetFrameworkUtils.cs b/src/libraries/Common/src/System/Diagnostics/NetFrameworkUtils.cs index 67316269a6458d..87f56dcdc242f4 100644 --- a/src/libraries/Common/src/System/Diagnostics/NetFrameworkUtils.cs +++ b/src/libraries/Common/src/System/Diagnostics/NetFrameworkUtils.cs @@ -4,6 +4,8 @@ using System.IO; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Security.AccessControl; +using System.Security.Principal; using System.Text; using System.Threading; using Microsoft.Win32; @@ -22,6 +24,13 @@ internal static void EnterMutexWithoutGlobal(string mutexName, ref Mutex mutex) { Mutex tmpMutex = new Mutex(false, mutexName, out _); + // Specify a SID in case the mutex has not yet been created; this prevents it from using the SID from the current thread. + // This SID (AuthenticatedUserSid) is the same one used by .NET Framework. + MutexSecurity sec = new MutexSecurity(); + SecurityIdentifier authenticatedUserSid = new SecurityIdentifier(WellKnownSidType.AuthenticatedUserSid, null); + sec.AddAccessRule(new MutexAccessRule(authenticatedUserSid, MutexRights.Synchronize | MutexRights.Modify, AccessControlType.Allow)); + tmpMutex.SetAccessControl(sec); + SafeWaitForMutex(tmpMutex, ref mutex); } diff --git a/src/libraries/NetCoreAppLibrary.props b/src/libraries/NetCoreAppLibrary.props index a3f63978bf92da..e4489580fa106b 100644 --- a/src/libraries/NetCoreAppLibrary.props +++ b/src/libraries/NetCoreAppLibrary.props @@ -222,6 +222,7 @@ Microsoft.Extensions.Primitives; System.Diagnostics.EventLog; System.Security.Cryptography.Xml; + System.Threading.AccessControl; System.Threading.RateLimiting; diff --git a/src/libraries/System.Diagnostics.EventLog/src/System.Diagnostics.EventLog.csproj b/src/libraries/System.Diagnostics.EventLog/src/System.Diagnostics.EventLog.csproj index b75253bce7298b..e480010bd20544 100644 --- a/src/libraries/System.Diagnostics.EventLog/src/System.Diagnostics.EventLog.csproj +++ b/src/libraries/System.Diagnostics.EventLog/src/System.Diagnostics.EventLog.csproj @@ -137,6 +137,7 @@ System.Diagnostics.EventLog ReferenceOutputAssembly="false" OutputItemType="TfmRuntimeSpecificPackageFile" PrivateAssets="true" /> + diff --git a/src/libraries/System.Diagnostics.PerformanceCounter/src/System.Diagnostics.PerformanceCounter.csproj b/src/libraries/System.Diagnostics.PerformanceCounter/src/System.Diagnostics.PerformanceCounter.csproj index 7cb7fa1954f0df..a14b483efd344a 100644 --- a/src/libraries/System.Diagnostics.PerformanceCounter/src/System.Diagnostics.PerformanceCounter.csproj +++ b/src/libraries/System.Diagnostics.PerformanceCounter/src/System.Diagnostics.PerformanceCounter.csproj @@ -1,4 +1,4 @@ - + $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent);$(NetCoreAppMinimum)-windows;$(NetCoreAppMinimum);netstandard2.0;$(NetFrameworkMinimum) @@ -139,6 +139,7 @@ System.Diagnostics.PerformanceCounter + diff --git a/src/libraries/System.Diagnostics.PerformanceCounter/tests/MutexTests.cs b/src/libraries/System.Diagnostics.PerformanceCounter/tests/MutexTests.cs new file mode 100644 index 00000000000000..efae0eaa79bdb8 --- /dev/null +++ b/src/libraries/System.Diagnostics.PerformanceCounter/tests/MutexTests.cs @@ -0,0 +1,49 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Security.AccessControl; +using System.Security.Principal; +using System.Threading; +using Xunit; + +namespace System.Diagnostics.Tests +{ + public static class MutexTests + { + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotInAppContainer))] // Can't create global objects in appcontainer + public static void VerifySecurityIdentifier() + { + string mutexName = $"{Guid.NewGuid():N}"; + + Mutex mutex = null; + + // We can't test with the same global mutex used by performance counters, since the mutex was likely already + // initialized elsewhere and perhaps with with different ACLs, so we use a Guid to create a new mutex and + // then simulate the behavior by calling into EnterMutex() like the performance monitor code does. +#pragma warning disable CS0436 // Type conflicts with imported type + NetFrameworkUtils.EnterMutex(mutexName, ref mutex); +#pragma warning restore CS0436 + + try + { + // This is the SID that is added by EnterMutex(). + SecurityIdentifier authenticatedUserSid = new(WellKnownSidType.AuthenticatedUserSid, null); + + MutexSecurity security = mutex.GetAccessControl(); + AuthorizationRuleCollection rules = security.GetAccessRules(true, true, typeof(SecurityIdentifier)); + Assert.Equal(1, rules.Count); + MutexAccessRule accessRule = (MutexAccessRule)rules[0]; + SecurityIdentifier sid = (SecurityIdentifier)accessRule.IdentityReference; + Assert.Equal(authenticatedUserSid, sid); + } + finally + { + if (mutex != null) + { + mutex.ReleaseMutex(); + mutex.Close(); + } + } + } + } +} diff --git a/src/libraries/System.Diagnostics.PerformanceCounter/tests/System.Diagnostics.PerformanceCounter.Tests.csproj b/src/libraries/System.Diagnostics.PerformanceCounter/tests/System.Diagnostics.PerformanceCounter.Tests.csproj index fb902be8219173..d101c1ced60d84 100644 --- a/src/libraries/System.Diagnostics.PerformanceCounter/tests/System.Diagnostics.PerformanceCounter.Tests.csproj +++ b/src/libraries/System.Diagnostics.PerformanceCounter/tests/System.Diagnostics.PerformanceCounter.Tests.csproj @@ -1,20 +1,22 @@ - + true $(NetCoreAppCurrent)-windows;$(NetFrameworkMinimum) - - - - - - - + + + + + + + + + + - @@ -24,4 +26,4 @@ - \ No newline at end of file +