Possible causes of STATUS_DEVICE_POWER_FAILURE for a virtual display adapter?

I know less than nothing about display drivers. But…

was hoping that if I traced the CreateFile API to the point of failure (down in the kernel), I’d have an ‘Ah Hah!’ moment. Unfortunately, I didn’t know how to interpret the results.

You showed that the failure occurred in IopParseDevice (the “parse” method for DEVICE_OBJECT). This is expected, as this is the function in the I/O Manager where the Create IRP is built and sent to the driver.

At SOME point, I’d expect IopParseDevice to call SeAccessCheck. Either step through IopParseDevice (a real snoozer) or perhaps start by setting a breakpoint on SeAccessCheck?

There are two issues here: Why are you getting back access denied, and if this is related to the ACL what is the ACL set to?

I hate to ask the obvious, but have you looked at the ACL on the Device Object in question?

Don’t know if any of that is helpful. Like I said, I can barely find the power button to turn on my display device, I know so little about this particular device class.

Peter

1 Like

Thanks for jumping in Mr. Viscarola. Your advice emphasizes my suggestion to try the security descriptor in the INF file. Feedback is still pending…

Probably not much knowledge about the display device class needed any more to hang around in this thread.
We have an OS supplied function driver (WUDFRd.sys) together with an OS supplied upper filter (IndirectKmd.sys). The chances of finding any problem with these OS supplied drivers is magnitudes smaller than pinpointing the problem either at the application code or the UMDF driver DLL code (e.g. something dangling). Hence my comment about kernel mode debugging (for those who didn’t notice: quoting a line from a very popular 2015 movie “Old but not obsolete!”).

Two potential outcomes:

  1. Bug or potential usage problem with OS supplied display drivers:
    Very small probability.

  2. Needle in the haystack of developer’s code:
    Very high probability.

How far can/shall we proceed here?

Marcel Ruedinger
datronicsoft

1 Like

Hi Peter,

Thanks for chiming in!

…this is the function in the I/O Manager where the Create IRP is built and sent to the driver.
At SOME point, I’d expect IopParseDevice to call SeAccessCheck.

Yes indeed. I was able to determine that SeAccessCheck was returning a different result depending on whether or not I’d cycled the enabled state of the device.

Either step through IopParseDevice (a real snoozer) or perhaps start by setting a breakpoint on SeAccessCheck?

I did both. WinDbg is only showing me the assembly, with symbols. I know enough about the calling/return convention that I was able to painstakingly figure out what the arguments/returns were from IopParseDevice and SeAccessCheck. I have some old (outdated) NT source code I can (mostly) follow along by watching for specific calls, but my x86-Fu isn’t strong enough for me to grok what’s going on at source level most of the time.

There are two issues here: Why are you getting back access denied, and if this is related to the ACL what is the ACL set to?
I hate to ask the obvious, but have you looked at the ACL on the Device Object in question?

I manually examined the arguments going into SeAccessCheck for both (failure/success) cases. In my notes below, values are in hex and differences between cases are called out with “(Fail)” and “(Success)”:

IN PSECURITY_DESCRIPTOR SecurityDescriptor
    {
       UCHAR Revision .. 0x01
       UCHAR Sbz1 ...... 0x00
       SECURITY_DESCRIPTOR_CONTROL Control
            (Fail) ..... 0x9814 (SE_SELF_RELATIVE | SE_DACL_PROTECTED | SE_SACL_AUTO_INHERITED | SE_SACL_PRESENT | SE_DACL_PRESENT)
            (Success) .. 0x8014 (SE_SELF_RELATIVE |                                              SE_SACL_PRESENT | SE_DACL_PRESENT)
       PSID Owner
       {
           BYTE  Revision ................................ 01
           BYTE  SubAuthorityCount ....................... 02
           SID_IDENTIFIER_AUTHORITY IdentifierAuthority .. 00 00 00 00 00 05 [SECURITY_NT_AUTHORITY]
           DWORD SubAuthority[ANYSIZE_ARRAY]
           ................................................[0] 00000020 [NETWORK_SERVICE]
           ................................................[1] 00000220 [BUILTIN_ADMINISTRATORS]
       }
       PSID Group
       {
           BYTE  Revision ................................ 01
           BYTE  SubAuthorityCount ....................... 01
           SID_IDENTIFIER_AUTHORITY IdentifierAuthority .. 00 00 00 00 00 05 [SECURITY_NT_AUTHORITY]
           DWORD SubAuthority[ANYSIZE_ARRAY]
           ................................................[0] 00000012 [RESTRICTED_CODE]
       }
       PACL Sacl
       {
            BYTE AclRevision .. 02
            BYTE Sbz1 ......... 00
            WORD AclSize ...... 001c
            WORD AceCount ..... 0001
            WORD Sbz2 ......... 0000
            .................... 11 00 14 00 01 00 00 00 01 01 00 00 00 00 00 10 00 10 00 00
       }
       PACL Dacl
       {
            BYTE AclRevision .. 02
            BYTE Sbz1 ......... 00
            WORD AclSize
                (Fail) ........ 001c
                (Success) ..... 006c
            WORD AceCount
                (Fail) ........ 0001
                (Success) ..... 0004
            WORD Sbz2 ......... 0000
                (Fail) ........ 00 00 14 00 ff 01 1f 00 01 01 00 00 00 00 00 05 12 00 00 00
                (Success) ..... 00 00 14 00 bf 01 12 00 01 01 00 00 00 00 00 01 00 00 00 00
       }
    } // PSECURITY_DESCRIPTOR SecurityDescriptor

IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext
    PACCESS_TOKEN ClientToken ........................ 00000000`00000000
    SECURITY_IMPERSONATION_LEVEL ImpersonationLevel .. 0x00000000 [SecurityAnonymous]
    PACCESS_TOKEN PrimaryToken ....................... (non-null in both cases, but didn't record this)
    PVOID ProcessAuditId
        (Fail) ....................................... 0x00000000000006d4 (???)
        (Success) .................................... 0x0000000000001d2c (???)
IN BOOLEAN SubjectContextLocked ......... TRUE
IN ACCESS_MASK DesiredAccess ............ 00 10 0080 (SYNCHRONIZE | FILE_READ_ATTRIBUTES)
IN ACCESS_MASK PreviouslyGrantedAccess .. 00 00 0000
OUT PPRIVILEGE_SET * Privileges ......... (non-null in both cases)
IN PGENERIC_MAPPING GenericMapping
    ACCESS_MASK GenericRead ..... 00 12 0089 (SYNCHRONIZE | READ_CONTROL | FILE_READ_ATTRIBUTES | FILE_READ_EA | FILE_READ_DATA)
    ACCESS_MASK GenericWrite .... 00 12 0116 (SYNCHRONIZE | READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | FILE_APPEND_DATA | FILE_WRITE_DATA)
    ACCESS_MASK GenericExecute .. 00 12 00a0 (SYNCHRONIZE | READ_CONTROL | FILE_READ_ATTRIBUTES | FILE_EXECUTE)
    ACCESS_MASK GenericAll ...... 00 1f 01ff (SYNCHRONIZE | DELETE | READ_CONTROL | WRITE_DAC | WRITE_OWNER | FILE_WRITE_ATTRIBUTES | ...all...)
IN KPROCESSOR_MODE AccessMode .......... 0x01 [UserMode]
OUT PACCESS_MASK GrantedAccess ......... (non-null in both cases)
OUT PNTSTATUS AccessStatus ............. (non-null in both cases)

I’m reading up on ACLs, access tokens, privileges, security descriptors and SIDs right now. I’ve never really understood Windows security very well.

Hi Marcel,

  1. Needle in the haystack of developer’s code:
    Very high probability.

I was fairly certain that I’d introduced this during refactoring and enhancement of the V1 driver to the V2 driver. I was typing up a response to your last post this morning when I realized that I’d never actually checked to confirm that this doesn’t happen with the V1 driver.

The V1 driver didn’t have a custom IOCTL interface, so I think I initially discarded the idea. But it’s a simple matter to add a single WdfDeviceCreateDeviceInterface API call (in the same place) to the V1 code, so I did that, built it and ran the console test against it…

The V1 driver behaves the same; it initially fails the CreateFile call, but succeeds after I disable/re-enable the device in Device Manager.

So, I’m still betting this is down to something I did wrong, but I don’t need to go through the tedious process of looking for some subtle difference between my V1 and V2 drivers. Whatever this is, it was present from the beginning. I only noticed recently because the V1 driver didn’t have a custom interface.

Your advice emphasizes my suggestion to try the security descriptor in the INF file

Agreed. I’m reading up on Windows security at the moment. I’ve dealt with it intermittently in the past, but always in a yak shaving context. This time I’m going to try to understand it thoroughly enough that I don’t forget it all before I need it again.

I’ll try your suggestion and report back as soon as I figure out what my security descriptor should be…

Thanks!

Oh, and I’m also going to build the Microsoft example that V1 was based upon, and test that too. I’ll let you know.

You are really coming down on this thing, aren’t you?
I like it!
And who knows - maybe we will even really find a bug in the WDK IddCx sample or framework?
Wouldn’t be the first one I found (last one was in the 2007 Wave Cyclic audio sample - confirmed and fixed by MS).
IddCx framework is still very young (introduced in 2016 with Win 10 1607).
So the chances aren’t all that bad :wink:

Marcel Ruedinger
datronicsoft

There’s are WinDbg extensions !sd and !acl, in case they’d help. The ACL isn’t useful unless you can actuially read it. :wink:

This is extremely strange. It’s GOT to be something very simple that’s crossing you up. Hmmmm… wish I could offer-up more useful suggestions. I assume you’ve got Driver Verifier and WDF Verifier all enabled. And I assume that you’ve checked the log. Geez… who’s changing the ACL on the device, when, and more interestingly WHY?

Peter

Mr. Viscarola,
before spending too much time on this, you might probably want to know why I supplied a security descriptor for the INF file. I wanted my INF based security descriptor (which doesn’t require admin privileges) to overrule the PDO security. Careful - this PDO is created using SwDeviceCreate(…) which can also specify a security descriptor. I wanted to avoid all these details and eliminate exactly these degrees of freedom which are confusing us now. Unfortunately, my suggestions haven’t been followed yet…

Marcel Ruedinger
datronicsoft

Oh, and I’m also going to build the Microsoft example that V1 was based upon, and test that too. I’ll let you know.

  1. Made sure I had the latest copy of the Windows driver samples

  2. Modified driver (Windows-driver-samples\video\IndirectDisplay\IddSampleDriver) in the same way as above:

…add a single WdfDeviceCreateDeviceInterface API call (in the same place)

  1. Installed on two different test machines, and ran my console tester.

Issue exists with the sample driver

CreateFilecall returns Access Denied on the initial test after install. After I cycle enabled on the device, the CreateFile call succeeds.

I haven’t tried specifying an SDDL in the .inf file yet – still reading… I’ll post here after I do

Now you made me curious!

I just tried the same myself…
…and surprise, surprise…
…yes, indeed, you are right!

Quick further tests/observations:

  • Even happens without IddCx framework calls and IndirectKmd upper filter.
  • Only seems to disappear when changing the Setup Class in the INF file to something different than Display.

Hmmmm - need to think about this…

Marcel Ruedinger
datronicsoft

1 Like

I’m starting to fell like this may have something to do with the very, very, ugly “propagating of security descriptors” through a dev node.

That code, which dates back to almost ten years ago, was very subtle and reasonably complex. I wonder if it got broken. If you’re not aware of the issues, there’s an article here.

Peter

ETA: I just re-read that article… and, wow! The whole Device Object protection thing is even more complicated than I remembered. And I wrote that article. Maybe there’s something there that’ll help?

I don’t want to be a smartass, but just one hint: If you finally listen to my advice, then you can proceed without even worrying about this.

One of the reasons why I gave you this advice was the fact that I had discovered some customers of ours successfully using IddCx upper edge with my above mentioned security descriptor. I also found some other customers using a different security descriptor requiring administrative privileges.

PS: Further research postponed to the next weekend.

Marcel Ruedinger
datronicsoft

just one hint: If you finally listen to my advice, then you can proceed without even worrying about this

I’ve dragged my feet on this for a few reasons. I didn’t assume that your example SDDL could be copied verbatim into my .inf file (sounds like you’re suggesting that it can, though). I don’t yet know enough to confidently compose my own. Also, I wanted to pursue this far enough to feel assured that assigning a security descriptor in the INF file (vs. using the default) wouldn’t just be masking the root problem.

Noticed today that each time I disable/enable the adapter, it toggles between returning Access Denied and succeeding.

I.e., it goes from working back to not working if I toggle the enabled state. Then it goes from not working back to working when I toggle it again…

Why “sounds like”? Was there anything wrong or difficult to understand?

PS: Always glad to improve my foreign language skills in English if possible :wink:

Marcel Ruedinger
datronicsoft

I didn’t assume that your example SDDL could be copied verbatim into my .inf file (sounds like you’re suggesting that it can, though)

Why “sounds like”? Was there anything wrong or difficult to understand?

Not at all. Your English is so perfect, I forgot that it’s not your native language. :slight_smile:

Ever tried to assign a security descriptor in the INF file (see example below)?

From the word example above, it wasn’t clear that the implication was to use the provided string verbatim. I’ll go ahead and do that and report back shortly.

Yes, I observed the same funny behavior (and probably even more than that).
The whole thing is probably specific to the Setup Class Display.
I vaguely remember that I might have experienced similar effects decades ago with Windows XP when I wrote a Filter Driver for \Device\VideoX and DosDevices\DisplayY. I will try to find out what this is all about…

Short status summary to touch base again with 100% mutual understanding:
I initially gave you this security descriptor only because your application was my primary suspect. I considered (and still do) that this was the most effective approach at that time. It would have either pointed at your application or ruled it out immediately. Now that you ruled it out the hard way, the security descriptor has probably become the only remaining option to get something up and running at all.

BTW: Two of our messages above must have crossed. My reply obviously has missed one post of yours.

Marcel Ruedinger
datronicsoft

Marcel, et. al.,

I added the HKR,, Security,, "D:P(A;;GA;;;SY)(A;;GA;;;BA)(A;;GA;;;WD)(A;;GA;;;RC)" line to my .inf file and the problem disappeared. It doesn’t occur after driver install or Windows restart.

Thanks for your help with this!

Wait - we are not done yet! Who was the one who didn’t want to take this security descriptor verbatim? :wink:

We still have to ask one fundamental question here: Do you want to require admin privileges for your application to access the IddCx driver upper edge IOCTL interface? In that case, the above security descriptor is not good!

It might actualy make very good sense to require admin privileges for the API here in this case. You might already have noticed that your application needs admin privileges anyway, right? This is due to SwDeviceCreate(…).

Marcel Ruedinger
datronicsoft

Do you want to require admin privileges for your application to access the IddCx driver upper edge IOCTL interface?

Yes, definitely.

I haven’t done it yet, but I was planning to go through the SDS you gave me and make sure I understood what it was doing.