Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

469 lines
14 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. IoDevObj.c
  5. Abstract:
  6. This module contains functions for managing device objects.
  7. Author:
  8. Adrian J. Oney - April 21, 2002
  9. Revision History:
  10. --*/
  11. #include "WlDef.h"
  12. #include "IopDevObj.h"
  13. #pragma hdrstop
  14. #ifdef ALLOC_PRAGMA
  15. #pragma alloc_text(PAGE, IoDevObjCreateDeviceSecure)
  16. #pragma alloc_text(PAGE, IopDevObjAdjustNewDeviceParameters)
  17. #pragma alloc_text(PAGE, IopDevObjApplyPostCreationSettings)
  18. #endif
  19. NTSTATUS
  20. IoDevObjCreateDeviceSecure(
  21. IN PDRIVER_OBJECT DriverObject,
  22. IN ULONG DeviceExtensionSize,
  23. IN PUNICODE_STRING DeviceName OPTIONAL,
  24. IN DEVICE_TYPE DeviceType,
  25. IN ULONG DeviceCharacteristics,
  26. IN BOOLEAN Exclusive,
  27. IN PCUNICODE_STRING DefaultSDDLString,
  28. IN LPCGUID DeviceClassGuid OPTIONAL,
  29. OUT PDEVICE_OBJECT *DeviceObject
  30. )
  31. /*++
  32. Routine Description:
  33. This routine creates a securable named device object. The security settings
  34. for the device object are retrieved from the registry or constructed using
  35. the passed in defaults if registry overrides are not available.
  36. It should be used
  37. 1. To secure legacy device objects
  38. 2. To secure raw PnP PDOs
  39. It should not be used to create FDOs, non-raw PDOs, or any unnamed objects.
  40. For those operations, IoCreateDevice should be used.
  41. Arguments:
  42. DriverObject - A pointer to the driver object for this device.
  43. DeviceExtensionSize - Size, in bytes, of extension to device object;
  44. i.e., the size of the driver-specific data for this device object.
  45. DeviceName - Optional name that should be associated with this device.
  46. If the DeviceCharacteristics has the FILE_AUTOGENERATED_DEVICE_NAME
  47. flag set, this parameter is ignored.
  48. DeviceType - The type of device that the device object should represent.
  49. Possibly overriden by registry.
  50. DeviceCharacteristics - The characteristics for the device. Additional
  51. flags may be supplied by the registry.
  52. Exclusive - Indicates that the device object should be created with using
  53. the exclusive object attribute. Possibly overriden by registry.
  54. NOTE: This flag should not be used for WDM drivers. Since only the
  55. PDO is named, it is the only device object in a devnode attachment
  56. stack that is openable. However, since this device object is created
  57. by the underlying bus driver (which has no knowledge about what type
  58. of device this is), there is no way to know whether this flag should
  59. be set. Therefore, this parameter should always be FALSE for WDM
  60. drivers. Drivers attached to the PDO (e.g., the function driver) must
  61. enforce any exclusivity rules.
  62. DefaultSDDLString - In the absense of registry settings, this string
  63. specifies the security to supply for the device object.
  64. Only the subset of the SDDL format is currently supported. The format
  65. is:
  66. D:P(ACE)(ACE)(ACE), where (ACE) is (AceType;;Access;;;SID)
  67. Where:
  68. AceType - Only Allow ("A") is supported.
  69. Access - Rights specified in either hex format (0xnnnnnnnn), or via the
  70. SDDL Generic/Standard abbreviations
  71. SID - Abbreviated security ID
  72. (WD, BA, SY, IU, RC, AU, NU, AN, BG, BU, LS, NS)
  73. The S-w-x-y-z form for SIDs is not supported
  74. The unimplemented ace fields are:
  75. AceFlags - Describes features such as inheritance for sub-objects
  76. (ie files) and containers (ie keys/folders). An example SDDL
  77. AceFlag string would be ("OICI"). While control over
  78. inheritance is crucial for registry keys and files, it's
  79. irrelevant for device objects. As such, this function supports
  80. no ACE flags.
  81. ObjectGuid - Used for describing rights that transcent the 32bit
  82. mask supplied by the OS. Typically used for Active Directory
  83. objects.
  84. InheritObjectGuid - - Used for describing rights that transcent the
  85. 32bit mask supplied by the OS. Typically used for Active
  86. Directory objects.
  87. Example -
  88. "D:P(A;;GA;;;SY)" which is Allow System to have Generic All access.
  89. DeviceClassGuid - Supplies a device install class GUID. This class is
  90. looked up in the registry to see if any potential overrides exist.
  91. For legacy device objects, the caller may need to invent an appropriate
  92. class GUID (see IoCreateDeviceSecure documention on how to properly
  93. install a full class).
  94. Note that if no registry override exists, the registry will
  95. automatically be updated to *reflect* the default SDDL string.
  96. Therefore it is a very bad idea to use the same device class GUID with
  97. different DefaultSDDLString values (objects needing different default
  98. security should have different classes, or be secured via INFs where
  99. possible).
  100. DeviceObject - Pointer to the device object pointer this routine will
  101. return.
  102. Return Value:
  103. NTSTATUS.
  104. --*/
  105. {
  106. PSECURITY_DESCRIPTOR securityDescriptor;
  107. STACK_CREATION_SETTINGS stackSettings, updateSettings;
  108. PDEVICE_OBJECT newDeviceObject;
  109. UNICODE_STRING classKeyName;
  110. DEVICE_TYPE finalDeviceType;
  111. ULONG finalCharacteristics;
  112. BOOLEAN finalExclusivity;
  113. ULONG disposition;
  114. NTSTATUS status;
  115. PAGED_CODE();
  116. //
  117. // Preinit for failure
  118. //
  119. *DeviceObject = NULL;
  120. newDeviceObject = NULL;
  121. //
  122. // The device object is securable only if it has a name. Therefore, we fail
  123. // the create call if the device doesn't have a name.
  124. //
  125. if (!(ARGUMENT_PRESENT(DeviceName) ||
  126. (DeviceCharacteristics & FILE_AUTOGENERATED_DEVICE_NAME))) {
  127. return STATUS_INVALID_PARAMETER;
  128. }
  129. if (ARGUMENT_PRESENT(DeviceClassGuid)) {
  130. //
  131. // Try to find the appropriate security descriptor for the device. First
  132. // look for an override in the registry using the class GUID. We will
  133. // create a section in the registry if one doesn't exist as well. This is
  134. // a clue to the system administrator that there is something to lock down
  135. // in the system.
  136. //
  137. status = PpRegStateReadCreateClassCreationSettings(
  138. DeviceClassGuid,
  139. DriverObject,
  140. &stackSettings
  141. );
  142. if (!NT_SUCCESS(status)) {
  143. return status;
  144. }
  145. } else {
  146. PpRegStateInitEmptyCreationSettings(&stackSettings);
  147. }
  148. //
  149. // If a registry setting wasn't specified, parse the default SDDL string.
  150. //
  151. if (!(stackSettings.Flags & DSIFLAG_SECURITY_DESCRIPTOR)) {
  152. //
  153. // Parse the SDDL string into a security descriptor, and mark it
  154. // "default" as well. SE_DACL_DEFAULT means the DACL came from a
  155. // "default" mechanism, typically implying parental inheritance or
  156. // object default security. In our case, the "default source" is the
  157. // library as opposed to the user or an INF.
  158. //
  159. status = SeSddlSecurityDescriptorFromSDDL(
  160. DefaultSDDLString,
  161. TRUE,
  162. &securityDescriptor
  163. );
  164. if (!NT_SUCCESS(status)) {
  165. goto Exit;
  166. }
  167. PpRegStateLoadSecurityDescriptor(
  168. securityDescriptor,
  169. &stackSettings
  170. );
  171. if (ARGUMENT_PRESENT(DeviceClassGuid)) {
  172. //
  173. // Update the registry with the default SDDL string so that the
  174. // admin knows what settings are being used for this class. Note
  175. // that we don't free updateSettings, as the security descriptor
  176. // is also used by stackSettings.
  177. //
  178. PpRegStateInitEmptyCreationSettings(&updateSettings);
  179. PpRegStateLoadSecurityDescriptor(
  180. securityDescriptor,
  181. &updateSettings
  182. );
  183. status = PpRegStateUpdateStackCreationSettings(
  184. DeviceClassGuid,
  185. &updateSettings
  186. );
  187. if (!NT_SUCCESS(status)) {
  188. goto Exit;
  189. }
  190. }
  191. }
  192. //
  193. // Fill out the default values
  194. //
  195. finalDeviceType = DeviceType;
  196. finalCharacteristics = DeviceCharacteristics;
  197. finalExclusivity = Exclusive;
  198. //
  199. // Adjust the parameters based on the registry overrides
  200. //
  201. IopDevObjAdjustNewDeviceParameters(
  202. &stackSettings,
  203. &finalDeviceType,
  204. &finalCharacteristics,
  205. &finalExclusivity
  206. );
  207. //
  208. // Create the device object. The newly created object should have the
  209. // DO_DEVICE_INITIALIZING flag on it, meaning it cannot be opened. We
  210. // therefore still have an opportunity to apply security.
  211. //
  212. status = IoCreateDevice(
  213. DriverObject,
  214. DeviceExtensionSize,
  215. DeviceName,
  216. finalDeviceType,
  217. finalCharacteristics,
  218. finalExclusivity,
  219. &newDeviceObject
  220. );
  221. if (!NT_SUCCESS(status)) {
  222. goto Exit;
  223. }
  224. ASSERT(newDeviceObject->Flags & DO_DEVICE_INITIALIZING);
  225. status = IopDevObjApplyPostCreationSettings(
  226. newDeviceObject,
  227. &stackSettings
  228. );
  229. if (!NT_SUCCESS(status)) {
  230. IoDeleteDevice(newDeviceObject);
  231. goto Exit;
  232. }
  233. *DeviceObject = newDeviceObject;
  234. Exit:
  235. //
  236. // Clean up the security descriptor as appropriate.
  237. //
  238. PpRegStateFreeStackCreationSettings(&stackSettings);
  239. return status;
  240. }
  241. VOID
  242. IopDevObjAdjustNewDeviceParameters(
  243. IN PSTACK_CREATION_SETTINGS StackCreationSettings,
  244. IN OUT PDEVICE_TYPE DeviceType,
  245. IN OUT PULONG DeviceCharacteristics,
  246. IN OUT PBOOLEAN Exclusive
  247. )
  248. /*++
  249. Routine Description:
  250. This routine adjusts a newly created device object to reflect the passed
  251. in stack creation settings.
  252. Arguments:
  253. StackCreationSettings - Information reflecting the settings to apply.
  254. DeviceType - On input, the device type specified by the caller. This field
  255. is updated to reflect any changes specified in the registry.
  256. DeviceCharacteristics - On input, the characteristics specified by the
  257. caller. This field is updated to reflect any changes specified in the
  258. registry.
  259. Exclusive - On input, the exclusivity specified by the caller. This field
  260. is updated to reflect any changes specified in the registry.
  261. Return Value:
  262. None.
  263. --*/
  264. {
  265. PAGED_CODE();
  266. if (StackCreationSettings->Flags & DSIFLAG_DEVICE_TYPE) {
  267. *DeviceType = StackCreationSettings->DeviceType;
  268. }
  269. if (StackCreationSettings->Flags & DSIFLAG_CHARACTERISTICS) {
  270. *DeviceCharacteristics = StackCreationSettings->Characteristics;
  271. }
  272. if (StackCreationSettings->Flags & DSIFLAG_EXCLUSIVE) {
  273. *Exclusive = (BOOLEAN) StackCreationSettings->Exclusivity;
  274. }
  275. }
  276. NTSTATUS
  277. IopDevObjApplyPostCreationSettings(
  278. IN PDEVICE_OBJECT DeviceObject,
  279. IN PSTACK_CREATION_SETTINGS StackCreationSettings
  280. )
  281. /*++
  282. Routine Description:
  283. This routine adjusts a newly created device object to reflect the passed
  284. in stack creation settings.
  285. Arguments:
  286. DeviceObject - Device object who's settings to adjust.
  287. StackCreationSettings - Information reflecting the settings to apply.
  288. Return Value:
  289. NTSTATUS.
  290. --*/
  291. {
  292. SECURITY_INFORMATION securityInformation;
  293. ACCESS_MASK desiredAccess;
  294. BOOLEAN fromDefaultSource;
  295. NTSTATUS status;
  296. HANDLE handle;
  297. PAGED_CODE();
  298. if (!(StackCreationSettings->Flags & DSIFLAG_SECURITY_DESCRIPTOR)) {
  299. return STATUS_SUCCESS;
  300. }
  301. //
  302. // Get the corresponding securityInformation from the descriptor.
  303. //
  304. status = SeUtilSecurityInfoFromSecurityDescriptor(
  305. StackCreationSettings->SecurityDescriptor,
  306. &fromDefaultSource,
  307. &securityInformation
  308. );
  309. if (!NT_SUCCESS(status)) {
  310. return status;
  311. }
  312. #ifdef _KERNELIMPLEMENTATION_
  313. status = ObSetSecurityObjectByPointer(
  314. DeviceObject,
  315. securityInformation,
  316. StackCreationSettings->SecurityDescriptor
  317. );
  318. #else
  319. //
  320. // Since ObSetSecurityObjectByPointer isn't available on Win2K, we have to
  321. // use a rather sneaky trick. The device technically isn't openable yet.
  322. // However, ObOpenObjectByPointer doesn't bother doing any parse stuff.
  323. // Therefore, we can get a quick handle to the object, set the security
  324. // descriptor, and then dump the handle without the driver being any wiser.
  325. //
  326. SeSetSecurityAccessMask(securityInformation, &desiredAccess);
  327. status = ObOpenObjectByPointer(
  328. DeviceObject,
  329. OBJ_KERNEL_HANDLE,
  330. NULL,
  331. desiredAccess,
  332. *IoDeviceObjectType,
  333. KernelMode,
  334. &handle
  335. );
  336. if (!NT_SUCCESS(status)) {
  337. return status;
  338. }
  339. status = ZwSetSecurityObject(
  340. handle,
  341. securityInformation,
  342. StackCreationSettings->SecurityDescriptor
  343. );
  344. ZwClose(handle);
  345. #endif // _KERNELIMPLEMENTATION_
  346. return status;
  347. }