Sftp::BeginGetFile causes "releaseHandleFailed MDA"

+1 vote
asked Jul 22, 2010 by _FRED_ (640 points)
edited Dec 16, 2010

ReleaseHandleFailed was detected Message: A SafeHandle or CriticalHandle of type 'Microsoft.Win32.SafeHandles.SafeCapiKeyHandle' failed to properly release the handle with value 0x033BFF60. This usually indicates that the handle was released incorrectly via another means (such as extracting the handle using DangerousGetHandle and closing it directly or building another SafeHandle around it.)

http://msdn.microsoft.com/en-us/library/85eak4a0.aspx http://social.msdn.microsoft.com/Search/en-US/?Query=ReleaseHandleFailed

Can this issue was fixed?

Applies to: Rebex SFTP
commented Jul 22, 2010 by Lukas Pokorny (126,950 points)
Would it be possible to post the whole exception? Use a try/catch block to catch it and post the result of the Exception's ToString() method. We don't use Microsoft.Win32.SafeHandles.SafeCapiKeyHandle directly in any Rebex component, so this error must have occured in some part .NET Framework library we do use. Without the full exception stack trace, we are unable to tell what happened.
commented Jul 23, 2010 by _FRED_ (640 points)
commented Jul 23, 2010 by _FRED_ (640 points)
This message from GC Finalizer thread with call stack: mscorlib.dll!System.Runtime.InteropServices.SafeHandle.Dispose(bool disposing) + 0xf bytes mscorlib.dll!System.Runtime.InteropServices.SafeHandle.Finalize() + 0x1b bytes

2 Answers

+1 vote
answered Dec 16, 2010 by Lukas Matyska (60,770 points)
edited Dec 16, 2010
 
Best answer

We discovered the problem arises even when AesCryptoServiceProvider is used correctly. This is problem in .NET Framework which can be reproduced using the following simple code:

using System;
using System.Security.Cryptography;

namespace AesCspIssue
{
    class Program
    {
        static void Main(string[] args)
        {
            SymmetricAlgorithm alg = new AesCryptoServiceProvider();
            ICryptoTransform transform = alg.CreateEncryptor();

            // use the transform here (but not required to reproduce the problem)
            // ...

            transform.Dispose();
            alg.Clear();

            // to ensure the finalizers of 'alg' and 'transform' are called
            GC.Collect();
        }
    }
}

A workaround would be not to use the AesCryptoServiceProvider when debugging with MDA, but to use a slower implementation provided by the RijndaelManaged class. This is not easily possible in the current version of Rebex SFTP/SSH Shell (unless you disable AES completely). We will add an options to the next release that will make this possible using the following code:

Rebex.Security.Cryptography.CryptoHelper.ForceManagedAes = true;
commented Dec 17, 2010 by _FRED_ (640 points)
Thanks for research! I see, this is framework bug and workaround is acceptable. In Fx 4.0 the sample code working correctly. May be, this bug is fixed.
+2 votes
answered Jul 23, 2010 by Lukas Pokorny (126,950 points)
edited Dec 16, 2010

It looks like this is actually a .NET Framework issue - something is wrong with System.Security.Cryptography.AesCryptoServiceProvider object's finalizer. The following console application can be used to reproduce the issue without using any Rebex code:

using System;
using System.Security.Cryptography;
...

static void Main()
{
    while (true)
    {
        for (int i = 0; i < 1000; i++)
        {
            SymmetricAlgorithm aes = new AesCryptoServiceProvider();

            for (int j = 0; j < 16; j++)
            {
                aes.Key = new byte[32];
            }

            //aes.Clear();
        }

        Console.WriteLine("Press X to exit and any other key to try again.");
        if (Console.ReadKey().Key == ConsoleKey.X)
            break;
    }
}

This code triggers the MDA message you describe after several runs. Could you please try running this code and confirm that it behaves the same way at your machine?

In Rebex SFTP, we only use two instances of AesCryptoServiceProvider per SFTP session. It looks like creating 1000s of instances is not the real cause of the issue, but triggers a situation where it occurs. Uncommenting the aes.Clear() line solves the problem.

We are now looking into possibilities of how to work around this issue. Obviously, explicitly disposing the AES CSP object in Sftp.Disconnect/Sftp.Dispose would solve it if the programmer actually calls these methods, so that's the first thing we'll do. But it's unclear whether anything can be done if the SFTP session is not explicitly shut down.

commented Jul 26, 2010 by _FRED_ (640 points)
Yes, you should explicitly calling Dispose() on safe handles for avoid "releaseHandleFailed" MDA message in Sftp::Dispose(). If programmer does not disposing instance of Sftp class explicitly, you should not solve this issue - this is programmer's error and MSVS tell him about this. In my view, this is good and right behaviour.
commented Jul 26, 2010 by Lukas Pokorny (126,950 points)
Actually, we don't reference the safe handle directly. We are using the AesCryptoServiceProvider class which uses them internally. I don't think its behavior is right, but at least calling Dispose on instances of that class solves the issue, so that's what we will do in the next release (if you would like to try a beta, please let me know).
commented Jul 28, 2010 by _FRED_ (640 points)
Thanks! This is a good news (I like debugging with enabled MDA) and I can to try beta.
...