-
Notifications
You must be signed in to change notification settings - Fork 4.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce BinaryFormatter enablement switch; disable on wasm (#38963)
Applications are given the option of disabling BinaryFormatter.Serialize and BinaryFormatter.Deserialize, meaning they'll throw NotSupportedException if anybody tries calling them. WASM projects always disable these APIs via a hardcoded mechanism; there is no re-enablement mechanism for those projects. This commit only introduces the switch. It does not disable it in any project types by default. (Exception: wasm, as mentioned above.) The related PR dotnet/sdk#12434 causes aspnet 5.0+ applications to disable BinaryFormatter functionality by default, but apps can re-enable if needed.
- Loading branch information
1 parent
9b3cbc4
commit 0554117
Showing
36 changed files
with
395 additions
and
219 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
139 changes: 139 additions & 0 deletions
139
....Private.CoreLib/src/System/Runtime/Serialization/SerializationInfo.SerializationGuard.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
// 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; | ||
using System.Threading; | ||
|
||
namespace System.Runtime.Serialization | ||
{ | ||
/// <summary>The structure for holding all of the data needed for object serialization and deserialization.</summary> | ||
public sealed partial class SerializationInfo | ||
{ | ||
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; | ||
} | ||
} | ||
|
||
// Throws a SerializationException if dangerous deserialization is currently | ||
// in progress | ||
public static void ThrowIfDeserializationInProgress() | ||
{ | ||
if (DeserializationInProgress) | ||
{ | ||
throw new SerializationException(SR.Serialization_DangerousDeserialization); | ||
} | ||
} | ||
|
||
// Throws a DeserializationBlockedException if dangerous deserialization is currently | ||
// in progress and the AppContext switch Switch.System.Runtime.Serialization.SerializationGuard.{switchSuffix} | ||
// is not true. The value of the switch is cached in cachedValue to avoid repeated lookups: | ||
// 0: No value cached | ||
// 1: The switch is true | ||
// -1: The switch is false | ||
public static void ThrowIfDeserializationInProgress(string switchSuffix, ref int cachedValue) | ||
{ | ||
const string SwitchPrefix = "Switch.System.Runtime.Serialization.SerializationGuard."; | ||
if (switchSuffix == null) | ||
{ | ||
throw new ArgumentNullException(nameof(switchSuffix)); | ||
} | ||
if (string.IsNullOrWhiteSpace(switchSuffix)) | ||
{ | ||
throw new ArgumentException(SR.Argument_EmptyName, nameof(switchSuffix)); | ||
} | ||
|
||
if (cachedValue == 0) | ||
{ | ||
if (AppContext.TryGetSwitch(SwitchPrefix + switchSuffix, out bool isEnabled) && isEnabled) | ||
{ | ||
cachedValue = 1; | ||
} | ||
else | ||
{ | ||
cachedValue = -1; | ||
} | ||
} | ||
|
||
if (cachedValue == 1) | ||
{ | ||
return; | ||
} | ||
else if (cachedValue == -1) | ||
{ | ||
if (DeserializationInProgress) | ||
{ | ||
throw new SerializationException(SR.Format(SR.Serialization_DangerousDeserialization_Switch, SwitchPrefix + switchSuffix)); | ||
} | ||
} | ||
else | ||
{ | ||
throw new ArgumentOutOfRangeException(nameof(cachedValue)); | ||
} | ||
} | ||
|
||
// Declares that the current thread and async context have begun deserialization. | ||
// 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) | ||
{ | ||
if (!tracker.DeserializationInProgress) | ||
{ | ||
AsyncDeserializationInProgress.Value = true; | ||
tracker.DeserializationInProgress = true; | ||
return new DeserializationToken(tracker); | ||
} | ||
} | ||
} | ||
} | ||
|
||
return new DeserializationToken(null); | ||
} | ||
} | ||
} |
Oops, something went wrong.