Windows NT 4.0 source code leak
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.

1780 lines
50 KiB

4 years ago
  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. obhandle.c
  5. Abstract:
  6. Object handle routines
  7. Author:
  8. Steve Wood (stevewo) 31-Mar-1989
  9. Revision History:
  10. --*/
  11. #include "obp.h"
  12. //
  13. // Define logical sum of all generic accesses.
  14. //
  15. #define GENERIC_ACCESS (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL)
  16. //
  17. // Define local prototypes
  18. //
  19. NTSTATUS
  20. ObpIncrementHandleDataBase(
  21. IN POBJECT_HEADER ObjectHeader,
  22. IN PEPROCESS Process,
  23. OUT PULONG NewProcessHandleCount
  24. );
  25. #ifdef ALLOC_PRAGMA
  26. #pragma alloc_text(PAGE,NtDuplicateObject)
  27. #pragma alloc_text(PAGE,ObpInsertHandleCount)
  28. #pragma alloc_text(PAGE,ObpIncrementHandleCount)
  29. #pragma alloc_text(PAGE,ObpIncrementUnnamedHandleCount)
  30. #pragma alloc_text(PAGE,ObpDecrementHandleCount)
  31. #pragma alloc_text(PAGE,ObpCreateHandle)
  32. #pragma alloc_text(PAGE,ObpCreateUnnamedHandle)
  33. #pragma alloc_text(PAGE,ObpIncrementHandleDataBase)
  34. #endif
  35. extern KMUTANT ObpInitKillMutant;
  36. #ifdef MPSAFE_HANDLE_COUNT_CHECK
  37. VOID
  38. FASTCALL
  39. ObpIncrPointerCount(
  40. IN POBJECT_HEADER ObjectHeader
  41. )
  42. {
  43. KIRQL OldIrql;
  44. ExAcquireFastLock( &ObpLock, &OldIrql );
  45. ObjectHeader->PointerCount += 1;
  46. ExReleaseFastLock( &ObpLock, OldIrql );
  47. }
  48. VOID
  49. FASTCALL
  50. ObpDecrPointerCount(
  51. IN POBJECT_HEADER ObjectHeader
  52. )
  53. {
  54. KIRQL OldIrql;
  55. ExAcquireFastLock( &ObpLock, &OldIrql );
  56. ObjectHeader->PointerCount -= 1;
  57. ExReleaseFastLock( &ObpLock, OldIrql );
  58. }
  59. BOOLEAN
  60. FASTCALL
  61. ObpDecrPointerCountWithResult(
  62. IN POBJECT_HEADER ObjectHeader
  63. )
  64. {
  65. KIRQL OldIrql;
  66. LONG Result;
  67. ExAcquireFastLock( &ObpLock, &OldIrql );
  68. if (ObjectHeader->PointerCount <= ObjectHeader->HandleCount) {
  69. DbgPrint( "OB: About to over-dereference object %x (ObjectHeader at %x)\n",
  70. ObjectHeader->Object, ObjectHeader
  71. );
  72. DbgBreakPoint();
  73. }
  74. ObjectHeader->PointerCount -= 1;
  75. Result = ObjectHeader->PointerCount;
  76. ExReleaseFastLock( &ObpLock, OldIrql );
  77. return Result == 0;
  78. }
  79. VOID
  80. FASTCALL
  81. ObpIncrHandleCount(
  82. IN POBJECT_HEADER ObjectHeader
  83. )
  84. {
  85. KIRQL OldIrql;
  86. ExAcquireFastLock( &ObpLock, &OldIrql );
  87. ObjectHeader->HandleCount += 1;
  88. ExReleaseFastLock( &ObpLock, OldIrql );
  89. }
  90. BOOLEAN
  91. FASTCALL
  92. ObpDecrHandleCount(
  93. IN POBJECT_HEADER ObjectHeader
  94. )
  95. {
  96. KIRQL OldIrql;
  97. LONG Old;
  98. ExAcquireFastLock( &ObpLock, &OldIrql );
  99. Old = ObjectHeader->HandleCount;
  100. ObjectHeader->HandleCount -= 1;
  101. ExReleaseFastLock( &ObpLock, OldIrql );
  102. return Old == 1;
  103. }
  104. #endif // MPSAFE_HANDLE_COUNT_CHECK
  105. POBJECT_HANDLE_COUNT_ENTRY
  106. ObpInsertHandleCount(
  107. POBJECT_HEADER ObjectHeader
  108. )
  109. {
  110. POBJECT_HEADER_HANDLE_INFO HandleInfo;
  111. POBJECT_HANDLE_COUNT_DATABASE OldHandleCountDataBase;
  112. POBJECT_HANDLE_COUNT_DATABASE NewHandleCountDataBase;
  113. POBJECT_HANDLE_COUNT_ENTRY FreeHandleCountEntry;
  114. ULONG CountEntries;
  115. ULONG OldSize;
  116. ULONG NewSize;
  117. OBJECT_HANDLE_COUNT_DATABASE SingleEntryDataBase;
  118. PAGED_CODE();
  119. HandleInfo = OBJECT_HEADER_TO_HANDLE_INFO(ObjectHeader);
  120. if (HandleInfo == NULL) {
  121. return NULL;
  122. }
  123. if (ObjectHeader->Flags & OB_FLAG_SINGLE_HANDLE_ENTRY) {
  124. SingleEntryDataBase.CountEntries = 1;
  125. SingleEntryDataBase.HandleCountEntries[0] = HandleInfo->SingleEntry;
  126. OldHandleCountDataBase = &SingleEntryDataBase;
  127. OldSize = sizeof( SingleEntryDataBase );
  128. CountEntries = 2;
  129. NewSize = sizeof(OBJECT_HANDLE_COUNT_DATABASE) +
  130. ((CountEntries - 1) * sizeof( OBJECT_HANDLE_COUNT_ENTRY ));
  131. } else {
  132. OldHandleCountDataBase = HandleInfo->HandleCountDataBase;
  133. CountEntries = OldHandleCountDataBase->CountEntries;
  134. OldSize = sizeof(OBJECT_HANDLE_COUNT_DATABASE) +
  135. ((CountEntries - 1) * sizeof( OBJECT_HANDLE_COUNT_ENTRY));
  136. CountEntries += 4;
  137. NewSize = sizeof(OBJECT_HANDLE_COUNT_DATABASE) +
  138. ((CountEntries - 1) * sizeof( OBJECT_HANDLE_COUNT_ENTRY));
  139. }
  140. NewHandleCountDataBase = ExAllocatePoolWithTag(PagedPool, NewSize,'dHbO');
  141. if (NewHandleCountDataBase == NULL) {
  142. return NULL;
  143. }
  144. RtlMoveMemory(NewHandleCountDataBase, OldHandleCountDataBase, OldSize);
  145. if (ObjectHeader->Flags & OB_FLAG_SINGLE_HANDLE_ENTRY) {
  146. ObjectHeader->Flags &= ~OB_FLAG_SINGLE_HANDLE_ENTRY;
  147. } else {
  148. ExFreePool( OldHandleCountDataBase );
  149. }
  150. FreeHandleCountEntry =
  151. (POBJECT_HANDLE_COUNT_ENTRY)((PCHAR)NewHandleCountDataBase + OldSize);
  152. RtlZeroMemory(FreeHandleCountEntry, NewSize - OldSize);
  153. NewHandleCountDataBase->CountEntries = CountEntries;
  154. HandleInfo->HandleCountDataBase = NewHandleCountDataBase;
  155. return FreeHandleCountEntry;
  156. }
  157. NTSTATUS
  158. ObpIncrementHandleDataBase(
  159. IN POBJECT_HEADER ObjectHeader,
  160. IN PEPROCESS Process,
  161. OUT PULONG NewProcessHandleCount
  162. )
  163. /*++
  164. Routine Description:
  165. This function increments the handle count database associated with the
  166. specified object for a specified process.
  167. Arguments:
  168. ObjectHeader - Supplies a pointer to the object.
  169. Process - Supplies a pointer to the process whose handle count is to be
  170. updated.
  171. NewProcessHandleCount - Supplies a pointer to a variable that receives
  172. the new handle count for the process.
  173. Return Value:
  174. NTSTATUS
  175. --*/
  176. {
  177. POBJECT_HEADER_HANDLE_INFO HandleInfo;
  178. POBJECT_HANDLE_COUNT_DATABASE HandleCountDataBase;
  179. POBJECT_HANDLE_COUNT_ENTRY HandleCountEntry;
  180. POBJECT_HANDLE_COUNT_ENTRY FreeHandleCountEntry;
  181. ULONG CountEntries;
  182. ULONG ProcessHandleCount;
  183. PAGED_CODE();
  184. HandleInfo = OBJECT_HEADER_TO_HANDLE_INFO(ObjectHeader);
  185. if (ObjectHeader->Flags & OB_FLAG_SINGLE_HANDLE_ENTRY) {
  186. if (HandleInfo->SingleEntry.HandleCount == 0) {
  187. *NewProcessHandleCount = 1;
  188. HandleInfo->SingleEntry.HandleCount = 1;
  189. HandleInfo->SingleEntry.Process = Process;
  190. return STATUS_SUCCESS;
  191. } else if (HandleInfo->SingleEntry.Process == Process) {
  192. *NewProcessHandleCount = ++HandleInfo->SingleEntry.HandleCount;
  193. return STATUS_SUCCESS;
  194. } else {
  195. FreeHandleCountEntry = ObpInsertHandleCount( ObjectHeader );
  196. if (FreeHandleCountEntry == NULL) {
  197. return STATUS_INSUFFICIENT_RESOURCES;
  198. }
  199. FreeHandleCountEntry->Process = Process;
  200. FreeHandleCountEntry->HandleCount = 1;
  201. *NewProcessHandleCount = 1;
  202. return STATUS_SUCCESS;
  203. }
  204. }
  205. HandleCountDataBase = HandleInfo->HandleCountDataBase;
  206. FreeHandleCountEntry = NULL;
  207. if (HandleCountDataBase != NULL) {
  208. CountEntries = HandleCountDataBase->CountEntries;
  209. HandleCountEntry = &HandleCountDataBase->HandleCountEntries[ 0 ];
  210. while (CountEntries) {
  211. if (HandleCountEntry->Process == Process) {
  212. *NewProcessHandleCount = ++HandleCountEntry->HandleCount;
  213. return STATUS_SUCCESS;
  214. } else if (HandleCountEntry->HandleCount == 0) {
  215. FreeHandleCountEntry = HandleCountEntry;
  216. }
  217. ++HandleCountEntry;
  218. --CountEntries;
  219. }
  220. if (FreeHandleCountEntry == NULL) {
  221. FreeHandleCountEntry = ObpInsertHandleCount( ObjectHeader );
  222. if (FreeHandleCountEntry == NULL) {
  223. return(STATUS_INSUFFICIENT_RESOURCES);
  224. }
  225. }
  226. FreeHandleCountEntry->Process = Process;
  227. FreeHandleCountEntry->HandleCount = 1;
  228. *NewProcessHandleCount = 1;
  229. }
  230. return STATUS_SUCCESS;
  231. }
  232. NTSTATUS
  233. ObpIncrementHandleCount(
  234. OB_OPEN_REASON OpenReason,
  235. PEPROCESS Process,
  236. PVOID Object,
  237. POBJECT_TYPE ObjectType,
  238. PACCESS_STATE AccessState OPTIONAL,
  239. KPROCESSOR_MODE AccessMode,
  240. ULONG Attributes
  241. )
  242. /*++
  243. Routine Description:
  244. Increments the count of number of handles to the given object.
  245. If the object is being opened or created, access validation and
  246. auditing will be performed as appropriate.
  247. Arguments:
  248. OpenReason - Supplies the reason the handle count is being incremented.
  249. Process - Pointer to the process in which the new handle will reside.
  250. ObjectHeader - Supplies the header to the object.
  251. ObjectType - Supplies the type of the object.
  252. AccessState - Optional parameter supplying the current accumulated
  253. security information describing the attempt to access the object.
  254. Attributes -
  255. Return Value:
  256. --*/
  257. {
  258. NTSTATUS Status;
  259. ULONG ProcessHandleCount;
  260. BOOLEAN ExclusiveHandle;
  261. POBJECT_HEADER_CREATOR_INFO CreatorInfo;
  262. POBJECT_HEADER_QUOTA_INFO QuotaInfo;
  263. POBJECT_HEADER ObjectHeader;
  264. BOOLEAN HasPrivilege = FALSE;
  265. PRIVILEGE_SET Privileges;
  266. BOOLEAN NewObject;
  267. PAGED_CODE();
  268. ObpValidateIrql( "ObpIncrementHandleCount" );
  269. ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object );
  270. Status = ObpChargeQuotaForObject( ObjectHeader, ObjectType, &NewObject );
  271. if (!NT_SUCCESS( Status )) {
  272. return Status;
  273. }
  274. ObpEnterObjectTypeMutex( ObjectType );
  275. try {
  276. ExclusiveHandle = FALSE;
  277. if (Attributes & OBJ_EXCLUSIVE) {
  278. if ((Attributes & OBJ_INHERIT) ||
  279. ((ObjectHeader->Flags & OB_FLAG_EXCLUSIVE_OBJECT) == 0)) {
  280. return( Status = STATUS_INVALID_PARAMETER );
  281. }
  282. if (((OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader) == NULL) &&
  283. ObjectHeader->HandleCount != 0
  284. ) ||
  285. ((OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader) != NULL) &&
  286. OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader) != PsGetCurrentProcess()
  287. )
  288. ) {
  289. return( Status = STATUS_ACCESS_DENIED );
  290. }
  291. ExclusiveHandle = TRUE;
  292. }
  293. else
  294. if ((ObjectHeader->Flags & OB_FLAG_EXCLUSIVE_OBJECT) &&
  295. OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader) != NULL) {
  296. return( Status = STATUS_ACCESS_DENIED );
  297. }
  298. //
  299. // If handle count going from zero to one for an existing object that
  300. // maintains a handle count database, but does not have an open procedure
  301. // just a close procedure, then fail the call as they are trying to
  302. // reopen an object by pointer and the close procedure will not know
  303. // that the object has been 'recreated'
  304. //
  305. if (ObjectHeader->HandleCount == 0 &&
  306. !NewObject &&
  307. ObjectType->TypeInfo.MaintainHandleCount &&
  308. ObjectType->TypeInfo.OpenProcedure == NULL &&
  309. ObjectType->TypeInfo.CloseProcedure != NULL
  310. ) {
  311. return( Status = STATUS_UNSUCCESSFUL );
  312. }
  313. if ((OpenReason == ObOpenHandle) ||
  314. ((OpenReason == ObDuplicateHandle) && ARGUMENT_PRESENT(AccessState))) {
  315. //
  316. // Perform Access Validation to see if we can open this
  317. // (already existing) object.
  318. //
  319. if (!ObCheckObjectAccess( Object,
  320. AccessState,
  321. TRUE,
  322. AccessMode,
  323. &Status )) {
  324. return( Status );
  325. }
  326. }
  327. else
  328. if ((OpenReason == ObCreateHandle)) {
  329. //
  330. // We are creating a new instance of this object type.
  331. // A total of three audit messages may be generated:
  332. //
  333. // 1 - Audit the attempt to create an instance of this
  334. // object type.
  335. //
  336. // 2 - Audit the successful creation.
  337. //
  338. // 3 - Audit the allocation of the handle.
  339. //
  340. //
  341. // At this point, the RemainingDesiredAccess field in
  342. // the AccessState may still contain either Generic access
  343. // types, or MAXIMUM_ALLOWED. We will map the generics
  344. // and substitute GenericAll for MAXIMUM_ALLOWED.
  345. //
  346. if ( AccessState->RemainingDesiredAccess & MAXIMUM_ALLOWED ) {
  347. AccessState->RemainingDesiredAccess &= ~MAXIMUM_ALLOWED;
  348. AccessState->RemainingDesiredAccess |= GENERIC_ALL;
  349. }
  350. if ((GENERIC_ACCESS & AccessState->RemainingDesiredAccess) != 0) {
  351. RtlMapGenericMask( &AccessState->RemainingDesiredAccess,
  352. &ObjectType->TypeInfo.GenericMapping
  353. );
  354. }
  355. //
  356. // Since we are creating the object, we can give any access the caller
  357. // wants. The only exception is ACCESS_SYSTEM_SECURITY, which requires
  358. // a privilege.
  359. //
  360. if ( AccessState->RemainingDesiredAccess & ACCESS_SYSTEM_SECURITY ) {
  361. //
  362. // We could use SeSinglePrivilegeCheck here, but it
  363. // captures the subject context again, and we don't
  364. // want to do that in this path for performance reasons.
  365. //
  366. Privileges.PrivilegeCount = 1;
  367. Privileges.Control = PRIVILEGE_SET_ALL_NECESSARY;
  368. Privileges.Privilege[0].Luid = SeSecurityPrivilege;
  369. Privileges.Privilege[0].Attributes = 0;
  370. HasPrivilege = SePrivilegeCheck(
  371. &Privileges,
  372. &AccessState->SubjectSecurityContext,
  373. KeGetPreviousMode()
  374. );
  375. if (!HasPrivilege) {
  376. SePrivilegedServiceAuditAlarm ( NULL,
  377. &AccessState->SubjectSecurityContext,
  378. &Privileges,
  379. FALSE
  380. );
  381. return( Status = STATUS_PRIVILEGE_NOT_HELD );
  382. }
  383. AccessState->RemainingDesiredAccess &= ~ACCESS_SYSTEM_SECURITY;
  384. AccessState->PreviouslyGrantedAccess |= ACCESS_SYSTEM_SECURITY;
  385. (VOID)
  386. SeAppendPrivileges(
  387. AccessState,
  388. &Privileges
  389. );
  390. }
  391. CreatorInfo = OBJECT_HEADER_TO_CREATOR_INFO( ObjectHeader );
  392. if (CreatorInfo != NULL) {
  393. InsertTailList( &ObjectType->TypeList, &CreatorInfo->TypeList );
  394. }
  395. }
  396. if (ExclusiveHandle) {
  397. OBJECT_HEADER_TO_QUOTA_INFO(ObjectHeader)->ExclusiveProcess = Process;
  398. }
  399. ObpIncrHandleCount( ObjectHeader );
  400. ProcessHandleCount = 0;
  401. if (ObjectType->TypeInfo.MaintainHandleCount) {
  402. Status = ObpIncrementHandleDataBase( ObjectHeader,
  403. Process,
  404. &ProcessHandleCount );
  405. if (!NT_SUCCESS(Status)) {
  406. leave;
  407. }
  408. }
  409. if (ObjectType->TypeInfo.OpenProcedure != NULL) {
  410. KIRQL SaveIrql;
  411. ObpBeginTypeSpecificCallOut( SaveIrql );
  412. (*ObjectType->TypeInfo.OpenProcedure)( OpenReason,
  413. Process,
  414. Object,
  415. AccessState ?
  416. AccessState->PreviouslyGrantedAccess :
  417. 0,
  418. ProcessHandleCount
  419. );
  420. ObpEndTypeSpecificCallOut( SaveIrql, "Open", ObjectType, Object );
  421. }
  422. ObjectType->TotalNumberOfHandles += 1;
  423. if (ObjectType->TotalNumberOfHandles > ObjectType->HighWaterNumberOfHandles) {
  424. ObjectType->HighWaterNumberOfHandles = ObjectType->TotalNumberOfHandles;
  425. }
  426. Status = STATUS_SUCCESS;
  427. }
  428. finally {
  429. ObpLeaveObjectTypeMutex( ObjectType );
  430. }
  431. return( Status );
  432. }
  433. NTSTATUS
  434. ObpIncrementUnnamedHandleCount(
  435. PACCESS_MASK DesiredAccess,
  436. PEPROCESS Process,
  437. PVOID Object,
  438. POBJECT_TYPE ObjectType,
  439. KPROCESSOR_MODE AccessMode,
  440. ULONG Attributes
  441. )
  442. /*++
  443. Routine Description:
  444. Increments the count of number of handles to the given object.
  445. Arguments:
  446. OpenReason - Supplies the reason the handle count is being incremented.
  447. Process - Pointer to the process in which the new handle will reside.
  448. ObjectHeader - Supplies the header to the object.
  449. ObjectType - Supplies the type of the object.
  450. Attributes -
  451. Return Value:
  452. --*/
  453. {
  454. NTSTATUS Status;
  455. BOOLEAN ExclusiveHandle;
  456. POBJECT_HEADER_CREATOR_INFO CreatorInfo;
  457. POBJECT_HEADER_QUOTA_INFO QuotaInfo;
  458. POBJECT_HEADER ObjectHeader;
  459. BOOLEAN NewObject;
  460. ULONG ProcessHandleCount;
  461. PAGED_CODE();
  462. ObpValidateIrql( "ObpIncrementUnnamedHandleCount" );
  463. ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object );
  464. Status = ObpChargeQuotaForObject( ObjectHeader, ObjectType, &NewObject );
  465. if (!NT_SUCCESS( Status )) {
  466. return Status;
  467. }
  468. ObpEnterObjectTypeMutex( ObjectType );
  469. try {
  470. ExclusiveHandle = FALSE;
  471. if (Attributes & OBJ_EXCLUSIVE) {
  472. if ((Attributes & OBJ_INHERIT) ||
  473. ((ObjectHeader->Flags & OB_FLAG_EXCLUSIVE_OBJECT) == 0)) {
  474. return( Status = STATUS_INVALID_PARAMETER );
  475. }
  476. if (((OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader) == NULL) &&
  477. ObjectHeader->HandleCount != 0
  478. ) ||
  479. ((OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader) != NULL) &&
  480. OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader) != PsGetCurrentProcess()
  481. )
  482. ) {
  483. return( Status = STATUS_ACCESS_DENIED );
  484. }
  485. ExclusiveHandle = TRUE;
  486. }
  487. else
  488. if ((ObjectHeader->Flags & OB_FLAG_EXCLUSIVE_OBJECT) &&
  489. OBJECT_HEADER_TO_EXCLUSIVE_PROCESS(ObjectHeader) != NULL) {
  490. return( Status = STATUS_ACCESS_DENIED );
  491. }
  492. //
  493. // If handle count going from zero to one for an existing object that
  494. // maintains a handle count database, but does not have an open procedure
  495. // just a close procedure, then fail the call as they are trying to
  496. // reopen an object by pointer and the close procedure will not know
  497. // that the object has been 'recreated'
  498. //
  499. if (ObjectHeader->HandleCount == 0 &&
  500. !NewObject &&
  501. ObjectType->TypeInfo.MaintainHandleCount &&
  502. ObjectType->TypeInfo.OpenProcedure == NULL &&
  503. ObjectType->TypeInfo.CloseProcedure != NULL
  504. ) {
  505. Status = STATUS_UNSUCCESSFUL;
  506. leave;
  507. }
  508. if ( *DesiredAccess & MAXIMUM_ALLOWED ) {
  509. *DesiredAccess &= ~MAXIMUM_ALLOWED;
  510. *DesiredAccess |= GENERIC_ALL;
  511. }
  512. if ((GENERIC_ACCESS & *DesiredAccess) != 0) {
  513. RtlMapGenericMask( DesiredAccess,
  514. &ObjectType->TypeInfo.GenericMapping
  515. );
  516. }
  517. CreatorInfo = OBJECT_HEADER_TO_CREATOR_INFO( ObjectHeader );
  518. if (CreatorInfo != NULL) {
  519. InsertTailList( &ObjectType->TypeList, &CreatorInfo->TypeList );
  520. }
  521. if (ExclusiveHandle) {
  522. OBJECT_HEADER_TO_QUOTA_INFO(ObjectHeader)->ExclusiveProcess = Process;
  523. }
  524. ObpIncrHandleCount( ObjectHeader );
  525. ProcessHandleCount = 0;
  526. if (ObjectType->TypeInfo.MaintainHandleCount) {
  527. Status = ObpIncrementHandleDataBase( ObjectHeader,
  528. Process,
  529. &ProcessHandleCount );
  530. if (!NT_SUCCESS(Status)) {
  531. leave;
  532. }
  533. }
  534. if (ObjectType->TypeInfo.OpenProcedure != NULL) {
  535. KIRQL SaveIrql;
  536. ObpBeginTypeSpecificCallOut( SaveIrql );
  537. (*ObjectType->TypeInfo.OpenProcedure)( ObCreateHandle,
  538. Process,
  539. Object,
  540. *DesiredAccess,
  541. ProcessHandleCount
  542. );
  543. ObpEndTypeSpecificCallOut( SaveIrql, "Open", ObjectType, Object );
  544. }
  545. ObjectType->TotalNumberOfHandles += 1;
  546. if (ObjectType->TotalNumberOfHandles > ObjectType->HighWaterNumberOfHandles) {
  547. ObjectType->HighWaterNumberOfHandles = ObjectType->TotalNumberOfHandles;
  548. }
  549. Status = STATUS_SUCCESS;
  550. }
  551. finally {
  552. ObpLeaveObjectTypeMutex( ObjectType );
  553. }
  554. return( Status );
  555. }
  556. NTSTATUS
  557. ObpChargeQuotaForObject(
  558. IN POBJECT_HEADER ObjectHeader,
  559. IN POBJECT_TYPE ObjectType,
  560. OUT PBOOLEAN NewObject
  561. )
  562. {
  563. POBJECT_HEADER_QUOTA_INFO QuotaInfo;
  564. ULONG NonPagedPoolCharge;
  565. ULONG PagedPoolCharge;
  566. QuotaInfo = OBJECT_HEADER_TO_QUOTA_INFO( ObjectHeader );
  567. *NewObject = FALSE;
  568. if (ObjectHeader->Flags & OB_FLAG_NEW_OBJECT) {
  569. ObjectHeader->Flags &= ~OB_FLAG_NEW_OBJECT;
  570. if (QuotaInfo != NULL) {
  571. PagedPoolCharge = QuotaInfo->PagedPoolCharge +
  572. QuotaInfo->SecurityDescriptorCharge;
  573. NonPagedPoolCharge = QuotaInfo->NonPagedPoolCharge;
  574. }
  575. else {
  576. PagedPoolCharge = ObjectType->TypeInfo.DefaultPagedPoolCharge;
  577. if (ObjectHeader->SecurityDescriptor != NULL) {
  578. ObjectHeader->Flags |= OB_FLAG_DEFAULT_SECURITY_QUOTA;
  579. PagedPoolCharge += SE_DEFAULT_SECURITY_QUOTA;
  580. }
  581. NonPagedPoolCharge = ObjectType->TypeInfo.DefaultNonPagedPoolCharge;
  582. }
  583. ObjectHeader->QuotaBlockCharged = (PVOID)PsChargeSharedPoolQuota( PsGetCurrentProcess(),
  584. PagedPoolCharge,
  585. NonPagedPoolCharge
  586. );
  587. if (ObjectHeader->QuotaBlockCharged == NULL) {
  588. return STATUS_QUOTA_EXCEEDED;
  589. }
  590. *NewObject = TRUE;
  591. }
  592. return STATUS_SUCCESS;
  593. }
  594. VOID
  595. ObpDecrementHandleCount(
  596. PEPROCESS Process,
  597. POBJECT_HEADER ObjectHeader,
  598. POBJECT_TYPE ObjectType,
  599. ACCESS_MASK GrantedAccess
  600. )
  601. {
  602. POBJECT_HEADER_HANDLE_INFO HandleInfo;
  603. POBJECT_HANDLE_COUNT_DATABASE HandleCountDataBase;
  604. POBJECT_HANDLE_COUNT_ENTRY HandleCountEntry;
  605. PVOID Object;
  606. ULONG CountEntries;
  607. ULONG ProcessHandleCount;
  608. ULONG SystemHandleCount;
  609. PAGED_CODE();
  610. ObpEnterObjectTypeMutex( ObjectType );
  611. Object = (PVOID)&ObjectHeader->Body;
  612. SystemHandleCount = ObjectHeader->HandleCount;
  613. ProcessHandleCount = 0;
  614. if (ObpDecrHandleCount( ObjectHeader ) &&
  615. (ObjectHeader->Flags & OB_FLAG_EXCLUSIVE_OBJECT)) {
  616. OBJECT_HEADER_TO_QUOTA_INFO( ObjectHeader )->ExclusiveProcess = NULL;
  617. }
  618. if (ObjectType->TypeInfo.MaintainHandleCount) {
  619. HandleInfo = OBJECT_HEADER_TO_HANDLE_INFO( ObjectHeader );
  620. if (ObjectHeader->Flags & OB_FLAG_SINGLE_HANDLE_ENTRY) {
  621. ASSERT(HandleInfo->SingleEntry.Process == Process);
  622. ASSERT(HandleInfo->SingleEntry.HandleCount > 0);
  623. ProcessHandleCount = HandleInfo->SingleEntry.HandleCount--;
  624. HandleCountEntry = &HandleInfo->SingleEntry;
  625. }
  626. else {
  627. HandleCountDataBase = HandleInfo->HandleCountDataBase;
  628. if (HandleCountDataBase != NULL) {
  629. CountEntries = HandleCountDataBase->CountEntries;
  630. HandleCountEntry = &HandleCountDataBase->HandleCountEntries[ 0 ];
  631. while (CountEntries) {
  632. if (HandleCountEntry->HandleCount != 0 &&
  633. HandleCountEntry->Process == Process
  634. ) {
  635. ProcessHandleCount = HandleCountEntry->HandleCount--;
  636. break;
  637. }
  638. HandleCountEntry++;
  639. CountEntries--;
  640. }
  641. }
  642. }
  643. if (ProcessHandleCount == 1) {
  644. HandleCountEntry->Process = NULL;
  645. HandleCountEntry->HandleCount = 0;
  646. }
  647. }
  648. //
  649. // If the Object Type has a Close Procedure, then release the type
  650. // mutex before calling it, and then call ObpDeleteNameCheck without
  651. // the mutex held.
  652. //
  653. if (ObjectType->TypeInfo.CloseProcedure) {
  654. KIRQL SaveIrql;
  655. ObpLeaveObjectTypeMutex( ObjectType );
  656. ObpBeginTypeSpecificCallOut( SaveIrql );
  657. (*ObjectType->TypeInfo.CloseProcedure)( Process,
  658. Object,
  659. GrantedAccess,
  660. ProcessHandleCount,
  661. SystemHandleCount
  662. );
  663. ObpEndTypeSpecificCallOut( SaveIrql, "Close", ObjectType, Object );
  664. ObpDeleteNameCheck( Object, FALSE );
  665. }
  666. //
  667. // If there is no Close Procedure, then just call ObpDeleteNameCheck
  668. // with the mutex held.
  669. //
  670. else {
  671. //
  672. // The following call will release the type mutex
  673. //
  674. ObpDeleteNameCheck( Object, TRUE );
  675. }
  676. ObjectType->TotalNumberOfHandles -= 1;
  677. }
  678. NTSTATUS
  679. ObpCreateHandle(
  680. IN OB_OPEN_REASON OpenReason,
  681. IN PVOID Object,
  682. IN POBJECT_TYPE ExpectedObjectType OPTIONAL,
  683. IN PACCESS_STATE AccessState,
  684. IN ULONG ObjectPointerBias OPTIONAL,
  685. IN ULONG Attributes,
  686. IN BOOLEAN DirectoryLocked,
  687. IN KPROCESSOR_MODE AccessMode,
  688. OUT PVOID *ReferencedNewObject OPTIONAL,
  689. OUT PHANDLE Handle
  690. )
  691. /*++
  692. Routine Description:
  693. description-of-function.
  694. Arguments:
  695. OpenReason -
  696. Object -
  697. ExpectedObjectType -
  698. AccessState -
  699. ObjectPointerBias -
  700. Attributes -
  701. DirectoryLocked -
  702. AccessMode -
  703. ReferencedNewObject -
  704. Handle -
  705. Return Value:
  706. return-value - Description of conditions needed to return value. - or -
  707. None.
  708. --*/
  709. {
  710. NTSTATUS Status;
  711. POBJECT_HEADER ObjectHeader;
  712. POBJECT_TYPE ObjectType;
  713. PVOID ObjectTable;
  714. OBJECT_TABLE_ENTRY ObjectTableEntry;
  715. HANDLE NewHandle;
  716. ACCESS_MASK DesiredAccess;
  717. ACCESS_MASK GrantedAccess;
  718. ULONG BiasCount;
  719. PAGED_CODE();
  720. ObpValidateIrql( "ObpCreateHandle" );
  721. DesiredAccess = AccessState->RemainingDesiredAccess |
  722. AccessState->PreviouslyGrantedAccess;
  723. ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object );
  724. ObjectType = ObjectHeader->Type;
  725. if (ARGUMENT_PRESENT( ExpectedObjectType ) &&
  726. ObjectType != ExpectedObjectType
  727. ) {
  728. if (DirectoryLocked) {
  729. ObpLeaveRootDirectoryMutex();
  730. }
  731. return( STATUS_OBJECT_TYPE_MISMATCH );
  732. }
  733. ObjectTableEntry.ObjectHeader = ObjectHeader;
  734. ObjectTable = ObpGetObjectTable();
  735. //
  736. // ObpIncrementHandleCount will perform access checking on the
  737. // object being opened as appropriate.
  738. //
  739. Status = ObpIncrementHandleCount( OpenReason,
  740. PsGetCurrentProcess(),
  741. Object,
  742. ObjectType,
  743. AccessState,
  744. AccessMode,
  745. Attributes
  746. );
  747. if (AccessState->GenerateOnClose) {
  748. Attributes |= OBJ_AUDIT_OBJECT_CLOSE;
  749. }
  750. ObjectTableEntry.Attributes |= (Attributes & OBJ_HANDLE_ATTRIBUTES);
  751. DesiredAccess = AccessState->RemainingDesiredAccess |
  752. AccessState->PreviouslyGrantedAccess;
  753. GrantedAccess = DesiredAccess &
  754. (ObjectType->TypeInfo.ValidAccessMask |
  755. ACCESS_SYSTEM_SECURITY );
  756. if (DirectoryLocked) {
  757. ObpLeaveRootDirectoryMutex();
  758. }
  759. if (!NT_SUCCESS( Status )) {
  760. return( Status );
  761. }
  762. if (ARGUMENT_PRESENT( ObjectPointerBias )) {
  763. BiasCount = ObjectPointerBias;
  764. while (BiasCount--) {
  765. ObpIncrPointerCount( ObjectHeader );
  766. }
  767. }
  768. #if i386 && !FPO
  769. if (NtGlobalFlag & FLG_KERNEL_STACK_TRACE_DB) {
  770. ObjectTableEntry.GrantedAccessIndex = ObpComputeGrantedAccessIndex( GrantedAccess );
  771. ObjectTableEntry.CreatorBackTraceIndex = RtlLogStackBackTrace();
  772. }
  773. else
  774. #endif // i386 && !FPO
  775. ObjectTableEntry.GrantedAccess = GrantedAccess;
  776. NewHandle = ExCreateHandle( ObjectTable, (PHANDLE_ENTRY)&ObjectTableEntry );
  777. if (NewHandle == NULL) {
  778. if (ARGUMENT_PRESENT( ObjectPointerBias )) {
  779. BiasCount = ObjectPointerBias;
  780. while (BiasCount--) {
  781. ObpDecrPointerCount( ObjectHeader );
  782. }
  783. }
  784. ObpDecrementHandleCount( PsGetCurrentProcess(),
  785. ObjectHeader,
  786. ObjectType,
  787. GrantedAccess
  788. );
  789. return( STATUS_INSUFFICIENT_RESOURCES );
  790. }
  791. *Handle = MAKE_OBJECT_HANDLE( NewHandle );
  792. //
  793. // If requested, generate audit messages to indicate that a new handle
  794. // has been allocated.
  795. //
  796. // This is the final security operation in the creation/opening of the
  797. // object.
  798. //
  799. if ( AccessState->GenerateAudit ) {
  800. SeAuditHandleCreation(
  801. AccessState,
  802. *Handle
  803. );
  804. }
  805. if (OpenReason == ObCreateHandle) {
  806. PAUX_ACCESS_DATA AuxData = AccessState->AuxData;
  807. if ( ( AuxData->PrivilegesUsed != NULL) && (AuxData->PrivilegesUsed->PrivilegeCount > 0) ) {
  808. SePrivilegeObjectAuditAlarm(
  809. *Handle,
  810. &AccessState->SubjectSecurityContext,
  811. GrantedAccess,
  812. AuxData->PrivilegesUsed,
  813. TRUE,
  814. KeGetPreviousMode()
  815. );
  816. }
  817. }
  818. if (ARGUMENT_PRESENT( ObjectPointerBias ) &&
  819. ARGUMENT_PRESENT( ReferencedNewObject )
  820. ) {
  821. *ReferencedNewObject = Object;
  822. }
  823. return( STATUS_SUCCESS );
  824. }
  825. NTSTATUS
  826. ObpCreateUnnamedHandle(
  827. IN PVOID Object,
  828. IN ACCESS_MASK DesiredAccess,
  829. IN ULONG ObjectPointerBias OPTIONAL,
  830. IN ULONG Attributes,
  831. IN KPROCESSOR_MODE AccessMode,
  832. OUT PVOID *ReferencedNewObject OPTIONAL,
  833. OUT PHANDLE Handle
  834. )
  835. /*++
  836. Routine Description:
  837. description-of-function.
  838. Arguments:
  839. OpenReason -
  840. Object -
  841. ExpectedObjectType -
  842. AccessState -
  843. ObjectPointerBias -
  844. Attributes -
  845. DirectoryLocked -
  846. AccessMode -
  847. ReferencedNewObject -
  848. Handle -
  849. Return Value:
  850. return-value - Description of conditions needed to return value. - or -
  851. None.
  852. --*/
  853. {
  854. NTSTATUS Status;
  855. POBJECT_HEADER ObjectHeader;
  856. POBJECT_TYPE ObjectType;
  857. PVOID ObjectTable;
  858. OBJECT_TABLE_ENTRY ObjectTableEntry;
  859. HANDLE NewHandle;
  860. ULONG BiasCount;
  861. ACCESS_MASK GrantedAccess;
  862. PAGED_CODE();
  863. ObpValidateIrql( "ObpCreateUnnamedHandle" );
  864. ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object );
  865. ObjectType = ObjectHeader->Type;
  866. ObjectTableEntry.ObjectHeader = ObjectHeader;
  867. ObjectTableEntry.Attributes |= (Attributes & OBJ_HANDLE_ATTRIBUTES);
  868. ObjectTable = ObpGetObjectTable();
  869. Status = ObpIncrementUnnamedHandleCount( &DesiredAccess,
  870. PsGetCurrentProcess(),
  871. Object,
  872. ObjectType,
  873. AccessMode,
  874. Attributes
  875. );
  876. GrantedAccess = DesiredAccess &
  877. (ObjectType->TypeInfo.ValidAccessMask |
  878. ACCESS_SYSTEM_SECURITY );
  879. if (!NT_SUCCESS( Status )) {
  880. return( Status );
  881. }
  882. if (ARGUMENT_PRESENT( ObjectPointerBias )) {
  883. BiasCount = ObjectPointerBias;
  884. while (BiasCount--) {
  885. ObpIncrPointerCount( ObjectHeader );
  886. }
  887. }
  888. #if i386 && !FPO
  889. if (NtGlobalFlag & FLG_KERNEL_STACK_TRACE_DB) {
  890. ObjectTableEntry.GrantedAccessIndex = ObpComputeGrantedAccessIndex( GrantedAccess );
  891. ObjectTableEntry.CreatorBackTraceIndex = RtlLogStackBackTrace();
  892. }
  893. else
  894. #endif // i386 && !FPO
  895. ObjectTableEntry.GrantedAccess = GrantedAccess;
  896. NewHandle = ExCreateHandle( ObjectTable, (PHANDLE_ENTRY)&ObjectTableEntry );
  897. if (NewHandle == NULL) {
  898. if (ARGUMENT_PRESENT( ObjectPointerBias )) {
  899. BiasCount = ObjectPointerBias;
  900. while (BiasCount--) {
  901. ObpDecrPointerCount( ObjectHeader );
  902. }
  903. }
  904. ObpDecrementHandleCount( PsGetCurrentProcess(),
  905. ObjectHeader,
  906. ObjectType,
  907. GrantedAccess
  908. );
  909. return( STATUS_INSUFFICIENT_RESOURCES );
  910. }
  911. *Handle = MAKE_OBJECT_HANDLE( NewHandle );
  912. if (ARGUMENT_PRESENT( ObjectPointerBias ) &&
  913. ARGUMENT_PRESENT( ReferencedNewObject )
  914. ) {
  915. *ReferencedNewObject = Object;
  916. }
  917. return( STATUS_SUCCESS );
  918. }
  919. NTSTATUS
  920. NtDuplicateObject(
  921. IN HANDLE SourceProcessHandle,
  922. IN HANDLE SourceHandle,
  923. IN HANDLE TargetProcessHandle OPTIONAL,
  924. OUT PHANDLE TargetHandle OPTIONAL,
  925. IN ACCESS_MASK DesiredAccess,
  926. IN ULONG HandleAttributes,
  927. IN ULONG Options
  928. )
  929. /*++
  930. Routine Description:
  931. This function creates a handle that is a duplicate of the specified
  932. source handle. The source handle is evaluated in the context of the
  933. specified source process. The calling process must have
  934. PROCESS_DUP_HANDLE access to the source process. The duplicate
  935. handle is created with the specified attributes and desired access.
  936. The duplicate handle is created in the handle table of the specified
  937. target process. The calling process must have PROCESS_DUP_HANDLE
  938. access to the target process.
  939. Arguments:
  940. SourceProcessHandle -
  941. SourceHandle -
  942. TargetProcessHandle -
  943. TargetHandle -
  944. DesiredAccess -
  945. HandleAttributes -
  946. Return Value:
  947. TBS
  948. --*/
  949. {
  950. KPROCESSOR_MODE PreviousMode;
  951. NTSTATUS Status;
  952. PVOID SourceObject;
  953. POBJECT_HEADER ObjectHeader;
  954. POBJECT_TYPE ObjectType;
  955. PEPROCESS SourceProcess;
  956. PEPROCESS TargetProcess;
  957. BOOLEAN Attached;
  958. PVOID ObjectTable;
  959. OBJECT_TABLE_ENTRY ObjectTableEntry;
  960. OBJECT_HANDLE_INFORMATION HandleInformation;
  961. HANDLE NewHandle;
  962. ACCESS_STATE AccessState;
  963. AUX_ACCESS_DATA AuxData;
  964. ACCESS_MASK SourceAccess;
  965. ACCESS_MASK TargetAccess;
  966. PACCESS_STATE PassedAccessState = NULL;
  967. //
  968. // Get previous processor mode and probe output arguments if necessary.
  969. //
  970. PreviousMode = KeGetPreviousMode();
  971. if (ARGUMENT_PRESENT( TargetHandle ) && PreviousMode != KernelMode) {
  972. try {
  973. ProbeForWriteHandle( TargetHandle );
  974. }
  975. except( EXCEPTION_EXECUTE_HANDLER ) {
  976. return( GetExceptionCode() );
  977. }
  978. }
  979. if (!(Options & DUPLICATE_SAME_ACCESS)) {
  980. Status = ObpValidateDesiredAccess( DesiredAccess );
  981. if (!NT_SUCCESS( Status )) {
  982. return( Status );
  983. }
  984. }
  985. Attached = FALSE;
  986. Status = ObReferenceObjectByHandle( SourceProcessHandle,
  987. PROCESS_DUP_HANDLE,
  988. PsProcessType,
  989. PreviousMode,
  990. (PVOID *)&SourceProcess,
  991. NULL
  992. );
  993. if (!NT_SUCCESS( Status )) {
  994. return Status;
  995. }
  996. KeEnterCriticalRegion();
  997. KeWaitForSingleObject( &ObpInitKillMutant,
  998. Executive,
  999. KernelMode,
  1000. FALSE,
  1001. NULL
  1002. );
  1003. //
  1004. // Make sure the source process has an object table still
  1005. //
  1006. if ( SourceProcess->ObjectTable == NULL ) {
  1007. KeReleaseMutant( &ObpInitKillMutant, 0, FALSE, FALSE );
  1008. KeLeaveCriticalRegion();
  1009. ObDereferenceObject( SourceProcess );
  1010. return STATUS_PROCESS_IS_TERMINATING;
  1011. }
  1012. //
  1013. // If the specified source process is not the current process, attach
  1014. // to the specified source process.
  1015. //
  1016. if (PsGetCurrentProcess() != SourceProcess) {
  1017. KeAttachProcess( &SourceProcess->Pcb );
  1018. Attached = TRUE;
  1019. }
  1020. Status = ObReferenceObjectByHandle( SourceHandle,
  1021. 0,
  1022. (POBJECT_TYPE)NULL,
  1023. PreviousMode,
  1024. &SourceObject,
  1025. &HandleInformation
  1026. );
  1027. if (Attached) {
  1028. KeDetachProcess();
  1029. Attached = FALSE;
  1030. }
  1031. if (!NT_SUCCESS( Status )) {
  1032. KeReleaseMutant( &ObpInitKillMutant, 0, FALSE, FALSE );
  1033. KeLeaveCriticalRegion();
  1034. ObDereferenceObject( SourceProcess );
  1035. return( Status );
  1036. }
  1037. //
  1038. // All done if no target process handle specified.
  1039. //
  1040. if (!ARGUMENT_PRESENT( TargetProcessHandle )) {
  1041. //
  1042. // If no TargetProcessHandle, then only possible option is to close
  1043. // the source handle in the context of the source process.
  1044. //
  1045. if (!(Options & DUPLICATE_CLOSE_SOURCE)) {
  1046. Status = STATUS_INVALID_PARAMETER;
  1047. }
  1048. if (Options & DUPLICATE_CLOSE_SOURCE) {
  1049. KeAttachProcess( &SourceProcess->Pcb );
  1050. NtClose( SourceHandle );
  1051. KeDetachProcess();
  1052. }
  1053. KeReleaseMutant( &ObpInitKillMutant, 0, FALSE, FALSE );
  1054. KeLeaveCriticalRegion();
  1055. ObDereferenceObject( SourceObject );
  1056. ObDereferenceObject( SourceProcess );
  1057. return( Status );
  1058. }
  1059. SourceAccess = HandleInformation.GrantedAccess;
  1060. Status = ObReferenceObjectByHandle( TargetProcessHandle,
  1061. PROCESS_DUP_HANDLE,
  1062. PsProcessType,
  1063. PreviousMode,
  1064. (PVOID *)&TargetProcess,
  1065. NULL
  1066. );
  1067. if (!NT_SUCCESS( Status )) {
  1068. if (Options & DUPLICATE_CLOSE_SOURCE) {
  1069. KeAttachProcess( &SourceProcess->Pcb );
  1070. NtClose( SourceHandle );
  1071. KeDetachProcess();
  1072. }
  1073. KeReleaseMutant( &ObpInitKillMutant, 0, FALSE, FALSE );
  1074. KeLeaveCriticalRegion();
  1075. ObDereferenceObject( SourceObject );
  1076. ObDereferenceObject( SourceProcess );
  1077. return( Status );
  1078. }
  1079. //
  1080. // Make sure the target process has not exited
  1081. //
  1082. if ( TargetProcess->ObjectTable == NULL ) {
  1083. if (Options & DUPLICATE_CLOSE_SOURCE) {
  1084. KeAttachProcess( &SourceProcess->Pcb );
  1085. NtClose( SourceHandle );
  1086. KeDetachProcess();
  1087. }
  1088. KeReleaseMutant( &ObpInitKillMutant, 0, FALSE, FALSE );
  1089. KeLeaveCriticalRegion();
  1090. ObDereferenceObject( SourceObject );
  1091. ObDereferenceObject( SourceProcess );
  1092. ObDereferenceObject( TargetProcess );
  1093. return STATUS_PROCESS_IS_TERMINATING;
  1094. }
  1095. //
  1096. // If the specified target process is not the current process, attach
  1097. // to the specified target process.
  1098. //
  1099. if (PsGetCurrentProcess() != TargetProcess) {
  1100. KeAttachProcess( &TargetProcess->Pcb );
  1101. Attached = TRUE;
  1102. }
  1103. if (Options & DUPLICATE_SAME_ACCESS) {
  1104. DesiredAccess = SourceAccess;
  1105. }
  1106. if (Options & DUPLICATE_SAME_ATTRIBUTES) {
  1107. HandleAttributes = HandleInformation.HandleAttributes;
  1108. }
  1109. else {
  1110. //
  1111. // Always propogate auditing information.
  1112. //
  1113. HandleAttributes |= HandleInformation.HandleAttributes & OBJ_AUDIT_OBJECT_CLOSE;
  1114. }
  1115. ObjectHeader = OBJECT_TO_OBJECT_HEADER( SourceObject );
  1116. ObjectType = ObjectHeader->Type;
  1117. ObjectTableEntry.ObjectHeader = ObjectHeader;
  1118. ObjectTableEntry.Attributes |= (HandleAttributes & OBJ_HANDLE_ATTRIBUTES);
  1119. if ((DesiredAccess & GENERIC_ACCESS) != 0) {
  1120. RtlMapGenericMask( &DesiredAccess,
  1121. &ObjectType->TypeInfo.GenericMapping
  1122. );
  1123. }
  1124. //
  1125. // Make sure to preserve ACCESS_SYSTEM_SECURITY, which most likely is not
  1126. // found in the ValidAccessMask
  1127. //
  1128. TargetAccess = DesiredAccess &
  1129. (ObjectType->TypeInfo.ValidAccessMask |
  1130. ACCESS_SYSTEM_SECURITY);
  1131. //
  1132. // If the access requested for the target is a superset of the
  1133. // access allowed in the source, perform full AVR. If it is a
  1134. // subset or equal, do not perform any access validation.
  1135. //
  1136. // Do not allow superset access if object type has a private security
  1137. // method, as there is no means to call them in this case to do the
  1138. // access check.
  1139. //
  1140. // If the AccessState is not passed to ObpIncrementHandleCount
  1141. // there will be no AVR.
  1142. //
  1143. if (TargetAccess & ~SourceAccess) {
  1144. if (ObjectType->TypeInfo.SecurityProcedure == SeDefaultObjectMethod) {
  1145. Status = SeCreateAccessState(
  1146. &AccessState,
  1147. &AuxData,
  1148. TargetAccess, // DesiredAccess
  1149. &ObjectType->TypeInfo.GenericMapping
  1150. );
  1151. PassedAccessState = &AccessState;
  1152. }
  1153. else {
  1154. Status = STATUS_ACCESS_DENIED;
  1155. }
  1156. }
  1157. else {
  1158. //
  1159. // Do not perform AVR
  1160. //
  1161. PassedAccessState = NULL;
  1162. Status = STATUS_SUCCESS;
  1163. }
  1164. if ( NT_SUCCESS( Status )) {
  1165. Status = ObpIncrementHandleCount( ObDuplicateHandle,
  1166. PsGetCurrentProcess(),
  1167. SourceObject,
  1168. ObjectType,
  1169. PassedAccessState,
  1170. PreviousMode,
  1171. HandleAttributes
  1172. );
  1173. ObjectTable = ObpGetObjectTable();
  1174. ASSERT(ObjectTable);
  1175. }
  1176. if (Attached) {
  1177. KeDetachProcess();
  1178. Attached = FALSE;
  1179. }
  1180. if (Options & DUPLICATE_CLOSE_SOURCE) {
  1181. KeAttachProcess( &SourceProcess->Pcb );
  1182. NtClose( SourceHandle );
  1183. KeDetachProcess();
  1184. }
  1185. if (!NT_SUCCESS( Status )) {
  1186. if (PassedAccessState != NULL) {
  1187. SeDeleteAccessState( PassedAccessState );
  1188. }
  1189. KeReleaseMutant( &ObpInitKillMutant, 0, FALSE, FALSE );
  1190. KeLeaveCriticalRegion();
  1191. ObDereferenceObject( SourceObject );
  1192. ObDereferenceObject( SourceProcess );
  1193. ObDereferenceObject( TargetProcess );
  1194. return( Status );
  1195. }
  1196. if (PassedAccessState != NULL && PassedAccessState->GenerateOnClose == TRUE) {
  1197. //
  1198. // If we performed AVR opening the handle, then mark the handle as needing
  1199. // auditing when it's closed.
  1200. //
  1201. ObjectTableEntry.Attributes |= OBJ_AUDIT_OBJECT_CLOSE;
  1202. }
  1203. #if i386 && !FPO
  1204. if (NtGlobalFlag & FLG_KERNEL_STACK_TRACE_DB) {
  1205. ObjectTableEntry.GrantedAccessIndex = ObpComputeGrantedAccessIndex( TargetAccess );
  1206. ObjectTableEntry.CreatorBackTraceIndex = RtlLogStackBackTrace();
  1207. }
  1208. else
  1209. #endif // i386 && !FPO
  1210. ObjectTableEntry.GrantedAccess = TargetAccess;
  1211. NewHandle = ExCreateHandle( ObjectTable, (PHANDLE_ENTRY)&ObjectTableEntry );
  1212. if (NewHandle) {
  1213. //
  1214. // Audit the creation of the new handle if AVR was done.
  1215. //
  1216. if (PassedAccessState != NULL) {
  1217. SeAuditHandleCreation( PassedAccessState, MAKE_OBJECT_HANDLE( NewHandle ));
  1218. }
  1219. if (SeDetailedAuditing && (ObjectTableEntry.Attributes & OBJ_AUDIT_OBJECT_CLOSE)) {
  1220. SeAuditHandleDuplication(
  1221. SourceHandle,
  1222. MAKE_OBJECT_HANDLE( NewHandle ),
  1223. SourceProcess,
  1224. TargetProcess
  1225. );
  1226. }
  1227. if (ARGUMENT_PRESENT( TargetHandle )) {
  1228. try {
  1229. *TargetHandle = MAKE_OBJECT_HANDLE( NewHandle );
  1230. }
  1231. except( EXCEPTION_EXECUTE_HANDLER ) {
  1232. //
  1233. // Fall through, since we cannot undo what we have done.
  1234. //
  1235. }
  1236. }
  1237. }
  1238. else {
  1239. ObpDecrementHandleCount( TargetProcess,
  1240. ObjectHeader,
  1241. ObjectType,
  1242. TargetAccess
  1243. );
  1244. ObDereferenceObject( SourceObject );
  1245. if (ARGUMENT_PRESENT( TargetHandle )) {
  1246. try {
  1247. *TargetHandle = (HANDLE)NULL;
  1248. }
  1249. except( EXCEPTION_EXECUTE_HANDLER ) {
  1250. //
  1251. // Fall through so we can return the correct status.
  1252. //
  1253. }
  1254. }
  1255. Status = STATUS_INSUFFICIENT_RESOURCES;
  1256. }
  1257. if (PassedAccessState != NULL) {
  1258. SeDeleteAccessState( PassedAccessState );
  1259. }
  1260. KeReleaseMutant( &ObpInitKillMutant, 0, FALSE, FALSE );
  1261. KeLeaveCriticalRegion();
  1262. ObDereferenceObject( SourceProcess );
  1263. ObDereferenceObject( TargetProcess );
  1264. return( Status );
  1265. }
  1266. NTSTATUS
  1267. ObpValidateDesiredAccess(
  1268. IN ACCESS_MASK DesiredAccess
  1269. )
  1270. {
  1271. if (DesiredAccess & 0x0EE00000) {
  1272. return( STATUS_ACCESS_DENIED );
  1273. }
  1274. else {
  1275. return( STATUS_SUCCESS );
  1276. }
  1277. }
  1278. NTSTATUS
  1279. ObpCaptureHandleInformation(
  1280. IN OUT PSYSTEM_HANDLE_TABLE_ENTRY_INFO *HandleEntryInfo,
  1281. IN HANDLE UniqueProcessId,
  1282. IN PVOID HandleTableEntry,
  1283. IN HANDLE HandleIndex,
  1284. IN ULONG Length,
  1285. IN OUT PULONG RequiredLength
  1286. );
  1287. #ifdef ALLOC_PRAGMA
  1288. #pragma alloc_text(PAGE,ObGetHandleInformation)
  1289. #endif
  1290. NTSTATUS
  1291. ObpCaptureHandleInformation(
  1292. IN OUT PSYSTEM_HANDLE_TABLE_ENTRY_INFO *HandleEntryInfo,
  1293. IN HANDLE UniqueProcessId,
  1294. IN PVOID HandleTableEntry,
  1295. IN HANDLE HandleIndex,
  1296. IN ULONG Length,
  1297. IN OUT PULONG RequiredLength
  1298. )
  1299. {
  1300. NTSTATUS Status;
  1301. POBJECT_TABLE_ENTRY ObjectTableEntry = (POBJECT_TABLE_ENTRY)HandleTableEntry;
  1302. POBJECT_HEADER ObjectHeader;
  1303. *RequiredLength += sizeof( SYSTEM_HANDLE_TABLE_ENTRY_INFO );
  1304. if (Length < *RequiredLength) {
  1305. Status = STATUS_INFO_LENGTH_MISMATCH;
  1306. }
  1307. else {
  1308. ObjectHeader = (POBJECT_HEADER)
  1309. (ObjectTableEntry->Attributes & ~OBJ_HANDLE_ATTRIBUTES);
  1310. (*HandleEntryInfo)->UniqueProcessId = (USHORT)UniqueProcessId;
  1311. (*HandleEntryInfo)->HandleAttributes = (UCHAR)
  1312. (ObjectTableEntry->Attributes & OBJ_HANDLE_ATTRIBUTES);
  1313. (*HandleEntryInfo)->ObjectTypeIndex = (UCHAR)(ObjectHeader->Type->Index);
  1314. (*HandleEntryInfo)->HandleValue = (USHORT)(MAKE_OBJECT_HANDLE( HandleIndex ));
  1315. (*HandleEntryInfo)->Object = &ObjectHeader->Body;
  1316. (*HandleEntryInfo)->CreatorBackTraceIndex = 0;
  1317. #if i386 && !FPO
  1318. if (NtGlobalFlag & FLG_KERNEL_STACK_TRACE_DB) {
  1319. (*HandleEntryInfo)->CreatorBackTraceIndex = ObjectTableEntry->CreatorBackTraceIndex;
  1320. (*HandleEntryInfo)->GrantedAccess = ObpTranslateGrantedAccessIndex( ObjectTableEntry->GrantedAccessIndex );
  1321. }
  1322. else
  1323. #endif // i386 && !FPO
  1324. (*HandleEntryInfo)->GrantedAccess = ObjectTableEntry->GrantedAccess;
  1325. (*HandleEntryInfo)++;
  1326. Status = STATUS_SUCCESS;
  1327. }
  1328. return( Status );
  1329. }
  1330. NTSTATUS
  1331. ObGetHandleInformation(
  1332. OUT PSYSTEM_HANDLE_INFORMATION HandleInformation,
  1333. IN ULONG Length,
  1334. OUT PULONG ReturnLength OPTIONAL
  1335. )
  1336. {
  1337. NTSTATUS Status;
  1338. ULONG RequiredLength;
  1339. PAGED_CODE();
  1340. RequiredLength = FIELD_OFFSET( SYSTEM_HANDLE_INFORMATION, Handles );
  1341. if (Length < RequiredLength) {
  1342. return( STATUS_INFO_LENGTH_MISMATCH );
  1343. }
  1344. HandleInformation->NumberOfHandles = 0;
  1345. Status = ExSnapShotHandleTables( ObpCaptureHandleInformation,
  1346. HandleInformation,
  1347. Length,
  1348. &RequiredLength
  1349. );
  1350. if (ARGUMENT_PRESENT( ReturnLength )) {
  1351. *ReturnLength = RequiredLength;
  1352. }
  1353. return( Status );
  1354. }
  1355. #if i386 && !FPO
  1356. ULONG ObpXXX1;
  1357. ULONG ObpXXX2;
  1358. ULONG ObpXXX3;
  1359. USHORT
  1360. ObpComputeGrantedAccessIndex(
  1361. ACCESS_MASK GrantedAccess
  1362. )
  1363. {
  1364. KIRQL OldIrql;
  1365. ULONG GrantedAccessIndex, n;
  1366. PACCESS_MASK p;
  1367. ObpXXX1 += 1;
  1368. ExAcquireFastLock( &ObpLock, &OldIrql );
  1369. n = ObpCurCachedGrantedAccessIndex;
  1370. p = ObpCachedGrantedAccesses;
  1371. for (GrantedAccessIndex=0;
  1372. GrantedAccessIndex<n;
  1373. GrantedAccessIndex++, p++
  1374. ) {
  1375. ObpXXX2 += 1;
  1376. if (*p == GrantedAccess) {
  1377. ExReleaseFastLock( &ObpLock, OldIrql );
  1378. return (USHORT)GrantedAccessIndex;
  1379. }
  1380. }
  1381. if (ObpCurCachedGrantedAccessIndex == ObpMaxCachedGrantedAccessIndex) {
  1382. DbgPrint( "OB: GrantedAccess cache limit hit.\n" );
  1383. DbgBreakPoint();
  1384. }
  1385. *p = GrantedAccess;
  1386. ObpCurCachedGrantedAccessIndex += 1;
  1387. ExReleaseFastLock( &ObpLock, OldIrql );
  1388. return (USHORT)GrantedAccessIndex;
  1389. }
  1390. ACCESS_MASK
  1391. ObpTranslateGrantedAccessIndex(
  1392. USHORT GrantedAccessIndex
  1393. )
  1394. {
  1395. KIRQL OldIrql;
  1396. ACCESS_MASK GrantedAccess = (ACCESS_MASK)0;
  1397. ObpXXX3 += 1;
  1398. ExAcquireFastLock( &ObpLock, &OldIrql );
  1399. if (GrantedAccessIndex < ObpCurCachedGrantedAccessIndex) {
  1400. GrantedAccess = ObpCachedGrantedAccesses[ GrantedAccessIndex ];
  1401. }
  1402. ExReleaseFastLock( &ObpLock, OldIrql );
  1403. return GrantedAccess;
  1404. }
  1405. #endif // i386 && !FPO