axe
axe

Reputation: 2371

Catching AccessViolation in .NET 4. Good or bad?

There is object of type SECURITY_IDENTIFIER structure in the file. I need to get owner SID from this structure. In order to do this I call GetSecurityDescriptorOwner WinAPI function and create System.Security.Principal.SecurityIdentifier (it has overload taking IntPtr as an argument)

The problem is this structure in file is broken sometimes, so the pointer I get from GetSecurityDescriptorOwner is invalid. It's not IntPtr.Zero, it's invalid, so when I create object of type SecurityIdentifier I get AccessViolationException, which is not possible to catch with .NET 4 with a simple try-catch.

I am aware of attribute which allows to catch such exceptions, so I used it for the time being, but I don't like this solution. It's not recommended to catch Corrupted State Exceptions (CSE), but I don't see any other solutions. This WinAPI function returns me invalid pointer and I see no way to check it for validness. Any ideas?

update

WinAPI

BOOL WINAPI GetSecurityDescriptorOwner(
  _In_   PSECURITY_DESCRIPTOR pSecurityDescriptor,
  _Out_  PSID *pOwner,
  _Out_  LPBOOL lpbOwnerDefaulted
);

Extern definition

[DllImport("Advapi32.dll")]
static extern bool GetSecurityDescriptorOwner(
   IntPtr pSecurityDescriptor,
   out IntPtr owner,
   out bool defaulted);

update

private static SecurityIdentifier GetSecurityIdentifier()
{
    // Allocate managed buffer for invalid security descriptor structure (20 bytes)
    int[] b = new int[5] {1, 1, 1, 1, 1};

    // Allocate unmanaged memory for security descriptor 
    IntPtr descriptorPtr = Marshal.AllocHGlobal(b.Length);

    // Copy invalid security descriptor structure to the unmanaged buffer
    Marshal.Copy(b, 0, descriptorPtr, b.Length);

    IntPtr ownerSid;
    bool defaulted;

    if (GetSecurityDescriptorGroup(descriptorPtr, out ownerSid, out defaulted))
    {
        // GetSecurityDescriptorGroup returns true, but `ownerSid` is `1`
        // Marshal.GetLastWin32Error returns 0 here
        return new SecurityIdentifier(ownerSid);
    }

    return null;
}

This code throws sometimes throws Corrupted State Exceptions from SecurityIdentifier constructor. Any solutions?

Upvotes: 4

Views: 479

Answers (2)

SmartK8
SmartK8

Reputation: 2626

Updated:

Try this instead:

    [DllImport("Advapi32.dll")]
    static extern bool GetSecurityDescriptorOwner(
       [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U4)]
       Int32[] securityDescriptor,
       [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U1)] 
       out Byte[] owner,
       out Boolean defaulted);


    [DllImport("Advapi32.dll")]
    static extern bool IsValidSecurityDescriptor(
        [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U4)] 
        Int32[] securityDescriptor);

    private static SecurityIdentifier GetSecurityIdentifier()
    {
        // Allocate managed buffer for invalid security descriptor structure (20 bytes)
        Int32[] b = new[] { 1, 1, 1, 1, 1 };

        Byte[] ownerSid;
        bool defaulted;

        if (IsValidSecurityDescriptor(b) &&
            GetSecurityDescriptorOwner(b, out ownerSid, out defaulted))
        {
            return new SecurityIdentifier(ownerSid, 0);
        }

        return null;
    }

    static void Main()
    {
        for (Int32 index = 0; index < 1000; index++)
        {
            SecurityIdentifier identifier = GetSecurityIdentifier();
            String text = identifier == null ? "(none)" : identifier.Value;
            Console.WriteLine(text);
        }

        Console.ReadKey();
    }

Upvotes: 0

to StackOverflow
to StackOverflow

Reputation: 124726

Have you tried calling IsValidSecurityDescriptor?

[DllImport("Advapi32.dll")]
static extern bool IsValidSecurityDescriptor(IntPtr pSecurityDescriptor);


if (IsValidSecurityDescriptor(descriptorPtr) && 
    GetSecurityDescriptorOwner(descriptorPtr, out ownerSid, out defaulted))
{
     return new SecurityIdentifier(ownerSid);
}

Upvotes: 1

Related Questions