Recipe17.20.Obtaining a Safer File Handle


Recipe 17.20. Obtaining a Safer File Handle

Problem

You want more security when manipulating an unmanaged file handle than a simple IntPtr can provide.

Solution

Use the Microsoft.Win32.SafeHandles.SafeFileHandle object to wrap an existing unmanaged file handle:

 public static void WriteToFileHandle(IntPtr hFile) {     // Wrap our file handle in a safe handle wrapper object.     using (Microsoft.Win32.SafeHandles.SafeFileHandle safeHFile =         new Microsoft.Win32.SafeHandles.SafeFileHandle(hFile, true))     {         // Open a FileStream object using the passed-in safe file handle.         using (FileStream fileStream = new FileStream(safeHFile,                FileAccess.ReadWrite))         {            // Flush before we start to clear any pending unmanaged actions.            fileStream.Flush();            // Operate on file here.            string line = "Using a safe file handle object";            // Write to the file.            byte[] bytes = Encoding.ASCII.GetBytes(line);            fileStream.Write(bytes,0,bytes.Length);         }     }     // Note that the hFile handle is invalid at this point. } 

The SafeFileHandle constructor takes two arguments. The first is an IntPtr that contains a handle to an unmanaged resource. The second argument is a Boolean value, where true indicates that the handle will always be released during finalization and false indicates that the safeguards that force the handle to be released during finalization are turned off. Unless you have an extremely good reason to turn off these safeguards, it is recommended that you always set this Boolean value to true.

Discussion

A SafeFileHandle object contains a single handle to an unmanaged file resource. This class has two major benefits over using an IntPtr to store a handlecritical finalization and prevention of handle recycling attacks. The SafeFileHandle is seen by the garbage collector as a critical finalizer, due to the fact that one of the SafeFileHandle's base classes is CriticalFinalizerObject. The garbage collector separates finalizers into two categories: critical and noncritical. The noncritical finalizers are run first, followed by the critical finalizers. If a FileStream's finalizer flushes any data, it can assume that the SafeFileHandle object is still valid, because the SafeFileHandle finalizer is guaranteed to run after the FileStream's.

The Close method on the FileStream object will also close its underlying SafeFileHandle object.


Since the SafeFileHandle falls under critical finalization, it means that the underlying unmanaged handle is always released (i.e., the SafeFileHandle.ReleaseHandle method is always called), even in situations in which the appdomain is corrupted and/or shutting down or the thread is being aborted. This will prevent resource handle leaks.

The SafeFileHandle object also helps to prevent handle recycling attacks. The operating system aggressively tries to recycle handles, so it is possible to close one handle and open another soon afterward and get the same value for the new handle. One way an attacker will take advantage of this is by forcing an accessible handle to close on one thread while it is possibly still being used on another in the hope that the handle will be recycled quickly and used as a handle to a new resource, possibly one that the attacker does not have permission to access. If the application still has this original handle and is actively using it, data corruption could be an issue.

Since this class inherits from the SafeHandleZeroOrMinusOneIsInvalid class, a handle value of zero or minus one is considered an invalid handle.

See Also

See the "Microsoft.Win32.SafeHandles.SafeFileHandle Class" topic in the MSDN documentation.



C# Cookbook
Secure Programming Cookbook for C and C++: Recipes for Cryptography, Authentication, Input Validation & More
ISBN: 0596003943
EAN: 2147483647
Year: 2004
Pages: 424

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net