1

I've been getting a completely random exception, I can run the same set of code 1000 times (each "run" is a full end-end of the program and thus starts as its own process from commandline and then exists) and get it fail once, or even 150 times. And I mean I can run it back-back over and over and it will fail completely randomly.

System.Security.AccessControl.PrivilegeNotHeldException: The process does not possess the 'SeSecurityPrivilege' privilege which is required for this operation.
at System.Security.AccessControl.Win32.GetSecurityInfo(ResourceType resourceType, String name, SafeHandle handle, AccessControlSections accessControlSections, RawSecurityDescriptor& resultSd)
at System.Security.AccessControl.NativeObjectSecurity.CreateInternal(ResourceType resourceType, Boolean isContainer, String name, SafeHandle handle, AccessControlSections includeSections, Boolean createByName, ExceptionFromErrorCode exceptionFromErrorCode, Object exceptionContext)
at System.Security.AccessControl.RegistrySecurity..ctor(SafeRegistryHandle hKey, String name, AccessControlSections includeSections) 
at Microsoft.Win32.RegistryKey.GetAccessControl(AccessControlSections includeSections)

I can't get it to fail when debugging so am having issues trying to see why it randomly decides to fail. As its failing inside the (RegistryKey).GetAccessControl(AccessControlSections.All) method, I'm stumped as to what I should try next.

Also, I'm looping through multiple keys, and if it decides to fail with this permission exception on one, they all fail for that process.

I'm running from command line (as admin, UACed in), starting the process and then it exists. From that same command line I start the process again, and it will randomly fail.

I am loading user hives and making sure that the registry rights are elevated, and it works except for this random bug.

Also, the issue occurs on multiple machines (always running locally, not remote), both under system (psexec) and administrator accounts.

John
  • 6,503
  • 3
  • 37
  • 58
  • We are going to need some code to help you I think. – Tony Hopkinson Jul 26 '12 at 22:34
  • @TonyHopkinson What would you like to see exactly? Its failing inside the `(RegistryKey).GetAccessControl(AccessControlSections.All)` call – John Jul 27 '12 at 01:43
  • Hard to say. Given it's intermittent and doesn't occur in debug. I'm thinking it's maybe a lifetime issue with the GC, or similar resources problem. One way to sort of point to that would be to put a sleep in the loop through the entries. Only a wild guess I have even less clues than you at the moment. Another equally nasty fix, might be to trap the exception and retry... – Tony Hopkinson Jul 27 '12 at 15:09
  • @TonyHopkinson yep, I've tried capturing it with a try and then sleeping for 10 seconds and then retrying, and it still errors... Strangely it either works 100% for all attempts for the lifetime of the process, or fails 100% for all attempts for the lifetime of the process.... So I can run the process start->end and it either works, or not for every key the process needs to update :( – John Jul 27 '12 at 16:26

1 Answers1

1

I don't think that the System account has the SeSecurityPrivilege enabled, or an admin for that matter.

Instead of (RegistryKey).GetAccessControl(AccessControlSections.All), try: (RegistryKey).GetAccessControl(AccessControlSections.Access)

Does that still give you the error? You won't be able to get the SACL with Access though.

EDIT: I grabbed some code from pinvoke for adjusting the privileges in an access token, you'll need admin rights to do it; I modified it for the SeSecurityPrivilege, you should be able to use (RegistryKey).GetAccessControl(AccessControlSections.All) now without any errors once "SetPriv();" is called. I was able to verify that it is working by using Process Hacker 2 and checking the token before and after, it is enabling SeSecuirtyPrivilege:

    [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
    internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall, ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);

    [DllImport("kernel32.dll", ExactSpelling = true)]
    internal static extern IntPtr GetCurrentProcess();

    [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
    internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr
    phtok);

    [DllImport("advapi32.dll", SetLastError = true)]
    internal static extern bool LookupPrivilegeValue(string host, string name,
    ref long pluid);

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    internal struct TokPriv1Luid
    {
        public int Count;
        public long Luid;
        public int Attr;
    }

    internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
    internal const int TOKEN_QUERY = 0x00000008;
    internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
    internal const string SeSecurity = "SeSecurityPrivilege";

    private bool SetPriv()
   {
       try
       {
           bool retVal;
           TokPriv1Luid tp;
           IntPtr hproc = GetCurrentProcess();
           IntPtr htok = IntPtr.Zero;
           retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
           tp.Count = 1;
           tp.Luid = 0;
           tp.Attr = SE_PRIVILEGE_ENABLED;
           retVal = LookupPrivilegeValue(null, SeSecurity, ref tp.Luid);
           retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
           return retVal;
       }
       catch (Exception ex)
       {
           throw;
           return false; 
       }

   }
0_______0
  • 547
  • 3
  • 11
  • Why would it work most of the time then? Like I said, I'm only getting this error randomly, so while it works 90% of the time, it will error out 10% (even when run back-back) – John Jul 27 '12 at 02:40
  • I can't explain that, maybe someone else can. As far as I'm aware, using `Access` should never require SeSecurityPrivilege, so with `Access` you shouldn't get the error. So unless you need `All` to access something you can't get with `Access`, I'd try it with `Access` and see if you stop getting the error. – 0_______0 Jul 27 '12 at 03:11
  • Yeah I tried `Access` instead if it fails to read `All` and that worked, not sure why its failing though, maybe someone else can answer that, if not the `Access` workaround will work, just not sure what kind of side effects it will have. – John Jul 27 '12 at 16:53
  • I edited my answer with code to enable the SeSecurityPrivilege, you should be able to use `All` now and not get any errors once the privilege has been enabled. – 0_______0 Jul 27 '12 at 18:18
  • Thanks for the help, I haven't tried your latest update of code but it was working with `All` falling back to `Access`, it was already doing some permission elevation requests to be able to modify hives and I'll make sure it does a request for the `SeSecurityPrivilege` as well. Still don't know why it was so random and why it would fail. Thanks for the help! :) – John Jul 31 '12 at 21:14