+1 vote
by (640 points)
edited

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
by (144k 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.
by (640 points)
by (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
by (70.2k points)
edited
 
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;
by (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
by (144k points)
edited

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.

by (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.
by (144k 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).
by (640 points)
Thanks! This is a good news (I like debugging with enabled MDA) and I can to try beta.
...