dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.25k stars 4.73k forks source link

Memmove reliability issue #38218

Closed gfs closed 4 years ago

gfs commented 4 years ago

@dotnet/jit-contrib

Description

From #36364:

In some cases calls to memmove may cause a CLR Crash.

For some repro cases see: secana/PeNet#143, secana/PeNet#142.

An example stack trace:

Fatal error. Internal CLR error. (0x80131506)
   at System.Buffer._Memmove(Byte ByRef, Byte ByRef, UInt64)
   at System.Buffer.Memmove(Byte ByRef, Byte ByRef, UInt64)
   at System.Span`1[[System.Byte, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].ToArray()
   at PeNet.Header.Authenticode.ContentInfo..ctor(System.Span`1<Byte>)
   at PeNet.Header.Authenticode.AuthenticodeInfo..ctor(PeNet.PeFile)
   at PeNet.HeaderParser.Authenticode.AuthenticodeParser.ParseTarget()
   at PeNet.PeFile.get_Authenticode()
   at AttackSurfaceAnalyzer.Collectors.WindowsFileSystemUtils.GetSignatureStatus(System.String)

@GrabYourPitchforks

Environment

PE.Net 2.2.4 .NET Core 3.1 (unsure of patch level at time of repro)

Simple Repro

Put this Microsoft.VisualBasic.Core.dll.zip .NET Runtime File into a Stream and pass it to the following function. You'll hit the Internal CLR Error mentioned above in the subsequent calls to memmove.

using PeNet;
using PeNet.Header.Authenticode;
using PeNet.Header.Pe;

public static Signature? GetSignatureStatus(string Path, Stream stream)
{
    if (stream is null)
    {
        return null;
    }
    try
    {
        if (PeFile.IsPeFile(stream))
        {
            var peHeader = new PeFile(stream);
            if (peHeader.Authenticode is AuthenticodeInfo ai)
            {
                var sig = new Signature(ai);
                return sig;
            }
        }
    }
    catch (Exception e)
    {
        Console.WriteLine($"Failed to get signature for {Path} ({e.GetType()}:{e.Message})");
    }
    return null;
}
Dotnet-GitSync-Bot commented 4 years ago

I couldn't figure out the best area label to add to this issue. Please help me learn by adding exactly one area label.

jkotas commented 4 years ago

You are creating creating Spans that point to unmapped memory in unsafe code.

The crash you are seeing is result of trying to operated on these invalid span.

CoreCLR does not allow applications to recover from bad memory access like this. The behavior you are seeing is by design. The behavior is unspecified in this case - you can get different types of crashes; or it may sometime work if you are lucky.