mirror of
https://github.com/reactos/reactos.git
synced 2024-07-04 19:54:58 +00:00
[NTOSKRNL]
- Implement IopGetDeviceAttachmentBase() which allows getting the base device of the device stack given any device object in it - Implement IopGetDevicePDO() which returns the physical device object of the device stack given any device object in it - Implement IopSetDeviceSecurityDescriptor() which will swap the old security descriptor of a device object with a new provided one - Implement IopSetDeviceSecurityDescriptors() which will swap the old security descriptor with a new provided one in all the device objects from the lowest provided to the uppest provided one. - Fix a fixme in IopGetSetSecurityObject(), the operation SetSecurityDescriptor is now fully implemented for both PDO & DO. This is required by VMware driver vmci.sys. Even though, the installation doesn't get any better; it just changes the BSOD, we now face a memory corruption (in SE). CORE-7991 svn path=/trunk/; revision=65856
This commit is contained in:
parent
cdc15f3bc5
commit
ecb6067cf0
|
@ -15,6 +15,8 @@
|
|||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
extern ERESOURCE IopSecurityResource;
|
||||
|
||||
/* PRIVATE FUNCTIONS *********************************************************/
|
||||
|
||||
VOID
|
||||
|
@ -1308,6 +1310,174 @@ IopDeleteFile(IN PVOID ObjectBody)
|
|||
}
|
||||
}
|
||||
|
||||
PDEVICE_OBJECT
|
||||
NTAPI
|
||||
IopGetDeviceAttachmentBase(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
PDEVICE_OBJECT PDO = DeviceObject;
|
||||
|
||||
/* Go down the stack to attempt to get the PDO */
|
||||
for (; ((PEXTENDED_DEVOBJ_EXTENSION)PDO->DeviceObjectExtension)->AttachedTo != NULL;
|
||||
PDO = ((PEXTENDED_DEVOBJ_EXTENSION)PDO->DeviceObjectExtension)->AttachedTo);
|
||||
|
||||
return PDO;
|
||||
}
|
||||
|
||||
PDEVICE_OBJECT
|
||||
NTAPI
|
||||
IopGetDevicePDO(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
PDEVICE_OBJECT PDO;
|
||||
|
||||
ASSERT(DeviceObject != NULL);
|
||||
|
||||
OldIrql = KeAcquireQueuedSpinLock(LockQueueIoDatabaseLock);
|
||||
/* Get the base DO */
|
||||
PDO = IopGetDeviceAttachmentBase(DeviceObject);
|
||||
/* Check whether that's really a PDO and if so, keep it */
|
||||
if ((PDO->Flags & DO_BUS_ENUMERATED_DEVICE) != DO_BUS_ENUMERATED_DEVICE)
|
||||
{
|
||||
PDO = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
ObReferenceObject(PDO);
|
||||
}
|
||||
KeReleaseQueuedSpinLock(LockQueueIoDatabaseLock, OldIrql);
|
||||
|
||||
return PDO;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IopSetDeviceSecurityDescriptor(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PSECURITY_INFORMATION SecurityInformation,
|
||||
IN PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||
IN POOL_TYPE PoolType,
|
||||
IN PGENERIC_MAPPING GenericMapping)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PSECURITY_DESCRIPTOR OldSecurityDescriptor, CachedSecurityDescriptor, NewSecurityDescriptor;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
/* Keep attempting till we find our old SD or fail */
|
||||
while (TRUE)
|
||||
{
|
||||
KeEnterCriticalRegion();
|
||||
ExAcquireResourceSharedLite(&IopSecurityResource, TRUE);
|
||||
|
||||
/* Get our old SD and reference it */
|
||||
OldSecurityDescriptor = DeviceObject->SecurityDescriptor;
|
||||
if (OldSecurityDescriptor != NULL)
|
||||
{
|
||||
ObReferenceSecurityDescriptor(OldSecurityDescriptor, 1);
|
||||
}
|
||||
|
||||
ExReleaseResourceLite(&IopSecurityResource);
|
||||
KeLeaveCriticalRegion();
|
||||
|
||||
/* Set the SD information */
|
||||
NewSecurityDescriptor = OldSecurityDescriptor;
|
||||
Status = SeSetSecurityDescriptorInfo(NULL, SecurityInformation,
|
||||
SecurityDescriptor, &NewSecurityDescriptor,
|
||||
PoolType, GenericMapping);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
if (OldSecurityDescriptor != NULL)
|
||||
{
|
||||
ObDereferenceSecurityDescriptor(OldSecurityDescriptor, 1);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Add the new DS to the internal cache */
|
||||
Status = ObLogSecurityDescriptor(NewSecurityDescriptor,
|
||||
&CachedSecurityDescriptor, 1);
|
||||
ExFreePool(NewSecurityDescriptor);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ObDereferenceSecurityDescriptor(OldSecurityDescriptor, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
KeEnterCriticalRegion();
|
||||
ExAcquireResourceSharedLite(&IopSecurityResource, TRUE);
|
||||
/* Check if someone changed it in our back */
|
||||
if (DeviceObject->SecurityDescriptor == OldSecurityDescriptor)
|
||||
{
|
||||
/* We're clear, do the swap */
|
||||
DeviceObject->SecurityDescriptor = CachedSecurityDescriptor;
|
||||
ExReleaseResourceLite(&IopSecurityResource);
|
||||
KeLeaveCriticalRegion();
|
||||
|
||||
/* And dereference old SD (twice - us + not in use) */
|
||||
ObDereferenceSecurityDescriptor(OldSecurityDescriptor, 2);
|
||||
|
||||
break;
|
||||
}
|
||||
ExReleaseResourceLite(&IopSecurityResource);
|
||||
KeLeaveCriticalRegion();
|
||||
|
||||
/* If so, try again */
|
||||
ObDereferenceSecurityDescriptor(OldSecurityDescriptor, 1);
|
||||
ObDereferenceSecurityDescriptor(CachedSecurityDescriptor, 1);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IopSetDeviceSecurityDescriptors(IN PDEVICE_OBJECT UpperDeviceObject,
|
||||
IN PDEVICE_OBJECT PhysicalDeviceObject,
|
||||
IN PSECURITY_INFORMATION SecurityInformation,
|
||||
IN PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||
IN POOL_TYPE PoolType,
|
||||
IN PGENERIC_MAPPING GenericMapping)
|
||||
{
|
||||
PDEVICE_OBJECT CurrentDO = PhysicalDeviceObject, NextDevice;
|
||||
NTSTATUS Status = STATUS_SUCCESS, TmpStatus;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
ASSERT(PhysicalDeviceObject != NULL);
|
||||
|
||||
/* We always reference the DO we're working on */
|
||||
ObReferenceObject(CurrentDO);
|
||||
|
||||
/* Go up from PDO to latest DO */
|
||||
do
|
||||
{
|
||||
/* Attempt to set the new SD on it */
|
||||
TmpStatus = IopSetDeviceSecurityDescriptor(CurrentDO, SecurityInformation,
|
||||
SecurityDescriptor, PoolType,
|
||||
GenericMapping);
|
||||
/* Was our last one? Remember that status then */
|
||||
if (CurrentDO == UpperDeviceObject)
|
||||
{
|
||||
Status = TmpStatus;
|
||||
}
|
||||
|
||||
/* Try to move to the next DO (and thus, reference it) */
|
||||
NextDevice = CurrentDO->AttachedDevice;
|
||||
if (NextDevice)
|
||||
{
|
||||
ObReferenceObject(NextDevice);
|
||||
}
|
||||
|
||||
/* Dereference current DO and move to the next one */
|
||||
ObDereferenceObject(CurrentDO);
|
||||
CurrentDO = NextDevice;
|
||||
}
|
||||
while (CurrentDO != NULL);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IopGetSetSecurityObject(IN PVOID ObjectBody,
|
||||
|
@ -1385,11 +1555,34 @@ IopGetSetSecurityObject(IN PVOID ObjectBody,
|
|||
/* Return success */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
else if (OperationCode == SetSecurityDescriptor)
|
||||
{
|
||||
DPRINT1("FIXME: Set SD unimplemented for Devices\n");
|
||||
/* Get the Physical Device Object if any */
|
||||
PDEVICE_OBJECT PDO = IopGetDevicePDO(DeviceObject);
|
||||
|
||||
if (PDO != NULL)
|
||||
{
|
||||
/* Apply the new SD to any DO in the path from PDO to current DO */
|
||||
Status = IopSetDeviceSecurityDescriptors(DeviceObject, PDO,
|
||||
SecurityInformation,
|
||||
SecurityDescriptor,
|
||||
PoolType, GenericMapping);
|
||||
ObDereferenceObject(PDO);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise, just set for ourselves */
|
||||
Status = IopSetDeviceSecurityDescriptor(DeviceObject,
|
||||
SecurityInformation,
|
||||
SecurityDescriptor,
|
||||
PoolType, GenericMapping);
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* Shouldn't happen */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else if (OperationCode == DeleteSecurityDescriptor)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue