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.

538 lines
15 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. obinsert.c
  5. Abstract:
  6. Object instantiation API
  7. Author:
  8. Steve Wood (stevewo) 31-Mar-1989
  9. Revision History:
  10. --*/
  11. #include "obp.h"
  12. #ifdef ALLOC_PRAGMA
  13. #pragma alloc_text(PAGE,ObInsertObject)
  14. #endif
  15. NTSTATUS
  16. ObInsertObject (
  17. IN PVOID Object,
  18. IN PACCESS_STATE AccessState OPTIONAL,
  19. IN ACCESS_MASK DesiredAccess OPTIONAL,
  20. IN ULONG ObjectPointerBias,
  21. OUT PVOID *NewObject OPTIONAL,
  22. OUT PHANDLE Handle OPTIONAL
  23. )
  24. /*++
  25. Routine Description:
  26. This routine inserts an object into the current processes handle table.
  27. The Object header includes a pointer to a SecurityDescriptor passed in
  28. an object creation call. This SecurityDescriptor is not assumed to have
  29. been captured. This routine is responsible for making an appropriate
  30. SecurityDescriptor and removing the reference in the object header.
  31. Arguments:
  32. Object - Supplies a pointer to the new object body
  33. AccessState - Optionally supplies the access state for the new
  34. handle
  35. DesiredAccess - Optionally supplies the desired access we want for the
  36. new handle
  37. ObjectPointerBias - Supplies a bias to apply for the pointer count for the
  38. object
  39. NewObject - Optionally receives the pointer to the new object that we've
  40. created a handle for
  41. Handle - Receives the new handle, If NULL then no handle is created.
  42. Objects that don't have handles created must be unnamed and
  43. have an object bias of zero.
  44. Return Value:
  45. An appropriate NTSTATUS value.
  46. --*/
  47. {
  48. POBJECT_CREATE_INFORMATION ObjectCreateInfo;
  49. POBJECT_HEADER ObjectHeader;
  50. PUNICODE_STRING ObjectName;
  51. POBJECT_TYPE ObjectType;
  52. POBJECT_HEADER_NAME_INFO NameInfo;
  53. PSECURITY_DESCRIPTOR ParentDescriptor = NULL;
  54. PVOID InsertObject;
  55. HANDLE NewHandle;
  56. OB_OPEN_REASON OpenReason;
  57. NTSTATUS Status = STATUS_SUCCESS;
  58. ACCESS_STATE LocalAccessState;
  59. AUX_ACCESS_DATA AuxData;
  60. BOOLEAN SecurityDescriptorAllocated;
  61. KPROCESSOR_MODE PreviousMode;
  62. NTSTATUS ReturnStatus;
  63. PVOID DirObject = NULL;
  64. OBP_LOOKUP_CONTEXT LookupContext;
  65. PAGED_CODE();
  66. ObpValidateIrql("ObInsertObject");
  67. //
  68. // Get the address of the object header, the object create information,
  69. // the object type, and the address of the object name descriptor, if
  70. // specified.
  71. //
  72. ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
  73. #if DBG
  74. if ((ObjectHeader->Flags & OB_FLAG_NEW_OBJECT) == 0) {
  75. KdPrint(("OB: Attempting to insert existing object %08x\n", Object));
  76. KdBreakPoint();
  77. ObDereferenceObject(Object);
  78. return STATUS_INVALID_PARAMETER;
  79. }
  80. #endif
  81. ObjectCreateInfo = ObjectHeader->ObjectCreateInfo;
  82. ObjectType = ObjectHeader->Type;
  83. NameInfo = ObpReferenceNameInfo( ObjectHeader );
  84. ObjectName = NULL;
  85. if ((NameInfo != NULL) && (NameInfo->Name.Buffer != NULL)) {
  86. ObjectName = &NameInfo->Name;
  87. }
  88. ASSERT (ARGUMENT_PRESENT (Handle) || (ObjectPointerBias == 0 && ObjectName == NULL &&
  89. ObjectType->TypeInfo.SecurityRequired && NewObject == NULL));
  90. //
  91. // If security checks are not required and an object name is not
  92. // specified, insert an unnamed object, biasing the count
  93. // by one, dereference the bias, and return to our caller
  94. //
  95. PreviousMode = KeGetPreviousMode();
  96. if (!ObjectType->TypeInfo.SecurityRequired && (ObjectName == NULL)) {
  97. ObjectHeader->ObjectCreateInfo = NULL;
  98. *Handle = NULL;
  99. Status = ObpCreateUnnamedHandle( Object,
  100. DesiredAccess,
  101. 1 + ObjectPointerBias,
  102. ObjectCreateInfo->Attributes,
  103. PreviousMode,
  104. NewObject,
  105. Handle );
  106. //
  107. // Free the object creation information and dereference the object.
  108. //
  109. ObpFreeObjectCreateInformation(ObjectCreateInfo);
  110. ObpDereferenceNameInfo( NameInfo );
  111. ObDereferenceObject(Object);
  112. return Status;
  113. }
  114. //
  115. // The object is either named or requires full security checks. If the
  116. // caller hasn't specified an access state then dummy up a local one
  117. // using the requested desired access
  118. //
  119. if (!ARGUMENT_PRESENT(AccessState)) {
  120. AccessState = &LocalAccessState;
  121. Status = SeCreateAccessState( &LocalAccessState,
  122. &AuxData,
  123. DesiredAccess,
  124. &ObjectType->TypeInfo.GenericMapping );
  125. if (!NT_SUCCESS(Status)) {
  126. ObpDereferenceNameInfo( NameInfo );
  127. ObDereferenceObject(Object);
  128. return Status;
  129. }
  130. }
  131. AccessState->SecurityDescriptor = ObjectCreateInfo->SecurityDescriptor;
  132. //
  133. // Check the desired access mask against the security descriptor
  134. //
  135. Status = ObpValidateAccessMask( AccessState );
  136. if (!NT_SUCCESS( Status )) {
  137. if (AccessState == &LocalAccessState) {
  138. SeDeleteAccessState( AccessState );
  139. }
  140. ObpDereferenceNameInfo( NameInfo );
  141. ObDereferenceObject(Object);
  142. if (AccessState == &LocalAccessState) {
  143. SeDeleteAccessState( AccessState );
  144. }
  145. return( Status );
  146. }
  147. //
  148. // Set some local state variables
  149. //
  150. ObpInitializeLookupContext(&LookupContext);
  151. InsertObject = Object;
  152. OpenReason = ObCreateHandle;
  153. //
  154. // Check if we have an object name. If so then
  155. // lookup the name
  156. //
  157. if (ObjectName != NULL) {
  158. Status = ObpLookupObjectName( ObjectCreateInfo->RootDirectory,
  159. ObjectName,
  160. ObjectCreateInfo->Attributes,
  161. ObjectType,
  162. (KPROCESSOR_MODE)(ObjectHeader->Flags & OB_FLAG_KERNEL_OBJECT
  163. ? KernelMode : UserMode),
  164. ObjectCreateInfo->ParseContext,
  165. ObjectCreateInfo->SecurityQos,
  166. Object,
  167. AccessState,
  168. &LookupContext,
  169. &InsertObject );
  170. //
  171. // We found the name and it is not the object we have as our input.
  172. // So we cannot insert the object again so we'll return an
  173. // appropriate status
  174. //
  175. if (NT_SUCCESS(Status) &&
  176. (InsertObject != NULL) &&
  177. (InsertObject != Object)) {
  178. OpenReason = ObOpenHandle;
  179. if (ObjectCreateInfo->Attributes & OBJ_OPENIF) {
  180. if (ObjectType != OBJECT_TO_OBJECT_HEADER(InsertObject)->Type) {
  181. Status = STATUS_OBJECT_TYPE_MISMATCH;
  182. } else {
  183. Status = STATUS_OBJECT_NAME_EXISTS; // Warning only
  184. }
  185. } else {
  186. Status = STATUS_OBJECT_NAME_COLLISION;
  187. }
  188. }
  189. //
  190. // We did not find the name so we'll cleanup after ourselves
  191. // and return to our caller
  192. //
  193. if (!NT_SUCCESS( Status )) {
  194. ObpReleaseLookupContext( &LookupContext );
  195. ObpDereferenceNameInfo( NameInfo );
  196. ObDereferenceObject( Object );
  197. //
  198. // Free security information if we allocated it
  199. //
  200. if (AccessState == &LocalAccessState) {
  201. SeDeleteAccessState( AccessState );
  202. }
  203. return( Status );
  204. } else {
  205. //
  206. // Otherwise we did locate the object name
  207. //
  208. // If we just created a named symbolic link then call out to
  209. // handle any Dos Device name semanatics.
  210. //
  211. if (ObjectType == ObpSymbolicLinkObjectType) {
  212. ObpCreateSymbolicLinkName( (POBJECT_SYMBOLIC_LINK)InsertObject );
  213. }
  214. }
  215. }
  216. //
  217. // If we are creating a new object, then we need assign security
  218. // to it. A pointer to the captured caller-proposed security
  219. // descriptor is contained in the AccessState structure. The
  220. // SecurityDescriptor field in the object header must point to
  221. // the final security descriptor, or to NULL if no security is
  222. // to be assigned to the object.
  223. //
  224. if (InsertObject == Object) {
  225. //
  226. // Only the following objects have security descriptors:
  227. //
  228. // - Named Objects
  229. // - Unnamed objects whose object-type information explicitly
  230. // indicates a security descriptor is required.
  231. //
  232. if ((ObjectName != NULL) || ObjectType->TypeInfo.SecurityRequired) {
  233. //
  234. // Get the parent's descriptor, if there is one...
  235. //
  236. if ((NameInfo != NULL) && (NameInfo->Directory != NULL)) {
  237. //
  238. // This will allocate a block of memory and copy
  239. // the parent's security descriptor into it, and
  240. // return the pointer to the block.
  241. //
  242. // Call ObReleaseObjectSecurity to free up this
  243. // memory.
  244. //
  245. ObGetObjectSecurity( NameInfo->Directory,
  246. &ParentDescriptor,
  247. &SecurityDescriptorAllocated );
  248. }
  249. else {
  250. SecurityDescriptorAllocated = FALSE;
  251. }
  252. //
  253. // Take the captured security descriptor in the AccessState,
  254. // put it into the proper format, and call the object's
  255. // security method to assign the new security descriptor to
  256. // the new object.
  257. //
  258. Status = ObAssignSecurity( AccessState,
  259. ParentDescriptor,
  260. Object,
  261. ObjectType );
  262. if (ParentDescriptor != NULL) {
  263. ObReleaseObjectSecurity( ParentDescriptor,
  264. SecurityDescriptorAllocated );
  265. } else if (NT_SUCCESS( Status )) {
  266. SeReleaseSecurityDescriptor( ObjectCreateInfo->SecurityDescriptor,
  267. ObjectCreateInfo->ProbeMode,
  268. TRUE );
  269. ObjectCreateInfo->SecurityDescriptor = NULL;
  270. AccessState->SecurityDescriptor = NULL;
  271. }
  272. }
  273. if (!NT_SUCCESS( Status )) {
  274. //
  275. // The attempt to assign the security descriptor to
  276. // the object failed.
  277. //
  278. if (LookupContext.DirectoryLocked) {
  279. //
  280. // If ObpLookupObjectName already inserted the
  281. // object into the directory we have to backup this
  282. //
  283. //
  284. // Capture the object Directory
  285. //
  286. DirObject = NameInfo->Directory;
  287. ObpDeleteDirectoryEntry( &LookupContext );
  288. }
  289. ObpReleaseLookupContext( &LookupContext );
  290. //
  291. // If ObpLookupObjectName inserted the object into the directory
  292. // it added a reference to the object and to its directory
  293. // object. We should remove the extra-references
  294. //
  295. if (DirObject) {
  296. ObDereferenceObject( Object );
  297. ObDereferenceObject( DirObject );
  298. }
  299. //
  300. // The first backout logic used ObpDeleteNameCheck
  301. // which is wrong because the security descriptor for
  302. // the object is not initialized. Actually ObpDeleteNameCheck
  303. // had no effect because the object was removed before from
  304. // the directory
  305. //
  306. ObpDereferenceNameInfo( NameInfo );
  307. ObDereferenceObject( Object );
  308. //
  309. // Free security information if we allocated it
  310. //
  311. if (AccessState == &LocalAccessState) {
  312. SeDeleteAccessState( AccessState );
  313. }
  314. return( Status );
  315. }
  316. }
  317. ReturnStatus = Status;
  318. ObjectHeader->ObjectCreateInfo = NULL;
  319. //
  320. // Create a named handle for the object with a pointer bias
  321. // This call also will unlock the directory lock is necessary
  322. // on return
  323. //
  324. if (ARGUMENT_PRESENT (Handle)) {
  325. Status = ObpCreateHandle( OpenReason,
  326. InsertObject,
  327. NULL,
  328. AccessState,
  329. 1 + ObjectPointerBias,
  330. ObjectCreateInfo->Attributes,
  331. &LookupContext,
  332. PreviousMode,
  333. NewObject,
  334. &NewHandle );
  335. //
  336. // If the insertion failed, the following dereference will cause
  337. // the newly created object to be deallocated.
  338. //
  339. if (!NT_SUCCESS( Status )) {
  340. //
  341. // Make the name reference go away if an error.
  342. //
  343. if (ObjectName != NULL) {
  344. ObpDeleteNameCheck( Object );
  345. }
  346. *Handle = NULL;
  347. ReturnStatus = Status;
  348. } else {
  349. *Handle = NewHandle;
  350. }
  351. ObpDereferenceNameInfo( NameInfo );
  352. ObDereferenceObject( Object );
  353. } else {
  354. BOOLEAN IsNewObject;
  355. //
  356. // Charge the user quota for the object.
  357. //
  358. ObpLockObject( ObjectHeader );
  359. ReturnStatus = ObpChargeQuotaForObject( ObjectHeader, ObjectType, &IsNewObject );
  360. ObpUnlockObject( ObjectHeader );
  361. if (!NT_SUCCESS (ReturnStatus)) {
  362. ObDereferenceObject( Object );
  363. }
  364. //
  365. // N.B. An object cannot be named if no Handle parameter is specified.
  366. // The calls to ObpDereferenceNameInfo and ObpReleaseLookupContext are
  367. // not necessary in this path then.
  368. //
  369. }
  370. ObpFreeObjectCreateInformation( ObjectCreateInfo );
  371. //
  372. // Free security information if we allocated it
  373. //
  374. if (AccessState == &LocalAccessState) {
  375. SeDeleteAccessState( AccessState );
  376. }
  377. return( ReturnStatus );
  378. }