dotnet / runtime

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

Missing [HandleProcessCorruptedStateExceptions] #4882

Closed ayende closed 4 years ago

ayende commented 8 years ago

I've code that may access invalid memory location. In the full .NET, I have [HandleProcessCorruptedStateExceptions] to mark such a code and recover from it. Is there such a way to handle it in the CoreCLR?

morganbr commented 8 years ago

@ayende, can you please tell us more about the scenario where you'd like to do that? We generally consider it a very dangerous practice to recover from corrupted state as it can make security attacks significantly easier.

ayende commented 8 years ago

Sure, here is my scenario:

https://github.com/ayende/ravendb/blob/master/Raven.Database/Indexing/LuceneCodecDirectory.cs#L180

Consider the case of memory mapping a file, and an API that is used to access it. Now, someone is disposing the class, so we unmap the file. However, some other code is still using this file, and expects to ObjectDisposedException when it happens.

This is stupid behavior, on many levels, but this is an existing codebase that we want to move.

ctemple commented 6 years ago

i think i got same question code like this catch exception on windows/.net 4.6.1,this is good but crash on windows/dotnetcore 2.0,this is not good need this feature to handle golang dll defer recover() functions

    [DllImport("kernel32.dll")]
    static extern void GetCurrentDirectory(int length, string dir);

    static void foo()
    {
        GetCurrentDirectory(256, null);
    }

    [HandleProcessCorruptedStateExceptions]
    static void boo()
    {
        try
        {
            foo();
        }
        catch (AccessViolationException ex)
        {
            Console.WriteLine("boo - {0}", ex.Message);
        }
    }
danmoseley commented 6 years ago

@jkotas is HandleProcessCorruptedStateExceptions likely to be supported on coreclr?

jkotas commented 6 years ago

Handling dirty access violations is not going to be supported. It is significant security risk as @morganbr described, and it is impossible to do cross-platform reliably.

@ctemple Could you please share more details on how you would like to use this for golang dll defer recover() functions?

ayende commented 6 years ago

@jkotas The problem for me is memory mapped system. If I get an error there (for example a network file mmap with network lost) I would really like to not have the entire cluster crash.

jkotas commented 6 years ago

The memory mapped files are interesting case. We may want to have register of memory mapped regions, and if there is a fault in managed code while accessing the registered memory region, convert it to exception and not fail fast. It works reliably only if you have a strong control over code accessing the memory mapped file. If you take the pointer and pass it to PInvoke (like in the above example) or to BCL function that happens to be implemented in C++, it would still fail fast - HandleProcessCorruptedStateExceptions on .NET Framework has the same problem.

ayende commented 6 years ago

I do have such strong control over this. And that would be wonderful for our purposes, yes. That would mean that I wouldn't have to protect all my methods, but just the memory regions in question.

jkotas commented 6 years ago

@morganbr What do you think about the memory mapped file case?

morganbr commented 6 years ago

Would it be possible for us to have MemoryMappedFile figure out whether something has been unmapped and avoid triggering the AV? I'm still very reluctant to expose HandleProcessCorruptedStateExceptions for general usage.

ayende commented 6 years ago

@morganbr For various reasons, we sometimes call to the native API directly, instead of going through MemoryMappedFile. It would be much better if we could have an API that would designate memory ranges as "turn an AV to an exception here".

mikedn commented 6 years ago

We should probably distinguish between "use after free" scenarios and "lost network" scenarios.

The former is dangerous and should not occur in correct code so it shouldn't be supported.

The later is not dangerous and it seems that at least on Windows it's relatively easy to handle - the exception code is EXCEPTION_IN_PAGE_ERROR instead of EXCEPTION_ACCESS_VIOLATION and the exception record contains the memory address that caused the exception, that can be passed to VirtualQuery to figure out that the address is within a mapped section. But if Unix like systems do not offer this kind of information then probably the only option is to manually communicate memory mapped ranges to the runtime.

jkotas commented 6 years ago

Would it be possible for us to have MemoryMappedFile figure out whether something has been unmapped and avoid triggering the AV?

Yes, the proposal is that the runtime is going to have a list of memory ranges where we turn the AV into exception.

ayende commented 6 years ago

Is there any progress around this are? I just run into an area where a mmap file had some bad sectors. When we tried to access some of then, an SEHException was thrown, obviously, and it killed the entire process.

ayende commented 6 years ago

I would be happy to send a PR for that if I that is fine and I can get some guidance on where to touch.

jkotas commented 6 years ago

The next steps that should happen for this:

jkotas commented 6 years ago

@ayende Would you be interested in crafting the API proposal?

ayende commented 6 years ago

@jkotas Yes, I can send that later today

ayende commented 6 years ago

Here it is: https://github.com/dotnet/corefx/issues/26513

jkotas commented 4 years ago

Duplicate of https://github.com/dotnet/runtime/issues/24767