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.

548 lines
13 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. obclose.c
  5. Abstract:
  6. Object close system service
  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,NtMakeTemporaryObject)
  14. #pragma alloc_text(PAGE,NtClose)
  15. #pragma alloc_text(PAGE,ObMakeTemporaryObject)
  16. #pragma alloc_text(PAGE,ObpCloseHandleTableEntry)
  17. #pragma alloc_text(PAGE,ObCloseHandle)
  18. #pragma alloc_text(PAGE,ObpCloseHandle)
  19. #endif
  20. //
  21. // Indicates if auditing is enabled so we have to close down the object
  22. // audit alarm
  23. //
  24. extern BOOLEAN SepAdtAuditingEnabled;
  25. NTSTATUS
  26. ObpCloseHandleTableEntry (
  27. IN PHANDLE_TABLE ObjectTable,
  28. IN PHANDLE_TABLE_ENTRY ObjectTableEntry,
  29. IN HANDLE Handle,
  30. IN KPROCESSOR_MODE PreviousMode,
  31. IN BOOLEAN Rundown
  32. )
  33. /*++
  34. Routine Description:
  35. This function is used to close a handle table entry
  36. Arguments:
  37. ObjectTableEntry - Supplies the entry being closed. It must be locked
  38. PreviousMode - Mode of caller
  39. Rundown - Called as part of process rundown, ignore protected handles in this mode
  40. Return Value:
  41. NTSTATUS.
  42. --*/
  43. {
  44. POBJECT_HEADER ObjectHeader;
  45. POBJECT_TYPE ObjectType;
  46. PVOID Object;
  47. ULONG CapturedGrantedAccess;
  48. ULONG CapturedAttributes;
  49. #if DBG
  50. KIRQL SaveIrql;
  51. #endif // DBG
  52. //
  53. // From the object table entry we can grab a pointer to the object
  54. // header, get its type and its body
  55. //
  56. ObjectHeader = (POBJECT_HEADER)(((ULONG_PTR)(ObjectTableEntry->Object)) & ~OBJ_HANDLE_ATTRIBUTES);
  57. ObjectType = ObjectHeader->Type;
  58. Object = &ObjectHeader->Body;
  59. //
  60. // If the object type specifies an okay to close procedure then we
  61. // need to invoke that callback. If the callback doesn't want us to
  62. // close handle then unlock the object table and return the error
  63. // to our caller
  64. //
  65. if (ObjectType->TypeInfo.OkayToCloseProcedure != NULL) {
  66. ObpBeginTypeSpecificCallOut( SaveIrql );
  67. if (!(*ObjectType->TypeInfo.OkayToCloseProcedure)( PsGetCurrentProcess(),
  68. Object,
  69. Handle,
  70. PreviousMode )) {
  71. ObpEndTypeSpecificCallOut( SaveIrql, "NtClose", ObjectType, Object );
  72. ExUnlockHandleTableEntry( ObjectTable, ObjectTableEntry );
  73. return STATUS_HANDLE_NOT_CLOSABLE;
  74. }
  75. ObpEndTypeSpecificCallOut( SaveIrql, "NtClose", ObjectType, Object );
  76. }
  77. CapturedAttributes = ObpGetHandleAttributes(ObjectTableEntry);
  78. //
  79. // If the previous mode was user and the handle is protected from
  80. // being closed, then we'll either raise or return an error depending
  81. // on the global flags and debugger port situation.
  82. //
  83. if ((CapturedAttributes & OBJ_PROTECT_CLOSE) != 0 && Rundown == FALSE) {
  84. if (PreviousMode != KernelMode) {
  85. ExUnlockHandleTableEntry( ObjectTable, ObjectTableEntry );
  86. if (!KeIsAttachedProcess() &&
  87. ((NtGlobalFlag & FLG_ENABLE_CLOSE_EXCEPTIONS) ||
  88. (PsGetCurrentProcess()->DebugPort != NULL) ||
  89. (ObjectTable->DebugInfo != NULL))) {
  90. //
  91. // Raise and exception in user mode
  92. //
  93. return KeRaiseUserException(STATUS_HANDLE_NOT_CLOSABLE);
  94. } else {
  95. return STATUS_HANDLE_NOT_CLOSABLE;
  96. }
  97. } else {
  98. KeBugCheckEx(INVALID_KERNEL_HANDLE, (ULONG_PTR)Handle, 0, 0, 0);
  99. }
  100. }
  101. //
  102. // Get the granted access for the handle
  103. //
  104. #if i386
  105. if (NtGlobalFlag & FLG_KERNEL_STACK_TRACE_DB) {
  106. CapturedGrantedAccess = ObpTranslateGrantedAccessIndex( ObjectTableEntry->GrantedAccessIndex );
  107. } else {
  108. CapturedGrantedAccess = ObpDecodeGrantedAccess(ObjectTableEntry->GrantedAccess);
  109. }
  110. #else
  111. CapturedGrantedAccess = ObpDecodeGrantedAccess(ObjectTableEntry->GrantedAccess);
  112. #endif // i386
  113. //
  114. // Now remove the handle from the handle table
  115. //
  116. ExDestroyHandle( ObjectTable,
  117. Handle,
  118. ObjectTableEntry );
  119. //
  120. // perform any auditing required
  121. //
  122. //
  123. // Extract the value of the GenerateOnClose bit stored
  124. // after object open auditing is performed. This value
  125. // was stored by a call to ObSetGenerateOnClosed.
  126. //
  127. if (CapturedAttributes & OBJ_AUDIT_OBJECT_CLOSE) {
  128. if ( SepAdtAuditingEnabled ) {
  129. SeCloseObjectAuditAlarm( Object,
  130. (HANDLE)((ULONG_PTR)Handle & ~OBJ_HANDLE_TAGBITS), // Mask off the tagbits defined for OB objects.
  131. TRUE );
  132. }
  133. }
  134. //
  135. // Since we took the handle away we need to decrement the objects
  136. // handle count, and remove a reference
  137. //
  138. ObpDecrementHandleCount( PsGetCurrentProcess(),
  139. ObjectHeader,
  140. ObjectType,
  141. CapturedGrantedAccess );
  142. ObDereferenceObject( Object );
  143. //
  144. // And return to our caller
  145. //
  146. return STATUS_SUCCESS;
  147. }
  148. NTSTATUS
  149. ObpCloseHandle (
  150. IN HANDLE Handle,
  151. IN KPROCESSOR_MODE PreviousMode
  152. )
  153. /*++
  154. Routine Description:
  155. This function is used to close access to the specified handle with the given mode
  156. Arguments:
  157. Handle - Supplies the handle being closed
  158. PreviousMode - Processor mode to be used in the handle access checks.
  159. CanNotRaise - We are not allowed to do a user mode raise.
  160. Return Value:
  161. An appropriate status value
  162. --*/
  163. {
  164. PHANDLE_TABLE ObjectTable;
  165. PHANDLE_TABLE_ENTRY ObjectTableEntry;
  166. NTSTATUS Status;
  167. BOOLEAN AttachedToProcess = FALSE;
  168. KAPC_STATE ApcState;
  169. PETHREAD CurrentThread;
  170. PEPROCESS CurrentProcess;
  171. ObpValidateIrql( "NtClose" );
  172. CurrentThread = PsGetCurrentThread ();
  173. CurrentProcess = PsGetCurrentProcessByThread (CurrentThread);
  174. //
  175. // For the current process we will grab its handle/object table and
  176. // translate the handle to its corresponding table entry. If the
  177. // call is successful it also lock down the handle table. But first
  178. // check for a kernel handle and attach and use that table if so.
  179. //
  180. if (IsKernelHandle( Handle, PreviousMode )) {
  181. Handle = DecodeKernelHandle( Handle );
  182. ObjectTable = ObpKernelHandleTable;
  183. //
  184. // Go to the system process if we have to
  185. //
  186. if (CurrentProcess != PsInitialSystemProcess) {
  187. KeStackAttachProcess (&PsInitialSystemProcess->Pcb, &ApcState);
  188. AttachedToProcess = TRUE;
  189. }
  190. } else {
  191. ObjectTable = CurrentProcess->ObjectTable;
  192. }
  193. //
  194. // Protect ourselves from being interrupted while we hold a handle table
  195. // entry lock
  196. //
  197. KeEnterCriticalRegionThread(&CurrentThread->Tcb);
  198. ObjectTableEntry = ExMapHandleToPointer( ObjectTable,
  199. Handle );
  200. //
  201. // Check that the specified handle is legitimate otherwise we can
  202. // assume the caller just passed in some bogus handle value
  203. //
  204. if (ObjectTableEntry != NULL) {
  205. Status = ObpCloseHandleTableEntry (ObjectTable, ObjectTableEntry, Handle, PreviousMode, FALSE);
  206. KeLeaveCriticalRegionThread(&CurrentThread->Tcb);
  207. //
  208. // If we are attached to the system process then detach
  209. //
  210. if (AttachedToProcess) {
  211. KeUnstackDetachProcess(&ApcState);
  212. AttachedToProcess = FALSE;
  213. }
  214. } else {
  215. KeLeaveCriticalRegionThread(&CurrentThread->Tcb);
  216. //
  217. // At this point the input handle did not translate to a valid
  218. // object table entry
  219. //
  220. //
  221. // If we are attached to the system process then return
  222. // back to our caller
  223. //
  224. if (AttachedToProcess) {
  225. KeUnstackDetachProcess(&ApcState);
  226. AttachedToProcess = FALSE;
  227. }
  228. //
  229. // Now if the handle is not null and it does not represent the
  230. // current thread or process then if we're user mode we either raise
  231. // or return an error
  232. //
  233. if ((Handle != NULL) &&
  234. (Handle != NtCurrentThread()) &&
  235. (Handle != NtCurrentProcess())) {
  236. if (PreviousMode != KernelMode) {
  237. if ((NtGlobalFlag & FLG_ENABLE_CLOSE_EXCEPTIONS) ||
  238. (CurrentProcess->DebugPort != NULL) ||
  239. (ObjectTable->DebugInfo != NULL)) {
  240. if (!KeIsAttachedProcess()) {
  241. return KeRaiseUserException (STATUS_INVALID_HANDLE);
  242. } else {
  243. return STATUS_INVALID_HANDLE;
  244. }
  245. }
  246. } else {
  247. //
  248. // bugcheck here if kernel debugger is enabled and if kernel mode code is
  249. // closing a bogus handle and process is not exiting. Ignore
  250. // if no PEB as this occurs if process is killed before
  251. // really starting.
  252. //
  253. if ((!PsIsThreadTerminating(CurrentThread)) &&
  254. (CurrentProcess->Peb != NULL)) {
  255. if (KdDebuggerEnabled) {
  256. KeBugCheckEx(INVALID_KERNEL_HANDLE, (ULONG_PTR)Handle, 1, 0, 0);
  257. }
  258. }
  259. }
  260. }
  261. Status = STATUS_INVALID_HANDLE;
  262. }
  263. return Status;
  264. }
  265. NTSTATUS
  266. ObCloseHandle (
  267. IN HANDLE Handle,
  268. IN KPROCESSOR_MODE PreviousMode
  269. )
  270. /*++
  271. Routine Description:
  272. This function is used to close access to the specified handle with the given mode
  273. Arguments:
  274. Handle - Supplies the handle being closed
  275. PreviousMode - Processor mode to be used in the handle access checks.
  276. Return Value:
  277. An appropriate status value
  278. --*/
  279. {
  280. return ObpCloseHandle (Handle,
  281. PreviousMode);
  282. }
  283. NTSTATUS
  284. NtClose (
  285. IN HANDLE Handle
  286. )
  287. /*++
  288. Routine Description:
  289. This function is used to close access to the specified handle
  290. Arguments:
  291. Handle - Supplies the handle being closed
  292. Return Value:
  293. An appropriate status value
  294. --*/
  295. {
  296. return ObpCloseHandle (Handle,
  297. KeGetPreviousMode ());
  298. }
  299. NTSTATUS
  300. NtMakeTemporaryObject (
  301. IN HANDLE Handle
  302. )
  303. /*++
  304. Routine Description:
  305. This routine makes the specified object non permanent.
  306. Arguments:
  307. Handle - Supplies a handle to the object being modified
  308. Return Value:
  309. An appropriate status value.
  310. --*/
  311. {
  312. KPROCESSOR_MODE PreviousMode;
  313. NTSTATUS Status;
  314. PVOID Object;
  315. OBJECT_HANDLE_INFORMATION HandleInformation;
  316. PAGED_CODE();
  317. //
  318. // Get previous processor mode and probe output argument if necessary.
  319. //
  320. PreviousMode = KeGetPreviousMode();
  321. Status = ObReferenceObjectByHandle( Handle,
  322. DELETE,
  323. (POBJECT_TYPE)NULL,
  324. PreviousMode,
  325. &Object,
  326. &HandleInformation );
  327. if (!NT_SUCCESS( Status )) {
  328. return( Status );
  329. }
  330. //
  331. // Make the object temporary. Note that the object should still
  332. // have a name and directory entry because its handle count is not
  333. // zero
  334. //
  335. ObMakeTemporaryObject( Object );
  336. //
  337. // Check if we need to generate a delete object audit/alarm
  338. //
  339. if (HandleInformation.HandleAttributes & OBJ_AUDIT_OBJECT_CLOSE) {
  340. SeDeleteObjectAuditAlarm( Object,
  341. Handle );
  342. }
  343. ObDereferenceObject( Object );
  344. return( Status );
  345. }
  346. VOID
  347. ObMakeTemporaryObject (
  348. IN PVOID Object
  349. )
  350. /*++
  351. Routine Description:
  352. This routine removes the name of the object from its parent
  353. directory. The object is only removed if it has a non zero
  354. handle count and a name. Otherwise the object is simply
  355. made non permanent
  356. Arguments:
  357. Object - Supplies the object being modified
  358. Return Value:
  359. None.
  360. --*/
  361. {
  362. POBJECT_HEADER ObjectHeader;
  363. POBJECT_TYPE ObjectType;
  364. PAGED_CODE();
  365. ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object );
  366. ObjectType = ObjectHeader->Type;
  367. //
  368. // Other bits are set in this flags field by the handle database code. Synchronise with that.
  369. //
  370. ObpLockObject( ObjectHeader );
  371. ObjectHeader->Flags &= ~OB_FLAG_PERMANENT_OBJECT;
  372. ObpUnlockObject( ObjectHeader );
  373. //
  374. // Now delete the object name if no more handles are present.
  375. //
  376. ObpDeleteNameCheck( Object );
  377. return;
  378. }