2006-05-23 21:42:28 +00:00
|
|
|
/*
|
|
|
|
* PROJECT: ReactOS Kernel
|
|
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
2006-06-22 02:20:34 +00:00
|
|
|
* FILE: ntoskrnl/ob/obsecure.c
|
2006-05-23 21:42:28 +00:00
|
|
|
* PURPOSE: SRM Interface of the Object Manager
|
|
|
|
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
|
2006-06-08 02:36:12 +00:00
|
|
|
* Eric Kohl
|
2006-05-23 21:42:28 +00:00
|
|
|
*/
|
1999-12-26 15:50:53 +00:00
|
|
|
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
|
2004-08-15 16:39:12 +00:00
|
|
|
#include <ntoskrnl.h>
|
2004-09-09 12:20:48 +00:00
|
|
|
#define NDEBUG
|
2007-01-08 07:46:17 +00:00
|
|
|
#include <debug.h>
|
1999-12-26 15:50:53 +00:00
|
|
|
|
2006-06-29 05:05:27 +00:00
|
|
|
/* PRIVATE FUNCTIONS *********************************************************/
|
|
|
|
|
2008-03-31 20:07:02 +00:00
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
ObAssignObjectSecurityDescriptor(IN PVOID Object,
|
|
|
|
IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL,
|
|
|
|
IN POOL_TYPE PoolType)
|
|
|
|
{
|
|
|
|
POBJECT_HEADER ObjectHeader;
|
|
|
|
NTSTATUS Status;
|
|
|
|
PSECURITY_DESCRIPTOR NewSd;
|
2009-03-04 20:58:32 +00:00
|
|
|
PEX_FAST_REF FastRef;
|
2008-03-31 20:07:02 +00:00
|
|
|
PAGED_CODE();
|
2008-04-01 21:09:28 +00:00
|
|
|
|
2008-03-31 20:07:02 +00:00
|
|
|
/* Get the object header */
|
|
|
|
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
|
2009-03-04 20:58:32 +00:00
|
|
|
FastRef = (PEX_FAST_REF)&ObjectHeader->SecurityDescriptor;
|
2008-03-31 20:07:02 +00:00
|
|
|
if (!SecurityDescriptor)
|
|
|
|
{
|
|
|
|
/* Nothing to assign */
|
2009-03-04 20:58:32 +00:00
|
|
|
ExInitializeFastReference(FastRef, NULL);
|
2008-03-31 20:07:02 +00:00
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
2008-04-01 21:09:28 +00:00
|
|
|
|
2008-03-31 20:07:02 +00:00
|
|
|
/* Add it to our internal cache */
|
2009-03-04 20:58:32 +00:00
|
|
|
Status = ObLogSecurityDescriptor(SecurityDescriptor,
|
|
|
|
&NewSd,
|
|
|
|
MAX_FAST_REFS + 1);
|
2008-03-31 20:07:02 +00:00
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* Free the old copy */
|
2008-08-31 15:29:21 +00:00
|
|
|
ExFreePoolWithTag(SecurityDescriptor, TAG_SD);
|
2008-04-01 21:09:28 +00:00
|
|
|
|
2008-03-31 20:07:02 +00:00
|
|
|
/* Set the new pointer */
|
|
|
|
ASSERT(NewSd);
|
2009-03-04 20:58:32 +00:00
|
|
|
ExInitializeFastReference(FastRef, NewSd);
|
2008-03-31 20:07:02 +00:00
|
|
|
}
|
2008-04-01 21:09:28 +00:00
|
|
|
|
2008-03-31 20:07:02 +00:00
|
|
|
/* Return status */
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
ObDeassignSecurity(IN OUT PSECURITY_DESCRIPTOR *SecurityDescriptor)
|
|
|
|
{
|
2009-03-04 20:58:32 +00:00
|
|
|
EX_FAST_REF FastRef;
|
[HAL/NDK]
- Make Vector parameter in HalEnableSystemInterrupt, HalDisableSystemInterrupt and HalBeginSystemInterrupt an ULONG, not an UCHAR
[NDK]
- 64bit fixes for HANDLE_TABLE, KPROCESS, SECTION_IMAGE_INFORMATION, MMADDRESS_LIST, MMVAD_FLAGS, MMVAD, MMVAD_LONG, MMVAD_SHORT, MEMORY_DESCRIPTOR, MEMORY_ALLOCATION_DESCRIPTOR, LdrVerifyMappedImageMatchesChecksum
- KDPC_DATA::DpcQueueDepth is signed on amd64, unsigned on x86
[NTOSKRNL]
- Fix hundreds of MSVC and amd64 warnings
- add a pragma message to FstubFixupEfiPartition, since it looks broken
- Move portable Ke constants from <arch>/cpu.c to krnlinit.c
- Fixed a bug in amd64 KiGeneralProtectionFaultHandler
svn path=/trunk/; revision=53734
2011-09-18 13:11:45 +00:00
|
|
|
ULONG Count;
|
2009-03-04 20:58:32 +00:00
|
|
|
PSECURITY_DESCRIPTOR OldSecurityDescriptor;
|
2013-11-18 14:27:01 +00:00
|
|
|
|
2009-03-04 20:58:32 +00:00
|
|
|
/* Get the fast reference and capture it */
|
|
|
|
FastRef = *(PEX_FAST_REF)SecurityDescriptor;
|
2013-11-18 14:27:01 +00:00
|
|
|
|
2008-03-31 20:07:02 +00:00
|
|
|
/* Don't free again later */
|
|
|
|
*SecurityDescriptor = NULL;
|
2013-11-18 14:27:01 +00:00
|
|
|
|
2009-03-04 20:58:32 +00:00
|
|
|
/* Get the descriptor and reference count */
|
|
|
|
OldSecurityDescriptor = ExGetObjectFastReference(FastRef);
|
|
|
|
Count = ExGetCountFastReference(FastRef);
|
2013-11-18 14:27:01 +00:00
|
|
|
|
2009-03-04 20:58:32 +00:00
|
|
|
/* Dereference the descriptor */
|
|
|
|
ObDereferenceSecurityDescriptor(OldSecurityDescriptor, Count + 1);
|
2008-04-01 21:09:28 +00:00
|
|
|
|
2008-03-31 20:07:02 +00:00
|
|
|
/* All done */
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
ObQuerySecurityDescriptorInfo(IN PVOID Object,
|
|
|
|
IN PSECURITY_INFORMATION SecurityInformation,
|
|
|
|
OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
|
|
|
|
IN OUT PULONG Length,
|
|
|
|
IN PSECURITY_DESCRIPTOR *OutputSecurityDescriptor)
|
|
|
|
{
|
|
|
|
POBJECT_HEADER ObjectHeader;
|
|
|
|
NTSTATUS Status;
|
|
|
|
PSECURITY_DESCRIPTOR ObjectSd;
|
|
|
|
PAGED_CODE();
|
2008-04-01 21:09:28 +00:00
|
|
|
|
2008-03-31 20:07:02 +00:00
|
|
|
/* Get the object header */
|
|
|
|
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
|
2008-04-01 21:09:28 +00:00
|
|
|
|
2008-03-31 20:07:02 +00:00
|
|
|
/* Get the SD */
|
2008-04-01 21:09:28 +00:00
|
|
|
ObjectSd = ObpReferenceSecurityDescriptor(ObjectHeader);
|
|
|
|
|
2008-03-31 20:07:02 +00:00
|
|
|
/* Query the information */
|
|
|
|
Status = SeQuerySecurityDescriptorInfo(SecurityInformation,
|
|
|
|
SecurityDescriptor,
|
|
|
|
Length,
|
|
|
|
&ObjectSd);
|
|
|
|
|
|
|
|
/* Check if we have an object SD and dereference it, if so */
|
2008-04-01 21:09:28 +00:00
|
|
|
if (ObjectSd) ObDereferenceSecurityDescriptor(ObjectSd, 1);
|
|
|
|
|
2008-03-31 20:07:02 +00:00
|
|
|
/* Return status */
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
ObSetSecurityDescriptorInfo(IN PVOID Object,
|
|
|
|
IN PSECURITY_INFORMATION SecurityInformation,
|
|
|
|
IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
|
|
|
|
IN OUT PSECURITY_DESCRIPTOR *OutputSecurityDescriptor,
|
|
|
|
IN POOL_TYPE PoolType,
|
|
|
|
IN PGENERIC_MAPPING GenericMapping)
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
POBJECT_HEADER ObjectHeader;
|
|
|
|
PSECURITY_DESCRIPTOR OldDescriptor, NewDescriptor, CachedDescriptor;
|
2009-03-04 20:58:32 +00:00
|
|
|
PEX_FAST_REF FastRef;
|
|
|
|
EX_FAST_REF OldValue;
|
[HAL/NDK]
- Make Vector parameter in HalEnableSystemInterrupt, HalDisableSystemInterrupt and HalBeginSystemInterrupt an ULONG, not an UCHAR
[NDK]
- 64bit fixes for HANDLE_TABLE, KPROCESS, SECTION_IMAGE_INFORMATION, MMADDRESS_LIST, MMVAD_FLAGS, MMVAD, MMVAD_LONG, MMVAD_SHORT, MEMORY_DESCRIPTOR, MEMORY_ALLOCATION_DESCRIPTOR, LdrVerifyMappedImageMatchesChecksum
- KDPC_DATA::DpcQueueDepth is signed on amd64, unsigned on x86
[NTOSKRNL]
- Fix hundreds of MSVC and amd64 warnings
- add a pragma message to FstubFixupEfiPartition, since it looks broken
- Move portable Ke constants from <arch>/cpu.c to krnlinit.c
- Fixed a bug in amd64 KiGeneralProtectionFaultHandler
svn path=/trunk/; revision=53734
2011-09-18 13:11:45 +00:00
|
|
|
ULONG Count;
|
2008-03-31 20:07:02 +00:00
|
|
|
PAGED_CODE();
|
2008-04-01 21:09:28 +00:00
|
|
|
|
2008-03-31 20:07:02 +00:00
|
|
|
/* Get the object header */
|
|
|
|
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
|
|
|
|
while (TRUE)
|
|
|
|
{
|
|
|
|
/* Reference the old descriptor */
|
2008-04-01 21:09:28 +00:00
|
|
|
OldDescriptor = ObpReferenceSecurityDescriptor(ObjectHeader);
|
2008-03-31 20:07:02 +00:00
|
|
|
NewDescriptor = OldDescriptor;
|
2008-04-01 21:09:28 +00:00
|
|
|
|
2008-03-31 20:07:02 +00:00
|
|
|
/* Set the SD information */
|
|
|
|
Status = SeSetSecurityDescriptorInfo(Object,
|
|
|
|
SecurityInformation,
|
|
|
|
SecurityDescriptor,
|
|
|
|
&NewDescriptor,
|
|
|
|
PoolType,
|
|
|
|
GenericMapping);
|
2014-11-04 20:41:10 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
2008-03-31 20:07:02 +00:00
|
|
|
{
|
2014-11-04 20:41:10 +00:00
|
|
|
/* We failed, dereference the old one */
|
|
|
|
if (OldDescriptor) ObDereferenceSecurityDescriptor(OldDescriptor, 1);
|
|
|
|
break;
|
2008-03-31 20:07:02 +00:00
|
|
|
}
|
2014-11-04 20:41:10 +00:00
|
|
|
|
|
|
|
/* Now add this to the cache */
|
|
|
|
Status = ObLogSecurityDescriptor(NewDescriptor,
|
|
|
|
&CachedDescriptor,
|
|
|
|
MAX_FAST_REFS + 1);
|
|
|
|
|
|
|
|
/* Let go of our uncached copy */
|
|
|
|
ExFreePool(NewDescriptor);
|
|
|
|
|
|
|
|
/* Check for success */
|
|
|
|
if (!NT_SUCCESS(Status))
|
2008-03-31 20:07:02 +00:00
|
|
|
{
|
|
|
|
/* We failed, dereference the old one */
|
2014-11-04 20:41:10 +00:00
|
|
|
ObDereferenceSecurityDescriptor(OldDescriptor, 1);
|
2008-03-31 20:07:02 +00:00
|
|
|
break;
|
|
|
|
}
|
2014-11-04 20:41:10 +00:00
|
|
|
|
|
|
|
/* Do the swap */
|
|
|
|
FastRef = (PEX_FAST_REF)OutputSecurityDescriptor;
|
|
|
|
OldValue = ExCompareSwapFastReference(FastRef,
|
|
|
|
CachedDescriptor,
|
|
|
|
OldDescriptor);
|
|
|
|
|
|
|
|
/* Make sure the swap worked */
|
|
|
|
if (ExGetObjectFastReference(OldValue) == OldDescriptor)
|
|
|
|
{
|
|
|
|
/* Flush waiters */
|
|
|
|
ObpAcquireObjectLock(ObjectHeader);
|
|
|
|
ObpReleaseObjectLock(ObjectHeader);
|
|
|
|
|
|
|
|
/* And dereference the old one */
|
|
|
|
Count = ExGetCountFastReference(OldValue);
|
|
|
|
ObDereferenceSecurityDescriptor(OldDescriptor, Count + 2);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Someone changed it behind our back -- try again */
|
|
|
|
ObDereferenceSecurityDescriptor(OldDescriptor, 1);
|
|
|
|
ObDereferenceSecurityDescriptor(CachedDescriptor,
|
|
|
|
MAX_FAST_REFS + 1);
|
|
|
|
}
|
2008-03-31 20:07:02 +00:00
|
|
|
}
|
2008-04-01 21:09:28 +00:00
|
|
|
|
2008-03-31 20:07:02 +00:00
|
|
|
/* Return status */
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2007-01-08 07:46:17 +00:00
|
|
|
BOOLEAN
|
|
|
|
NTAPI
|
|
|
|
ObCheckCreateObjectAccess(IN PVOID Object,
|
|
|
|
IN ACCESS_MASK CreateAccess,
|
|
|
|
IN PACCESS_STATE AccessState,
|
|
|
|
IN PUNICODE_STRING ComponentName,
|
|
|
|
IN BOOLEAN LockHeld,
|
|
|
|
IN KPROCESSOR_MODE AccessMode,
|
|
|
|
OUT PNTSTATUS AccessStatus)
|
|
|
|
{
|
|
|
|
POBJECT_HEADER ObjectHeader;
|
|
|
|
POBJECT_TYPE ObjectType;
|
[NTOSKRNL]
Coverity code defects fixes :
- Cache: CID 701441
- Config: CIDs 716570, 716669, 716760
- Dbgk: Kdbg: CIDs 716571, 515128/9, 500432
- Ex: CIDs 500156/7, 515122, 716200/67, 701301, 514669
- Fsrtl: Fstub: CIDs 701341/2, 701288, 716770, 701302, and CIDs 716576/7/8 + 514636 + 716805 thanks to Thomas Faber
- Io: CIDs 514576, 514643, 514672/3, 716203, 716269, 716581, 716591, 716713
- Ke: CIDs 515125, 716592
- Ps: CIDs 716603/4, 701422
- Ob: Po: CIDs 514671/680, 701419/420/421, 716763, 716601/2
All the details are given in the different bug reports.
CORE-6677 CORE-6679 CORE-6680 CORE-6683 CORE-6686 CORE-6692 CORE-6693 CORE-6694 CORE-6695 CORE-6696 #comment Committed in rev.57400 #resolve #close
svn path=/trunk/; revision=57400
2012-09-27 17:16:31 +00:00
|
|
|
PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
|
2007-01-08 07:46:17 +00:00
|
|
|
BOOLEAN SdAllocated;
|
|
|
|
BOOLEAN Result = TRUE;
|
|
|
|
ACCESS_MASK GrantedAccess = 0;
|
|
|
|
PPRIVILEGE_SET Privileges = NULL;
|
|
|
|
NTSTATUS Status;
|
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
/* Get the header and type */
|
|
|
|
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
|
|
|
|
ObjectType = ObjectHeader->Type;
|
|
|
|
|
|
|
|
/* Get the security descriptor */
|
|
|
|
Status = ObGetObjectSecurity(Object, &SecurityDescriptor, &SdAllocated);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* We failed */
|
|
|
|
*AccessStatus = Status;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Lock the security context */
|
|
|
|
SeLockSubjectContext(&AccessState->SubjectSecurityContext);
|
|
|
|
|
|
|
|
/* Check if we have an SD */
|
|
|
|
if (SecurityDescriptor)
|
|
|
|
{
|
|
|
|
/* Now do the entire access check */
|
|
|
|
Result = SeAccessCheck(SecurityDescriptor,
|
|
|
|
&AccessState->SubjectSecurityContext,
|
|
|
|
TRUE,
|
|
|
|
CreateAccess,
|
|
|
|
0,
|
|
|
|
&Privileges,
|
|
|
|
&ObjectType->TypeInfo.GenericMapping,
|
|
|
|
AccessMode,
|
|
|
|
&GrantedAccess,
|
|
|
|
AccessStatus);
|
|
|
|
if (Privileges)
|
|
|
|
{
|
|
|
|
/* We got privileges, append them to the access state and free them */
|
|
|
|
Status = SeAppendPrivileges(AccessState, Privileges);
|
|
|
|
SeFreePrivileges(Privileges);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We're done, unlock the context and release security */
|
|
|
|
SeUnlockSubjectContext(&AccessState->SubjectSecurityContext);
|
|
|
|
ObReleaseObjectSecurity(SecurityDescriptor, SdAllocated);
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN
|
|
|
|
NTAPI
|
|
|
|
ObpCheckTraverseAccess(IN PVOID Object,
|
|
|
|
IN ACCESS_MASK TraverseAccess,
|
|
|
|
IN PACCESS_STATE AccessState OPTIONAL,
|
|
|
|
IN BOOLEAN LockHeld,
|
|
|
|
IN KPROCESSOR_MODE AccessMode,
|
|
|
|
OUT PNTSTATUS AccessStatus)
|
|
|
|
{
|
|
|
|
POBJECT_HEADER ObjectHeader;
|
|
|
|
POBJECT_TYPE ObjectType;
|
[NTOSKRNL]
Coverity code defects fixes :
- Cache: CID 701441
- Config: CIDs 716570, 716669, 716760
- Dbgk: Kdbg: CIDs 716571, 515128/9, 500432
- Ex: CIDs 500156/7, 515122, 716200/67, 701301, 514669
- Fsrtl: Fstub: CIDs 701341/2, 701288, 716770, 701302, and CIDs 716576/7/8 + 514636 + 716805 thanks to Thomas Faber
- Io: CIDs 514576, 514643, 514672/3, 716203, 716269, 716581, 716591, 716713
- Ke: CIDs 515125, 716592
- Ps: CIDs 716603/4, 701422
- Ob: Po: CIDs 514671/680, 701419/420/421, 716763, 716601/2
All the details are given in the different bug reports.
CORE-6677 CORE-6679 CORE-6680 CORE-6683 CORE-6686 CORE-6692 CORE-6693 CORE-6694 CORE-6695 CORE-6696 #comment Committed in rev.57400 #resolve #close
svn path=/trunk/; revision=57400
2012-09-27 17:16:31 +00:00
|
|
|
PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
|
2007-01-08 07:46:17 +00:00
|
|
|
BOOLEAN SdAllocated;
|
|
|
|
BOOLEAN Result;
|
|
|
|
ACCESS_MASK GrantedAccess = 0;
|
|
|
|
PPRIVILEGE_SET Privileges = NULL;
|
|
|
|
NTSTATUS Status;
|
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
/* Get the header and type */
|
|
|
|
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
|
|
|
|
ObjectType = ObjectHeader->Type;
|
|
|
|
|
|
|
|
/* Get the security descriptor */
|
|
|
|
Status = ObGetObjectSecurity(Object, &SecurityDescriptor, &SdAllocated);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* We failed */
|
|
|
|
*AccessStatus = Status;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2013-01-27 09:50:20 +00:00
|
|
|
/* First try to perform a fast traverse check
|
|
|
|
* If it fails, then the entire access check will
|
|
|
|
* have to be done.
|
|
|
|
*/
|
|
|
|
Result = SeFastTraverseCheck(SecurityDescriptor,
|
|
|
|
AccessState,
|
|
|
|
FILE_WRITE_DATA,
|
|
|
|
AccessMode);
|
|
|
|
if (Result)
|
|
|
|
{
|
|
|
|
ObReleaseObjectSecurity(SecurityDescriptor, SdAllocated);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2007-01-08 07:46:17 +00:00
|
|
|
/* Lock the security context */
|
|
|
|
SeLockSubjectContext(&AccessState->SubjectSecurityContext);
|
|
|
|
|
|
|
|
/* Now do the entire access check */
|
|
|
|
Result = SeAccessCheck(SecurityDescriptor,
|
|
|
|
&AccessState->SubjectSecurityContext,
|
|
|
|
TRUE,
|
|
|
|
TraverseAccess,
|
|
|
|
0,
|
|
|
|
&Privileges,
|
|
|
|
&ObjectType->TypeInfo.GenericMapping,
|
|
|
|
AccessMode,
|
|
|
|
&GrantedAccess,
|
|
|
|
AccessStatus);
|
|
|
|
if (Privileges)
|
|
|
|
{
|
|
|
|
/* We got privileges, append them to the access state and free them */
|
|
|
|
Status = SeAppendPrivileges(AccessState, Privileges);
|
|
|
|
SeFreePrivileges(Privileges);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We're done, unlock the context and release security */
|
|
|
|
SeUnlockSubjectContext(&AccessState->SubjectSecurityContext);
|
|
|
|
ObReleaseObjectSecurity(SecurityDescriptor, SdAllocated);
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN
|
|
|
|
NTAPI
|
|
|
|
ObpCheckObjectReference(IN PVOID Object,
|
|
|
|
IN OUT PACCESS_STATE AccessState,
|
|
|
|
IN BOOLEAN LockHeld,
|
|
|
|
IN KPROCESSOR_MODE AccessMode,
|
|
|
|
OUT PNTSTATUS AccessStatus)
|
|
|
|
{
|
|
|
|
POBJECT_HEADER ObjectHeader;
|
|
|
|
POBJECT_TYPE ObjectType;
|
[NTOSKRNL]
Coverity code defects fixes :
- Cache: CID 701441
- Config: CIDs 716570, 716669, 716760
- Dbgk: Kdbg: CIDs 716571, 515128/9, 500432
- Ex: CIDs 500156/7, 515122, 716200/67, 701301, 514669
- Fsrtl: Fstub: CIDs 701341/2, 701288, 716770, 701302, and CIDs 716576/7/8 + 514636 + 716805 thanks to Thomas Faber
- Io: CIDs 514576, 514643, 514672/3, 716203, 716269, 716581, 716591, 716713
- Ke: CIDs 515125, 716592
- Ps: CIDs 716603/4, 701422
- Ob: Po: CIDs 514671/680, 701419/420/421, 716763, 716601/2
All the details are given in the different bug reports.
CORE-6677 CORE-6679 CORE-6680 CORE-6683 CORE-6686 CORE-6692 CORE-6693 CORE-6694 CORE-6695 CORE-6696 #comment Committed in rev.57400 #resolve #close
svn path=/trunk/; revision=57400
2012-09-27 17:16:31 +00:00
|
|
|
PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
|
2007-01-08 07:46:17 +00:00
|
|
|
BOOLEAN SdAllocated;
|
|
|
|
BOOLEAN Result;
|
|
|
|
ACCESS_MASK GrantedAccess = 0;
|
|
|
|
PPRIVILEGE_SET Privileges = NULL;
|
|
|
|
NTSTATUS Status;
|
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
/* Get the header and type */
|
|
|
|
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
|
|
|
|
ObjectType = ObjectHeader->Type;
|
|
|
|
|
|
|
|
/* Get the security descriptor */
|
|
|
|
Status = ObGetObjectSecurity(Object, &SecurityDescriptor, &SdAllocated);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* We failed */
|
|
|
|
*AccessStatus = Status;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Lock the security context */
|
|
|
|
SeLockSubjectContext(&AccessState->SubjectSecurityContext);
|
|
|
|
|
|
|
|
/* Now do the entire access check */
|
|
|
|
Result = SeAccessCheck(SecurityDescriptor,
|
|
|
|
&AccessState->SubjectSecurityContext,
|
|
|
|
TRUE,
|
|
|
|
AccessState->RemainingDesiredAccess,
|
|
|
|
AccessState->PreviouslyGrantedAccess,
|
|
|
|
&Privileges,
|
|
|
|
&ObjectType->TypeInfo.GenericMapping,
|
|
|
|
AccessMode,
|
|
|
|
&GrantedAccess,
|
|
|
|
AccessStatus);
|
|
|
|
if (Result)
|
|
|
|
{
|
|
|
|
/* Update the access state */
|
|
|
|
AccessState->RemainingDesiredAccess &= ~GrantedAccess;
|
|
|
|
AccessState->PreviouslyGrantedAccess |= GrantedAccess;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check if we have an SD */
|
|
|
|
if (SecurityDescriptor)
|
|
|
|
{
|
|
|
|
/* Do audit alarm */
|
|
|
|
#if 0
|
|
|
|
SeObjectReferenceAuditAlarm(&AccessState->OperationID,
|
|
|
|
Object,
|
|
|
|
SecurityDescriptor,
|
|
|
|
&AccessState->SubjectSecurityContext,
|
|
|
|
AccessState->RemainingDesiredAccess |
|
|
|
|
AccessState->PreviouslyGrantedAccess,
|
2008-06-16 08:54:21 +00:00
|
|
|
((PAUX_ACCESS_DATA)(AccessState->AuxData))->
|
2007-01-08 07:46:17 +00:00
|
|
|
PrivilegeSet,
|
|
|
|
Result,
|
|
|
|
AccessMode);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We're done, unlock the context and release security */
|
|
|
|
SeUnlockSubjectContext(&AccessState->SubjectSecurityContext);
|
|
|
|
ObReleaseObjectSecurity(SecurityDescriptor, SdAllocated);
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2006-06-29 05:05:27 +00:00
|
|
|
/*++
|
|
|
|
* @name ObCheckObjectAccess
|
|
|
|
*
|
2007-03-07 12:30:07 +00:00
|
|
|
* The ObCheckObjectAccess routine <FILLMEIN>
|
2006-06-29 05:05:27 +00:00
|
|
|
*
|
|
|
|
* @param Object
|
|
|
|
* <FILLMEIN>
|
|
|
|
*
|
|
|
|
* @param AccessState
|
|
|
|
* <FILLMEIN>
|
|
|
|
*
|
2007-01-08 07:46:17 +00:00
|
|
|
* @param LockHeld
|
2006-06-29 05:05:27 +00:00
|
|
|
* <FILLMEIN>
|
|
|
|
*
|
|
|
|
* @param AccessMode
|
|
|
|
* <FILLMEIN>
|
|
|
|
*
|
|
|
|
* @param ReturnedStatus
|
|
|
|
* <FILLMEIN>
|
|
|
|
*
|
|
|
|
* @return TRUE if access was granted, FALSE otherwise.
|
|
|
|
*
|
|
|
|
* @remarks None.
|
|
|
|
*
|
|
|
|
*--*/
|
|
|
|
BOOLEAN
|
|
|
|
NTAPI
|
|
|
|
ObCheckObjectAccess(IN PVOID Object,
|
|
|
|
IN OUT PACCESS_STATE AccessState,
|
2007-01-08 07:46:17 +00:00
|
|
|
IN BOOLEAN LockHeld,
|
2006-06-29 05:05:27 +00:00
|
|
|
IN KPROCESSOR_MODE AccessMode,
|
|
|
|
OUT PNTSTATUS ReturnedStatus)
|
|
|
|
{
|
|
|
|
POBJECT_HEADER ObjectHeader;
|
|
|
|
POBJECT_TYPE ObjectType;
|
|
|
|
PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
|
|
|
|
BOOLEAN SdAllocated;
|
|
|
|
NTSTATUS Status;
|
|
|
|
BOOLEAN Result;
|
|
|
|
ACCESS_MASK GrantedAccess;
|
|
|
|
PPRIVILEGE_SET Privileges = NULL;
|
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
/* Get the object header and type */
|
|
|
|
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
|
|
|
|
ObjectType = ObjectHeader->Type;
|
|
|
|
|
|
|
|
/* Get security information */
|
|
|
|
Status = ObGetObjectSecurity(Object, &SecurityDescriptor, &SdAllocated);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* Return failure */
|
|
|
|
*ReturnedStatus = Status;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
else if (!SecurityDescriptor)
|
|
|
|
{
|
|
|
|
/* Otherwise, if we don't actually have an SD, return success */
|
|
|
|
*ReturnedStatus = Status;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Lock the security context */
|
|
|
|
SeLockSubjectContext(&AccessState->SubjectSecurityContext);
|
|
|
|
|
|
|
|
/* Now do the entire access check */
|
|
|
|
Result = SeAccessCheck(SecurityDescriptor,
|
|
|
|
&AccessState->SubjectSecurityContext,
|
|
|
|
TRUE,
|
|
|
|
AccessState->RemainingDesiredAccess,
|
|
|
|
AccessState->PreviouslyGrantedAccess,
|
|
|
|
&Privileges,
|
|
|
|
&ObjectType->TypeInfo.GenericMapping,
|
|
|
|
AccessMode,
|
|
|
|
&GrantedAccess,
|
|
|
|
ReturnedStatus);
|
|
|
|
if (Privileges)
|
|
|
|
{
|
2007-01-08 07:46:17 +00:00
|
|
|
/* We got privileges, append them to the access state and free them */
|
2006-06-29 05:05:27 +00:00
|
|
|
Status = SeAppendPrivileges(AccessState, Privileges);
|
|
|
|
SeFreePrivileges(Privileges);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check if access was granted */
|
|
|
|
if (Result)
|
|
|
|
{
|
|
|
|
/* Update the access state */
|
|
|
|
AccessState->RemainingDesiredAccess &= ~(GrantedAccess |
|
|
|
|
MAXIMUM_ALLOWED);
|
|
|
|
AccessState->PreviouslyGrantedAccess |= GrantedAccess;
|
|
|
|
}
|
|
|
|
|
2006-12-29 22:17:29 +00:00
|
|
|
/* Do audit alarm */
|
|
|
|
SeOpenObjectAuditAlarm(&ObjectType->Name,
|
|
|
|
Object,
|
|
|
|
NULL,
|
|
|
|
SecurityDescriptor,
|
|
|
|
AccessState,
|
|
|
|
FALSE,
|
|
|
|
Result,
|
|
|
|
AccessMode,
|
|
|
|
&AccessState->GenerateOnClose);
|
|
|
|
|
2006-06-29 05:05:27 +00:00
|
|
|
/* We're done, unlock the context and release security */
|
|
|
|
SeUnlockSubjectContext(&AccessState->SubjectSecurityContext);
|
|
|
|
ObReleaseObjectSecurity(SecurityDescriptor, SdAllocated);
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* PUBLIC FUNCTIONS **********************************************************/
|
1999-12-26 15:50:53 +00:00
|
|
|
|
2006-05-23 21:42:28 +00:00
|
|
|
/*++
|
|
|
|
* @name ObAssignSecurity
|
|
|
|
* @implemented NT4
|
|
|
|
*
|
|
|
|
* The ObAssignSecurity routine <FILLMEIN>
|
|
|
|
*
|
|
|
|
* @param AccessState
|
|
|
|
* <FILLMEIN>
|
|
|
|
*
|
|
|
|
* @param SecurityDescriptor
|
|
|
|
* <FILLMEIN>
|
|
|
|
*
|
|
|
|
* @param Object
|
|
|
|
* <FILLMEIN>
|
|
|
|
*
|
|
|
|
* @param Type
|
|
|
|
* <FILLMEIN>
|
|
|
|
*
|
|
|
|
* @return STATUS_SUCCESS or appropriate error value.
|
|
|
|
*
|
|
|
|
* @remarks None.
|
|
|
|
*
|
|
|
|
*--*/
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
2002-02-22 17:57:57 +00:00
|
|
|
ObAssignSecurity(IN PACCESS_STATE AccessState,
|
2006-05-23 21:42:28 +00:00
|
|
|
IN PSECURITY_DESCRIPTOR SecurityDescriptor,
|
|
|
|
IN PVOID Object,
|
|
|
|
IN POBJECT_TYPE Type)
|
2002-02-22 17:57:57 +00:00
|
|
|
{
|
2006-05-23 21:42:28 +00:00
|
|
|
PSECURITY_DESCRIPTOR NewDescriptor;
|
|
|
|
NTSTATUS Status;
|
2006-12-29 22:17:29 +00:00
|
|
|
KIRQL CalloutIrql;
|
2006-05-23 21:42:28 +00:00
|
|
|
PAGED_CODE();
|
2004-07-22 18:38:08 +00:00
|
|
|
|
2006-05-23 21:42:28 +00:00
|
|
|
/* Build the new security descriptor */
|
|
|
|
Status = SeAssignSecurity(SecurityDescriptor,
|
|
|
|
AccessState->SecurityDescriptor,
|
|
|
|
&NewDescriptor,
|
2018-02-13 20:33:04 +00:00
|
|
|
(Type == ObpDirectoryObjectType),
|
2006-05-23 21:42:28 +00:00
|
|
|
&AccessState->SubjectSecurityContext,
|
|
|
|
&Type->TypeInfo.GenericMapping,
|
|
|
|
PagedPool);
|
|
|
|
if (!NT_SUCCESS(Status)) return Status;
|
|
|
|
|
|
|
|
/* Call the security method */
|
2006-12-29 22:17:29 +00:00
|
|
|
ObpCalloutStart(&CalloutIrql);
|
2006-05-23 21:42:28 +00:00
|
|
|
Status = Type->TypeInfo.SecurityProcedure(Object,
|
|
|
|
AssignSecurityDescriptor,
|
2006-12-29 22:17:29 +00:00
|
|
|
NULL,
|
2006-05-23 21:42:28 +00:00
|
|
|
NewDescriptor,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
2006-06-08 02:36:12 +00:00
|
|
|
PagedPool,
|
|
|
|
&Type->TypeInfo.GenericMapping);
|
2006-12-29 22:17:29 +00:00
|
|
|
ObpCalloutEnd(CalloutIrql, "Security", Type, Object);
|
|
|
|
|
|
|
|
/* Check for failure and deassign security if so */
|
|
|
|
if (!NT_SUCCESS(Status)) SeDeassignSecurity(&NewDescriptor);
|
2004-07-22 18:38:08 +00:00
|
|
|
|
2006-06-08 02:36:12 +00:00
|
|
|
/* Return to caller */
|
2006-05-23 21:42:28 +00:00
|
|
|
return Status;
|
2002-02-22 17:57:57 +00:00
|
|
|
}
|
|
|
|
|
2006-05-23 21:42:28 +00:00
|
|
|
/*++
|
|
|
|
* @name ObGetObjectSecurity
|
|
|
|
* @implemented NT4
|
|
|
|
*
|
|
|
|
* The ObGetObjectSecurity routine <FILLMEIN>
|
|
|
|
*
|
|
|
|
* @param Object
|
|
|
|
* <FILLMEIN>
|
|
|
|
*
|
|
|
|
* @param SecurityDescriptor
|
|
|
|
* <FILLMEIN>
|
|
|
|
*
|
|
|
|
* @param MemoryAllocated
|
|
|
|
* <FILLMEIN>
|
|
|
|
*
|
|
|
|
* @return STATUS_SUCCESS or appropriate error value.
|
|
|
|
*
|
|
|
|
* @remarks None.
|
|
|
|
*
|
|
|
|
*--*/
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
2002-02-22 17:57:57 +00:00
|
|
|
ObGetObjectSecurity(IN PVOID Object,
|
2006-05-23 21:42:28 +00:00
|
|
|
OUT PSECURITY_DESCRIPTOR *SecurityDescriptor,
|
|
|
|
OUT PBOOLEAN MemoryAllocated)
|
2002-02-22 17:57:57 +00:00
|
|
|
{
|
2006-05-24 20:13:47 +00:00
|
|
|
POBJECT_HEADER Header;
|
2006-06-08 02:36:12 +00:00
|
|
|
POBJECT_TYPE Type;
|
2006-12-29 22:17:29 +00:00
|
|
|
ULONG Length = 0;
|
2006-05-23 21:42:28 +00:00
|
|
|
NTSTATUS Status;
|
2006-12-29 22:17:29 +00:00
|
|
|
SECURITY_INFORMATION SecurityInformation;
|
|
|
|
KIRQL CalloutIrql;
|
2006-05-23 21:42:28 +00:00
|
|
|
PAGED_CODE();
|
2004-07-23 21:44:10 +00:00
|
|
|
|
2006-06-08 02:36:12 +00:00
|
|
|
/* Get the object header and type */
|
2006-05-25 20:14:09 +00:00
|
|
|
Header = OBJECT_TO_OBJECT_HEADER(Object);
|
2006-06-08 02:36:12 +00:00
|
|
|
Type = Header->Type;
|
2004-07-23 21:44:10 +00:00
|
|
|
|
2006-12-29 22:17:29 +00:00
|
|
|
/* Tell the caller that we didn't have to allocate anything yet */
|
|
|
|
*MemoryAllocated = FALSE;
|
|
|
|
|
2006-06-08 02:36:12 +00:00
|
|
|
/* Check if the object uses default security */
|
|
|
|
if (Type->TypeInfo.SecurityProcedure == SeDefaultObjectMethod)
|
2004-07-23 21:44:10 +00:00
|
|
|
{
|
2006-06-08 05:41:39 +00:00
|
|
|
/* Reference the descriptor */
|
2008-04-01 21:09:28 +00:00
|
|
|
*SecurityDescriptor = ObpReferenceSecurityDescriptor(Header);
|
2006-05-23 21:42:28 +00:00
|
|
|
return STATUS_SUCCESS;
|
2004-07-23 21:44:10 +00:00
|
|
|
}
|
|
|
|
|
2006-12-29 22:17:29 +00:00
|
|
|
/* Set mask to query */
|
|
|
|
SecurityInformation = OWNER_SECURITY_INFORMATION |
|
|
|
|
GROUP_SECURITY_INFORMATION |
|
|
|
|
DACL_SECURITY_INFORMATION |
|
|
|
|
SACL_SECURITY_INFORMATION;
|
|
|
|
|
2006-05-23 21:42:28 +00:00
|
|
|
/* Get the security descriptor size */
|
2006-12-29 22:17:29 +00:00
|
|
|
ObpCalloutStart(&CalloutIrql);
|
2006-06-08 02:36:12 +00:00
|
|
|
Status = Type->TypeInfo.SecurityProcedure(Object,
|
|
|
|
QuerySecurityDescriptor,
|
2006-12-29 22:17:29 +00:00
|
|
|
&SecurityInformation,
|
2006-06-08 05:41:39 +00:00
|
|
|
*SecurityDescriptor,
|
2006-06-08 02:36:12 +00:00
|
|
|
&Length,
|
|
|
|
&Header->SecurityDescriptor,
|
2006-06-08 05:41:39 +00:00
|
|
|
Type->TypeInfo.PoolType,
|
2006-06-08 02:36:12 +00:00
|
|
|
&Type->TypeInfo.GenericMapping);
|
2006-12-29 22:17:29 +00:00
|
|
|
ObpCalloutEnd(CalloutIrql, "Security", Type, Object);
|
|
|
|
|
|
|
|
/* Check for failure */
|
2006-05-23 21:42:28 +00:00
|
|
|
if (Status != STATUS_BUFFER_TOO_SMALL) return Status;
|
|
|
|
|
|
|
|
/* Allocate security descriptor */
|
2006-06-08 02:36:12 +00:00
|
|
|
*SecurityDescriptor = ExAllocatePoolWithTag(PagedPool,
|
|
|
|
Length,
|
2006-06-22 02:20:34 +00:00
|
|
|
TAG_SEC_QUERY);
|
2006-06-08 02:36:12 +00:00
|
|
|
if (!(*SecurityDescriptor)) return STATUS_INSUFFICIENT_RESOURCES;
|
2006-12-29 22:17:29 +00:00
|
|
|
*MemoryAllocated = TRUE;
|
2006-05-23 21:42:28 +00:00
|
|
|
|
|
|
|
/* Query security descriptor */
|
2006-12-29 22:17:29 +00:00
|
|
|
ObpCalloutStart(&CalloutIrql);
|
2006-06-08 02:36:12 +00:00
|
|
|
Status = Type->TypeInfo.SecurityProcedure(Object,
|
|
|
|
QuerySecurityDescriptor,
|
2006-12-29 22:17:29 +00:00
|
|
|
&SecurityInformation,
|
2006-06-08 02:36:12 +00:00
|
|
|
*SecurityDescriptor,
|
|
|
|
&Length,
|
|
|
|
&Header->SecurityDescriptor,
|
2006-06-08 05:41:39 +00:00
|
|
|
Type->TypeInfo.PoolType,
|
2006-06-08 02:36:12 +00:00
|
|
|
&Type->TypeInfo.GenericMapping);
|
2006-12-29 22:17:29 +00:00
|
|
|
ObpCalloutEnd(CalloutIrql, "Security", Type, Object);
|
|
|
|
|
|
|
|
/* Check for failure */
|
2006-05-23 21:42:28 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
2004-07-23 21:44:10 +00:00
|
|
|
{
|
2006-06-08 02:36:12 +00:00
|
|
|
/* Free the descriptor and tell the caller we failed */
|
2008-08-31 15:29:21 +00:00
|
|
|
ExFreePoolWithTag(*SecurityDescriptor, TAG_SEC_QUERY);
|
2006-06-08 02:36:12 +00:00
|
|
|
*MemoryAllocated = FALSE;
|
2004-07-23 21:44:10 +00:00
|
|
|
}
|
|
|
|
|
2006-06-08 02:36:12 +00:00
|
|
|
/* Return status */
|
|
|
|
return Status;
|
2002-02-22 17:57:57 +00:00
|
|
|
}
|
|
|
|
|
2006-05-23 21:42:28 +00:00
|
|
|
/*++
|
|
|
|
* @name ObReleaseObjectSecurity
|
|
|
|
* @implemented NT4
|
|
|
|
*
|
|
|
|
* The ObReleaseObjectSecurity routine <FILLMEIN>
|
|
|
|
*
|
|
|
|
* @param SecurityDescriptor
|
|
|
|
* <FILLMEIN>
|
|
|
|
*
|
|
|
|
* @param MemoryAllocated
|
|
|
|
* <FILLMEIN>
|
|
|
|
*
|
|
|
|
* @return STATUS_SUCCESS or appropriate error value.
|
|
|
|
*
|
|
|
|
* @remarks None.
|
|
|
|
*
|
|
|
|
*--*/
|
|
|
|
VOID
|
|
|
|
NTAPI
|
2002-02-22 17:57:57 +00:00
|
|
|
ObReleaseObjectSecurity(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
|
2006-05-23 21:42:28 +00:00
|
|
|
IN BOOLEAN MemoryAllocated)
|
2002-02-22 17:57:57 +00:00
|
|
|
{
|
2006-05-23 21:42:28 +00:00
|
|
|
PAGED_CODE();
|
2005-05-09 01:38:29 +00:00
|
|
|
|
2006-06-08 02:36:12 +00:00
|
|
|
/* Nothing to do in this case */
|
|
|
|
if (!SecurityDescriptor) return;
|
2004-07-23 21:44:10 +00:00
|
|
|
|
2006-06-08 02:36:12 +00:00
|
|
|
/* Check if we had allocated it from memory */
|
2006-05-23 21:42:28 +00:00
|
|
|
if (MemoryAllocated)
|
2004-07-23 21:44:10 +00:00
|
|
|
{
|
2006-06-08 02:36:12 +00:00
|
|
|
/* Free it */
|
2022-05-08 17:16:34 +00:00
|
|
|
ExFreePoolWithTag(SecurityDescriptor, TAG_SEC_QUERY);
|
2004-07-23 21:44:10 +00:00
|
|
|
}
|
2006-05-23 21:42:28 +00:00
|
|
|
else
|
2004-07-23 21:44:10 +00:00
|
|
|
{
|
2006-06-08 02:36:12 +00:00
|
|
|
/* Otherwise this means we used an internal descriptor */
|
2008-04-01 21:09:28 +00:00
|
|
|
ObDereferenceSecurityDescriptor(SecurityDescriptor, 1);
|
2004-07-23 21:44:10 +00:00
|
|
|
}
|
2002-02-22 17:57:57 +00:00
|
|
|
}
|
|
|
|
|
2006-12-29 22:17:29 +00:00
|
|
|
/*++
|
|
|
|
* @name ObSetSecurityObjectByPointer
|
|
|
|
* @implemented NT5.1
|
|
|
|
*
|
|
|
|
* The ObSetSecurityObjectByPointer routine <FILLMEIN>
|
|
|
|
*
|
|
|
|
* @param SecurityDescriptor
|
|
|
|
* <FILLMEIN>
|
|
|
|
*
|
|
|
|
* @param MemoryAllocated
|
|
|
|
* <FILLMEIN>
|
|
|
|
*
|
|
|
|
* @return STATUS_SUCCESS or appropriate error value.
|
|
|
|
*
|
|
|
|
* @remarks None.
|
|
|
|
*
|
|
|
|
*--*/
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
ObSetSecurityObjectByPointer(IN PVOID Object,
|
|
|
|
IN SECURITY_INFORMATION SecurityInformation,
|
|
|
|
IN PSECURITY_DESCRIPTOR SecurityDescriptor)
|
|
|
|
{
|
|
|
|
POBJECT_TYPE Type;
|
|
|
|
POBJECT_HEADER Header;
|
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
/* Get the header and type */
|
|
|
|
Header = OBJECT_TO_OBJECT_HEADER(Object);
|
|
|
|
Type = Header->Type;
|
|
|
|
|
|
|
|
/* Sanity check */
|
|
|
|
ASSERT(SecurityDescriptor);
|
|
|
|
|
|
|
|
/* Call the security procedure */
|
|
|
|
return Type->TypeInfo.SecurityProcedure(Object,
|
|
|
|
SetSecurityDescriptor,
|
|
|
|
&SecurityInformation,
|
|
|
|
SecurityDescriptor,
|
|
|
|
NULL,
|
|
|
|
&Header->SecurityDescriptor,
|
|
|
|
Type->TypeInfo.PoolType,
|
|
|
|
&Type->TypeInfo.GenericMapping);
|
|
|
|
}
|
|
|
|
|
2006-05-23 21:42:28 +00:00
|
|
|
/*++
|
|
|
|
* @name NtQuerySecurityObject
|
|
|
|
* @implemented NT4
|
|
|
|
*
|
|
|
|
* The NtQuerySecurityObject routine <FILLMEIN>
|
|
|
|
*
|
|
|
|
* @param Handle
|
|
|
|
* <FILLMEIN>
|
|
|
|
*
|
|
|
|
* @param SecurityInformation
|
|
|
|
* <FILLMEIN>
|
|
|
|
*
|
|
|
|
* @param SecurityDescriptor
|
|
|
|
* <FILLMEIN>
|
|
|
|
*
|
|
|
|
* @param Length
|
|
|
|
* <FILLMEIN>
|
|
|
|
*
|
|
|
|
* @param ResultLength
|
|
|
|
* <FILLMEIN>
|
|
|
|
*
|
|
|
|
* @return STATUS_SUCCESS or appropriate error value.
|
|
|
|
*
|
|
|
|
* @remarks None.
|
|
|
|
*
|
|
|
|
*--*/
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
2003-02-15 18:46:28 +00:00
|
|
|
NtQuerySecurityObject(IN HANDLE Handle,
|
2006-05-23 21:42:28 +00:00
|
|
|
IN SECURITY_INFORMATION SecurityInformation,
|
|
|
|
OUT PSECURITY_DESCRIPTOR SecurityDescriptor,
|
|
|
|
IN ULONG Length,
|
|
|
|
OUT PULONG ResultLength)
|
1999-12-26 15:50:53 +00:00
|
|
|
{
|
2006-05-23 21:42:28 +00:00
|
|
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
2005-12-30 01:41:02 +00:00
|
|
|
PVOID Object;
|
2006-05-24 20:13:47 +00:00
|
|
|
POBJECT_HEADER Header;
|
2006-06-22 02:20:34 +00:00
|
|
|
POBJECT_TYPE Type;
|
|
|
|
ACCESS_MASK DesiredAccess;
|
2009-08-26 17:31:02 +00:00
|
|
|
NTSTATUS Status;
|
2005-12-30 01:41:02 +00:00
|
|
|
PAGED_CODE();
|
2003-02-15 18:46:28 +00:00
|
|
|
|
2006-06-22 02:20:34 +00:00
|
|
|
/* Check if we came from user mode */
|
2005-12-30 01:41:02 +00:00
|
|
|
if (PreviousMode != KernelMode)
|
2003-02-15 18:46:28 +00:00
|
|
|
{
|
2006-06-22 02:20:34 +00:00
|
|
|
/* Enter SEH */
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_TRY
|
2005-12-30 01:41:02 +00:00
|
|
|
{
|
2006-06-22 02:20:34 +00:00
|
|
|
/* Probe the SD and the length pointer */
|
2006-05-23 21:42:28 +00:00
|
|
|
ProbeForWrite(SecurityDescriptor, Length, sizeof(ULONG));
|
2005-12-30 01:41:02 +00:00
|
|
|
ProbeForWriteUlong(ResultLength);
|
|
|
|
}
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
2005-12-30 01:41:02 +00:00
|
|
|
{
|
2009-08-26 17:31:02 +00:00
|
|
|
/* Return the exception code */
|
|
|
|
_SEH2_YIELD(return _SEH2_GetExceptionCode());
|
2005-12-30 01:41:02 +00:00
|
|
|
}
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_END;
|
2003-02-15 18:46:28 +00:00
|
|
|
}
|
|
|
|
|
2006-06-22 02:20:34 +00:00
|
|
|
/* Get the required access rights for the operation */
|
|
|
|
SeQuerySecurityAccessMask(SecurityInformation, &DesiredAccess);
|
2004-07-23 21:44:10 +00:00
|
|
|
|
2006-06-22 02:20:34 +00:00
|
|
|
/* Reference the object */
|
2005-12-30 01:41:02 +00:00
|
|
|
Status = ObReferenceObjectByHandle(Handle,
|
|
|
|
DesiredAccess,
|
|
|
|
NULL,
|
|
|
|
PreviousMode,
|
|
|
|
&Object,
|
|
|
|
NULL);
|
2006-06-22 02:20:34 +00:00
|
|
|
if (!NT_SUCCESS(Status)) return Status;
|
|
|
|
|
|
|
|
/* Get the Object Header and Type */
|
|
|
|
Header = OBJECT_TO_OBJECT_HEADER(Object);
|
|
|
|
Type = Header->Type;
|
|
|
|
|
|
|
|
/* Call the security procedure's query function */
|
|
|
|
Status = Type->TypeInfo.SecurityProcedure(Object,
|
|
|
|
QuerySecurityDescriptor,
|
2006-12-29 22:17:29 +00:00
|
|
|
&SecurityInformation,
|
2006-06-22 02:20:34 +00:00
|
|
|
SecurityDescriptor,
|
|
|
|
&Length,
|
|
|
|
&Header->SecurityDescriptor,
|
|
|
|
Type->TypeInfo.PoolType,
|
|
|
|
&Type->TypeInfo.GenericMapping);
|
|
|
|
|
|
|
|
/* Dereference the object */
|
|
|
|
ObDereferenceObject(Object);
|
2003-02-15 18:46:28 +00:00
|
|
|
|
2006-06-22 02:20:34 +00:00
|
|
|
/* Protect write with SEH */
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_TRY
|
2005-12-30 01:41:02 +00:00
|
|
|
{
|
2006-06-22 02:20:34 +00:00
|
|
|
/* Return the needed length */
|
|
|
|
*ResultLength = Length;
|
2005-12-30 01:41:02 +00:00
|
|
|
}
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_EXCEPT(ExSystemExceptionFilter())
|
2006-06-22 02:20:34 +00:00
|
|
|
{
|
|
|
|
/* Get the exception code */
|
2008-11-24 13:40:26 +00:00
|
|
|
Status = _SEH2_GetExceptionCode();
|
2006-05-24 02:48:51 +00:00
|
|
|
}
|
2008-11-24 13:40:26 +00:00
|
|
|
_SEH2_END;
|
2003-02-15 18:46:28 +00:00
|
|
|
|
2006-06-22 02:20:34 +00:00
|
|
|
/* Return status */
|
2005-12-30 01:41:02 +00:00
|
|
|
return Status;
|
1999-12-26 15:50:53 +00:00
|
|
|
}
|
|
|
|
|
2006-05-23 21:42:28 +00:00
|
|
|
/*++
|
|
|
|
* @name NtSetSecurityObject
|
|
|
|
* @implemented NT4
|
|
|
|
*
|
|
|
|
* The NtSetSecurityObject routine <FILLMEIN>
|
|
|
|
*
|
|
|
|
* @param Handle
|
|
|
|
* <FILLMEIN>
|
|
|
|
*
|
|
|
|
* @param SecurityInformation
|
|
|
|
* <FILLMEIN>
|
|
|
|
*
|
|
|
|
* @param SecurityDescriptor
|
|
|
|
* <FILLMEIN>
|
|
|
|
*
|
|
|
|
* @return STATUS_SUCCESS or appropriate error value.
|
|
|
|
*
|
|
|
|
* @remarks None.
|
|
|
|
*
|
|
|
|
*--*/
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
2002-02-22 13:36:24 +00:00
|
|
|
NtSetSecurityObject(IN HANDLE Handle,
|
2006-05-23 21:42:28 +00:00
|
|
|
IN SECURITY_INFORMATION SecurityInformation,
|
|
|
|
IN PSECURITY_DESCRIPTOR SecurityDescriptor)
|
1999-12-26 15:50:53 +00:00
|
|
|
{
|
2006-05-23 21:42:28 +00:00
|
|
|
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
2005-12-30 01:41:02 +00:00
|
|
|
PVOID Object;
|
2006-06-22 02:20:34 +00:00
|
|
|
SECURITY_DESCRIPTOR_RELATIVE *CapturedDescriptor;
|
2007-11-05 09:43:08 +00:00
|
|
|
ACCESS_MASK DesiredAccess = 0;
|
2005-12-30 01:41:02 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
PAGED_CODE();
|
2004-09-09 12:20:48 +00:00
|
|
|
|
2006-06-22 02:20:34 +00:00
|
|
|
/* Make sure the caller doesn't pass a NULL security descriptor! */
|
|
|
|
if (!SecurityDescriptor) return STATUS_ACCESS_VIOLATION;
|
2005-12-30 01:41:02 +00:00
|
|
|
|
2006-12-29 22:17:29 +00:00
|
|
|
/* Set the required access rights for the operation */
|
|
|
|
SeSetSecurityAccessMask(SecurityInformation, &DesiredAccess);
|
2004-07-25 12:39:28 +00:00
|
|
|
|
2006-12-29 22:17:29 +00:00
|
|
|
/* Reference the object */
|
|
|
|
Status = ObReferenceObjectByHandle(Handle,
|
|
|
|
DesiredAccess,
|
|
|
|
NULL,
|
|
|
|
PreviousMode,
|
|
|
|
&Object,
|
|
|
|
NULL);
|
|
|
|
if (NT_SUCCESS(Status))
|
2005-12-30 01:41:02 +00:00
|
|
|
{
|
2006-12-29 22:17:29 +00:00
|
|
|
/* Capture and make a copy of the security descriptor */
|
|
|
|
Status = SeCaptureSecurityDescriptor(SecurityDescriptor,
|
|
|
|
PreviousMode,
|
|
|
|
PagedPool,
|
|
|
|
TRUE,
|
|
|
|
(PSECURITY_DESCRIPTOR*)
|
|
|
|
&CapturedDescriptor);
|
|
|
|
if (!NT_SUCCESS(Status))
|
2005-12-30 01:41:02 +00:00
|
|
|
{
|
2006-12-29 22:17:29 +00:00
|
|
|
/* Fail */
|
2005-12-30 01:41:02 +00:00
|
|
|
ObDereferenceObject(Object);
|
2006-12-29 22:17:29 +00:00
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Sanity check */
|
|
|
|
ASSERT(CapturedDescriptor->Control & SE_SELF_RELATIVE);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Make sure the security descriptor passed by the caller
|
|
|
|
* is valid for the operation we're about to perform
|
|
|
|
*/
|
|
|
|
if (((SecurityInformation & OWNER_SECURITY_INFORMATION) &&
|
|
|
|
!(CapturedDescriptor->Owner)) ||
|
|
|
|
((SecurityInformation & GROUP_SECURITY_INFORMATION) &&
|
|
|
|
!(CapturedDescriptor->Group)))
|
|
|
|
{
|
|
|
|
/* Set the failure status */
|
|
|
|
Status = STATUS_INVALID_SECURITY_DESCR;
|
2005-12-30 01:41:02 +00:00
|
|
|
}
|
2006-12-29 22:17:29 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Set security */
|
|
|
|
Status = ObSetSecurityObjectByPointer(Object,
|
|
|
|
SecurityInformation,
|
|
|
|
CapturedDescriptor);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Release the descriptor and return status */
|
|
|
|
SeReleaseSecurityDescriptor((PSECURITY_DESCRIPTOR)CapturedDescriptor,
|
|
|
|
PreviousMode,
|
|
|
|
TRUE);
|
2007-09-09 11:09:56 +00:00
|
|
|
|
|
|
|
/* Now we can dereference the object */
|
|
|
|
ObDereferenceObject(Object);
|
2005-12-30 01:41:02 +00:00
|
|
|
}
|
2003-02-15 18:46:28 +00:00
|
|
|
|
2005-12-30 01:41:02 +00:00
|
|
|
return Status;
|
1999-12-26 15:50:53 +00:00
|
|
|
}
|
|
|
|
|
2006-06-05 06:31:42 +00:00
|
|
|
/*++
|
|
|
|
* @name ObQueryObjectAuditingByHandle
|
|
|
|
* @implemented NT5
|
|
|
|
*
|
|
|
|
* The ObDereferenceSecurityDescriptor routine <FILLMEIN>
|
|
|
|
*
|
|
|
|
* @param SecurityDescriptor
|
|
|
|
* <FILLMEIN>
|
|
|
|
*
|
|
|
|
* @param Count
|
|
|
|
* <FILLMEIN>
|
|
|
|
*
|
|
|
|
* @return STATUS_SUCCESS or appropriate error value.
|
|
|
|
*
|
|
|
|
* @remarks None.
|
|
|
|
*
|
|
|
|
*--*/
|
|
|
|
NTSTATUS
|
|
|
|
NTAPI
|
|
|
|
ObQueryObjectAuditingByHandle(IN HANDLE Handle,
|
|
|
|
OUT PBOOLEAN GenerateOnClose)
|
|
|
|
{
|
|
|
|
PHANDLE_TABLE_ENTRY HandleEntry;
|
|
|
|
PVOID HandleTable;
|
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
/* Check if we're dealing with a kernel handle */
|
2013-11-18 14:27:01 +00:00
|
|
|
if (ObpIsKernelHandle(Handle, ExGetPreviousMode()))
|
2006-06-05 06:31:42 +00:00
|
|
|
{
|
|
|
|
/* Use the kernel table and convert the handle */
|
|
|
|
HandleTable = ObpKernelHandleTable;
|
|
|
|
Handle = ObKernelHandleToHandle(Handle);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Use the process's handle table */
|
|
|
|
HandleTable = PsGetCurrentProcess()->ObjectTable;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Enter a critical region while we touch the handle table */
|
|
|
|
KeEnterCriticalRegion();
|
|
|
|
|
|
|
|
/* Map the handle */
|
|
|
|
HandleEntry = ExMapHandleToPointer(HandleTable, Handle);
|
|
|
|
if(HandleEntry)
|
|
|
|
{
|
|
|
|
/* Check if the flag is set */
|
2007-01-22 08:15:17 +00:00
|
|
|
*GenerateOnClose = HandleEntry->ObAttributes & OBJ_AUDIT_OBJECT_CLOSE;
|
2006-06-05 06:31:42 +00:00
|
|
|
|
|
|
|
/* Unlock the entry */
|
|
|
|
ExUnlockHandleTableEntry(HandleTable, HandleEntry);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Otherwise, fail */
|
|
|
|
Status = STATUS_INVALID_HANDLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Leave the critical region and return the status */
|
|
|
|
KeLeaveCriticalRegion();
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
2002-02-22 17:57:57 +00:00
|
|
|
/* EOF */
|