2 * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3 * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * - Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
14 * this list of conditions and the following disclaimer in the
16 * and/or other materials provided with the distribution.
17 * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
18 * nor the names of their contributors may be used to endorse or promote
19 * products derived from this software without specific prior written
20 * permission from Kernel Drivers, LLC and Your File System, Inc.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 // File: AFSProcessSupport.cpp
39 #include "AFSCommon.h"
42 AFSProcessNotify( IN HANDLE ParentId,
47 NTSTATUS ntStatus = STATUS_SUCCESS;
48 AFSProcessCB *pProcessCB = NULL, *pParentProcessCB = NULL;
49 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
50 AFSProcessAuthGroupCB *pProcessAuthGroup = NULL, *pLastAuthGroup = NULL;
51 AFSThreadCB *pThreadCB = NULL, *pNextThreadCB = NULL;
57 // If this is a create notification then update our tree, otherwise remove the
61 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
62 AFS_TRACE_LEVEL_VERBOSE,
63 "AFSProcessNotify Acquiring Control ProcessTree.TreeLock lock %08lX EXCL %08lX\n",
64 pDeviceExt->Specific.Control.ProcessTree.TreeLock,
65 PsGetCurrentThread());
67 AFSAcquireExcl( pDeviceExt->Specific.Control.ProcessTree.TreeLock,
73 AFSDbgLogMsg( AFS_SUBSYSTEM_PROCESS_PROCESSING,
74 AFS_TRACE_LEVEL_VERBOSE,
75 "AFSProcessNotify CREATE Parent %08lX Process %08lX %08lX\n",
78 PsGetCurrentThread());
80 pProcessCB = AFSInitializeProcessCB( (ULONGLONG)ParentId,
81 (ULONGLONG)ProcessId);
83 if( pProcessCB != NULL)
85 pProcessCB->CreatingThread = (ULONGLONG)PsGetCurrentThreadId();
88 try_return( ntStatus);
92 // It's a remove so pull the entry
95 AFSDbgLogMsg( AFS_SUBSYSTEM_PROCESS_PROCESSING,
96 AFS_TRACE_LEVEL_VERBOSE,
97 "AFSProcessNotify DESTROY Process %08lX %08lX\n",
99 PsGetCurrentThread());
101 ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.Control.ProcessTree.TreeHead,
102 (ULONGLONG)ProcessId,
103 (AFSBTreeEntry **)&pProcessCB);
105 if( NT_SUCCESS( ntStatus) &&
109 AFSRemoveHashEntry( &pDeviceExt->Specific.Control.ProcessTree.TreeHead,
110 (AFSBTreeEntry *)pProcessCB);
112 pProcessAuthGroup = pProcessCB->AuthGroupList;
114 while( pProcessAuthGroup != NULL)
117 pLastAuthGroup = pProcessAuthGroup->Next;
119 ExFreePool( pProcessAuthGroup);
121 pProcessAuthGroup = pLastAuthGroup;
124 pThreadCB = pProcessCB->ThreadList;
126 while( pThreadCB != NULL)
129 pNextThreadCB = pThreadCB->Next;
131 ExFreePool( pThreadCB);
133 pThreadCB = pNextThreadCB;
136 ExDeleteResourceLite( &pProcessCB->Lock);
138 ExFreePool( pProcessCB);
142 AFSDbgLogMsg( AFS_SUBSYSTEM_PROCESS_PROCESSING,
143 AFS_TRACE_LEVEL_WARNING,
144 "AFSProcessNotify Process %08lX not found in ProcessTree Status %08lX %08lX\n",
147 PsGetCurrentThread());
152 AFSReleaseResource( pDeviceExt->Specific.Control.ProcessTree.TreeLock);
160 // AFSValidateProcessEntry verifies the consistency of the current process
161 // entry which includes assigning an authentication group ACE if one is not
162 // present. A reference to the active authentication group GUID is returned.
166 AFSValidateProcessEntry( void)
169 GUID *pAuthGroup = NULL;
170 NTSTATUS ntStatus = STATUS_SUCCESS;
171 AFSProcessCB *pProcessCB = NULL, *pParentProcessCB = NULL;
172 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
173 ULONGLONG ullProcessID = (ULONGLONG)PsGetCurrentProcessId();
174 UNICODE_STRING uniSIDString;
176 AFSSIDEntryCB *pSIDEntryCB = NULL;
177 ULONG ulSessionId = 0;
178 ULONGLONG ullTableHash = 0;
179 AFSThreadCB *pParentThreadCB = NULL;
180 UNICODE_STRING uniGUID;
181 BOOLEAN bImpersonation = FALSE;
186 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
187 AFS_TRACE_LEVEL_VERBOSE,
188 "AFSValidateProcessEntry Acquiring Control ProcessTree.TreeLock lock %08lX SHARED %08lX\n",
189 pDeviceExt->Specific.Control.ProcessTree.TreeLock,
190 PsGetCurrentThread());
192 uniSIDString.Length = 0;
193 uniSIDString.MaximumLength = 0;
194 uniSIDString.Buffer = NULL;
196 AFSAcquireShared( pDeviceExt->Specific.Control.ProcessTree.TreeLock,
199 AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
200 AFS_TRACE_LEVEL_VERBOSE,
201 "%s Entry for ProcessID %I64X\n",
205 ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.Control.ProcessTree.TreeHead,
206 (ULONGLONG)ullProcessID,
207 (AFSBTreeEntry **)&pProcessCB);
209 if( !NT_SUCCESS( ntStatus) ||
213 AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
214 AFS_TRACE_LEVEL_ERROR,
215 "%s Failed to locate process entry for ProcessID %I64X\n",
220 AFSReleaseResource( pDeviceExt->Specific.Control.ProcessTree.TreeLock);
221 try_return( ntStatus = STATUS_UNSUCCESSFUL);
225 // Locate and lock the ParentProcessCB if we have one
228 if( pProcessCB->ParentProcessId != 0)
231 AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
232 AFS_TRACE_LEVEL_VERBOSE,
233 "%s Locating process entry for Parent ProcessID %I64X\n",
235 pProcessCB->ParentProcessId);
237 ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.Control.ProcessTree.TreeHead,
238 (ULONGLONG)pProcessCB->ParentProcessId,
239 (AFSBTreeEntry **)&pParentProcessCB);
241 if( NT_SUCCESS( ntStatus) &&
242 pParentProcessCB != NULL)
244 AFSAcquireExcl( &pParentProcessCB->Lock,
247 AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
248 AFS_TRACE_LEVEL_VERBOSE,
249 "%s Located process entry for Parent ProcessID %I64X\n",
251 pProcessCB->ParentProcessId);
257 AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
258 AFS_TRACE_LEVEL_VERBOSE,
259 "%s No parent ID for ProcessID %I64X\n",
264 AFSAcquireExcl( &pProcessCB->Lock,
267 AFSReleaseResource( pDeviceExt->Specific.Control.ProcessTree.TreeLock);
270 // Locate the SID for the caller
273 ntStatus = AFSGetCallerSID( &uniSIDString, &bImpersonation);
275 if( !NT_SUCCESS( ntStatus))
278 AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
279 AFS_TRACE_LEVEL_ERROR,
280 "%s Failed to locate callers SID for ProcessID %I64X\n",
284 try_return( ntStatus);
287 ulSessionId = AFSGetSessionId( (HANDLE)ullProcessID, &bImpersonation);
289 if( ulSessionId == (ULONG)-1)
292 AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
293 AFS_TRACE_LEVEL_ERROR,
294 "%s Failed to retrieve session ID for ProcessID %I64X\n",
298 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
301 AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
302 AFS_TRACE_LEVEL_VERBOSE,
303 "%s Retrieved callers SID %wZ for ProcessID %I64X Session %08lX\n",
310 // If there is an Auth Group for the current process,
311 // our job is finished.
314 if ( bImpersonation == FALSE)
316 pAuthGroup = pProcessCB->ActiveAuthGroup;
318 if( pAuthGroup != NULL &&
319 !AFSIsNoPAGAuthGroup( pAuthGroup))
322 uniGUID.Buffer = NULL;
324 RtlStringFromGUID( *pAuthGroup,
327 AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
328 AFS_TRACE_LEVEL_VERBOSE,
329 "%s Located valid AuthGroup GUID %wZ for SID %wZ ProcessID %I64X Session %08lX\n",
336 if( uniGUID.Buffer != NULL)
338 RtlFreeUnicodeString( &uniGUID);
341 try_return( ntStatus = STATUS_SUCCESS);
345 // The current process does not yet have an Auth Group. Try to inherit
346 // one from the parent process thread that created this process.
349 if( pParentProcessCB != NULL)
352 for ( pParentThreadCB = pParentProcessCB->ThreadList;
353 pParentThreadCB != NULL;
354 pParentThreadCB = pParentThreadCB->Next)
357 if( pParentThreadCB->ThreadId == pProcessCB->CreatingThread)
364 // If the creating thread was found and it has a thread specific
365 // Auth Group, use that even if it is the No PAG
368 if( pParentThreadCB != NULL &&
369 pParentThreadCB->ActiveAuthGroup != NULL &&
370 !AFSIsNoPAGAuthGroup( pParentThreadCB->ActiveAuthGroup))
372 pProcessCB->ActiveAuthGroup = pParentThreadCB->ActiveAuthGroup;
374 uniGUID.Buffer = NULL;
376 RtlStringFromGUID( *(pProcessCB->ActiveAuthGroup),
379 AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
380 AFS_TRACE_LEVEL_VERBOSE,
381 "%s PID %08lX Session %08lX inherited Active AuthGroup %wZ from thread %I64X\n",
386 pParentThreadCB->ThreadId);
388 if( uniGUID.Buffer != NULL)
390 RtlFreeUnicodeString( &uniGUID);
395 // If the parent thread was not found or does not have an auth group
398 else if( pParentProcessCB->ActiveAuthGroup != NULL &&
399 !AFSIsNoPAGAuthGroup( pParentProcessCB->ActiveAuthGroup))
401 pProcessCB->ActiveAuthGroup = pParentProcessCB->ActiveAuthGroup;
403 uniGUID.Buffer = NULL;
405 RtlStringFromGUID( *(pProcessCB->ActiveAuthGroup),
408 AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
409 AFS_TRACE_LEVEL_VERBOSE,
410 "%s PID %08lX Session %08lX inherited Active AuthGroup %wZ from parent PID %I64X\n",
415 pParentProcessCB->TreeEntry.HashIndex);
417 if( uniGUID.Buffer != NULL)
419 RtlFreeUnicodeString( &uniGUID);
424 // If an Auth Group was inherited, set it to be the active group
427 if( pProcessCB->ActiveAuthGroup != NULL &&
428 !AFSIsNoPAGAuthGroup( pParentProcessCB->ActiveAuthGroup))
430 pAuthGroup = pProcessCB->ActiveAuthGroup;
432 uniGUID.Buffer = NULL;
434 RtlStringFromGUID( *(pProcessCB->ActiveAuthGroup),
437 AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
438 AFS_TRACE_LEVEL_VERBOSE,
439 "%s Returning(1) Active AuthGroup %wZ for SID %wZ PID %I64X Session %08lX\n",
446 if( uniGUID.Buffer != NULL)
448 RtlFreeUnicodeString( &uniGUID);
451 try_return( ntStatus);
457 // If no Auth Group was inherited, assign one based upon the Session and SID
460 ntStatus = RtlHashUnicodeString( &uniSIDString,
462 HASH_STRING_ALGORITHM_DEFAULT,
465 if( !NT_SUCCESS( ntStatus))
468 AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
469 AFS_TRACE_LEVEL_ERROR,
470 "%s Failed to hash SID %wZ for PID %I64X Session %08lX Status %08lX\n",
477 try_return( ntStatus);
480 ullTableHash = ( ((ULONGLONG)ulSessionId << 32) | ulSIDHash);
482 AFSAcquireShared( pDeviceExt->Specific.Control.AuthGroupTree.TreeLock,
485 ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.Control.AuthGroupTree.TreeHead,
486 (ULONGLONG)ullTableHash,
487 (AFSBTreeEntry **)&pSIDEntryCB);
489 if( !NT_SUCCESS( ntStatus) ||
493 AFSReleaseResource( pDeviceExt->Specific.Control.AuthGroupTree.TreeLock);
495 AFSAcquireExcl( pDeviceExt->Specific.Control.AuthGroupTree.TreeLock,
498 ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.Control.AuthGroupTree.TreeHead,
499 (ULONGLONG)ullTableHash,
500 (AFSBTreeEntry **)&pSIDEntryCB);
502 if( !NT_SUCCESS( ntStatus) ||
506 pSIDEntryCB = (AFSSIDEntryCB *)AFSExAllocatePoolWithTag( NonPagedPool,
507 sizeof( AFSSIDEntryCB),
508 AFS_AG_ENTRY_CB_TAG);
510 if( pSIDEntryCB == NULL)
513 AFSReleaseResource( pDeviceExt->Specific.Control.AuthGroupTree.TreeLock);
515 try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
518 RtlZeroMemory( pSIDEntryCB,
519 sizeof( AFSSIDEntryCB));
521 pSIDEntryCB->TreeEntry.HashIndex = (ULONGLONG)ullTableHash;
523 while( ExUuidCreate( &pSIDEntryCB->AuthGroup) == STATUS_RETRY);
525 uniGUID.Buffer = NULL;
527 RtlStringFromGUID( pSIDEntryCB->AuthGroup,
530 AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
531 AFS_TRACE_LEVEL_VERBOSE,
532 "%s SID %wZ PID %I64X Session %08lX generated NEW AG %wZ\n",
539 if( uniGUID.Buffer != NULL)
541 RtlFreeUnicodeString( &uniGUID);
544 if( pDeviceExt->Specific.Control.AuthGroupTree.TreeHead == NULL)
546 pDeviceExt->Specific.Control.AuthGroupTree.TreeHead = (AFSBTreeEntry *)pSIDEntryCB;
550 AFSInsertHashEntry( pDeviceExt->Specific.Control.AuthGroupTree.TreeHead,
551 &pSIDEntryCB->TreeEntry);
555 AFSConvertToShared( pDeviceExt->Specific.Control.AuthGroupTree.TreeLock);
559 AFSReleaseResource( pDeviceExt->Specific.Control.AuthGroupTree.TreeLock);
562 // Store the auth group into the process cb
565 pProcessCB->ActiveAuthGroup = &pSIDEntryCB->AuthGroup;
567 uniGUID.Buffer = NULL;
569 RtlStringFromGUID( pSIDEntryCB->AuthGroup,
572 AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
573 AFS_TRACE_LEVEL_VERBOSE,
574 "%s SID %wZ PID %I64X Session %08lX assigned AG %wZ\n",
581 if( uniGUID.Buffer != NULL)
583 RtlFreeUnicodeString( &uniGUID);
587 // Set the AFS_PROCESS_LOCAL_SYSTEM_AUTH flag if the process SID
591 if( AFSIsLocalSystemSID( &uniSIDString))
593 SetFlag( pProcessCB->Flags, AFS_PROCESS_LOCAL_SYSTEM_AUTH);
595 AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
596 AFS_TRACE_LEVEL_VERBOSE,
597 "%s Setting PID %I64X Session %08lX with LOCAL SYSTEM AUTHORITY\n",
604 // Return the auth group
607 pAuthGroup = pProcessCB->ActiveAuthGroup;
609 uniGUID.Buffer = NULL;
611 RtlStringFromGUID( *(pProcessCB->ActiveAuthGroup),
614 AFSDbgLogMsg( AFS_SUBSYSTEM_AUTHGROUP_PROCESSING,
615 AFS_TRACE_LEVEL_VERBOSE,
616 "%s Returning(2) Active AuthGroup %wZ for SID %wZ PID %I64X Session %08lX\n",
623 if( uniGUID.Buffer != NULL)
625 RtlFreeUnicodeString( &uniGUID);
630 if( pProcessCB != NULL)
633 if( bImpersonation == FALSE &&
634 !BooleanFlagOn( pProcessCB->Flags, AFS_PROCESS_FLAG_ACE_SET) &&
635 NT_SUCCESS( ntStatus))
637 ntStatus = AFSProcessSetProcessDacl( pProcessCB);
639 if( !NT_SUCCESS( ntStatus))
645 SetFlag( pProcessCB->Flags, AFS_PROCESS_FLAG_ACE_SET);
649 AFSReleaseResource( &pProcessCB->Lock);
652 if( pParentProcessCB != NULL)
654 AFSReleaseResource( &pParentProcessCB->Lock);
657 if( uniSIDString.Length > 0)
659 RtlFreeUnicodeString( &uniSIDString);
667 AFSIs64BitProcess( IN ULONGLONG ProcessId)
670 NTSTATUS ntStatus = STATUS_SUCCESS;
671 BOOLEAN bIs64Bit = FALSE;
672 AFSProcessCB *pProcessCB = NULL;
673 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
678 AFSDbgLogMsg( AFS_SUBSYSTEM_LOCK_PROCESSING,
679 AFS_TRACE_LEVEL_VERBOSE,
680 "AFSIs64BitProcess Acquiring Control ProcessTree.TreeLock lock %08lX SHARED %08lX\n",
681 pDeviceExt->Specific.Control.ProcessTree.TreeLock,
682 PsGetCurrentThread());
684 AFSAcquireShared( pDeviceExt->Specific.Control.ProcessTree.TreeLock,
687 ntStatus = AFSLocateHashEntry( pDeviceExt->Specific.Control.ProcessTree.TreeHead,
688 (ULONGLONG)ProcessId,
689 (AFSBTreeEntry **)&pProcessCB);
691 if( pProcessCB != NULL)
693 bIs64Bit = BooleanFlagOn( pProcessCB->Flags, AFS_PROCESS_FLAG_IS_64BIT);
696 AFSReleaseResource( pDeviceExt->Specific.Control.ProcessTree.TreeLock);
703 AFSInitializeProcessCB( IN ULONGLONG ParentProcessId,
704 IN ULONGLONG ProcessId)
707 AFSProcessCB *pProcessCB = NULL;
708 AFSDeviceExt *pDeviceExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
713 pProcessCB = (AFSProcessCB *)AFSExAllocatePoolWithTag( NonPagedPool,
714 sizeof( AFSProcessCB),
717 if( pProcessCB == NULL)
719 try_return( pProcessCB);
722 RtlZeroMemory( pProcessCB,
723 sizeof( AFSProcessCB));
725 pProcessCB->TreeEntry.HashIndex = (ULONGLONG)ProcessId;
727 pProcessCB->ParentProcessId = (ULONGLONG)ParentProcessId;
731 if( !IoIs32bitProcess( NULL))
733 SetFlag( pProcessCB->Flags, AFS_PROCESS_FLAG_IS_64BIT);
738 if( pDeviceExt->Specific.Control.ProcessTree.TreeHead == NULL)
740 pDeviceExt->Specific.Control.ProcessTree.TreeHead = (AFSBTreeEntry *)pProcessCB;
744 AFSInsertHashEntry( pDeviceExt->Specific.Control.ProcessTree.TreeHead,
745 &pProcessCB->TreeEntry);
748 ExInitializeResourceLite( &pProcessCB->Lock);
750 pProcessCB->ActiveAuthGroup = &AFSNoPAGAuthGroup;
761 AFSInitializeThreadCB( IN AFSProcessCB *ProcessCB,
762 IN ULONGLONG ThreadId)
765 AFSThreadCB *pThreadCB = NULL, *pCurrentThreadCB = NULL;
770 pThreadCB = (AFSThreadCB *)AFSExAllocatePoolWithTag( NonPagedPool,
771 sizeof( AFSThreadCB),
774 if( pThreadCB == NULL)
776 try_return( pThreadCB);
779 RtlZeroMemory( pThreadCB,
780 sizeof( AFSThreadCB));
782 pThreadCB->ThreadId = ThreadId;
784 if( ProcessCB->ThreadList == NULL)
786 ProcessCB->ThreadList = pThreadCB;
791 pCurrentThreadCB = ProcessCB->ThreadList;
793 while( pCurrentThreadCB != NULL)
796 if( pCurrentThreadCB->Next == NULL)
798 pCurrentThreadCB->Next = pThreadCB;
802 pCurrentThreadCB = pCurrentThreadCB->Next;