September 2nd, 2024
likeheart3 reactions

The Co­Initialize­Security function demands an absolute security descriptor

One unfortunate requirement of the Co­Initialize­Security function is that it requires a security descriptor in absolute format. I call this unfortunate because the most common format for security descriptors is self-relative format. A common way to specify a security descriptor is to use the security descriptor definition language (SDDL), and the Convert­String­Security­Descriptor­To­Security­Descriptor function that converts these strings to security descriptors produces self-relative security descriptors. Another common way to specify a security descriptor is as a block of bytes, perhaps stored in the registry, or stored in a file, or just hard-coded into a binary blob, and these are naturally in self-relative format, since absolute format would be dependent on the location of the block of bytes in memory.

Unfortunately, if you pass a self-relative security descriptor to Co­Initialize­Security it fails with HRESULT_FROM_WIN32(ERROR_BAD_DESCRIPTOR_FORMAT). The requirement that the security descriptor be in absolute format is documented, but it’s still annoying.

Internally, the reason is that the Co­Initialize­Security converts the incoming security descriptor to relative format by calling Make­Self­Relative­SD, without first checking whether the conversion is even necessary. The Make­Self­Relative­SD function fails with ERROR_BAD_DESCRIPTOR_FORMAT if the security descriptor is not absolute, and that error is propagated from Co­Initialize­Security.

Now, Co­Initialize­Security could be updated to support self-relative security descriptor. It would just be a check whether the security descriptor is already self-relative, and using the existing one if so. However, this would create a compatibility problem, but not in the way you’re used to thinking of them.

Most of the time, the compatibility issue is “Will existing old code continue to work on a new system?” But in this case, the compatibility issues goes the other way: “Will new code continue to work on an old system?”

If Co­Initialize­Security started allowing self-relative security descriptors, then somebody writing code today could take advantage of this new feature (perhaps unwittingly), and then encounter problems when their program is run on an older version of Windows. There is no obvious indication as to what went wrong because the function Co­Initialize­Security does exist on the old system.

The scenario is that somebody wants to be compatible with (say) Windows 10 Version 1803, so they compile their program with the Windows 10 Version 1803 SDK, and it compiles just fine. It also runs fine on Windows 11, and since they used the Windows 10 version 1803 SDK, they erroneously conclude that the program also works on Windows 10 version 1803.

Now, maybe you say that somebody who does this deserves what they get, and maybe you’re right, but Windows traditionally has been wary of creating too many of these “pits of failure” where somebody proceeding with the best of intentions can stumble into a bad situation.

Topics

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

Single comment
  • tbodt

    This one seems easy enough to fix by Apple’s technique of giving the function the old behavior when the program is linked against the old SDK.