Author: pschweitzer
Date: Sun Dec 28 10:05:29 2014
New Revision: 65856
URL:
http://svn.reactos.org/svn/reactos?rev=65856&view=rev
Log:
[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
Modified:
trunk/reactos/ntoskrnl/io/iomgr/file.c
Modified: trunk/reactos/ntoskrnl/io/iomgr/file.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/file.c?r…
==============================================================================
--- trunk/reactos/ntoskrnl/io/iomgr/file.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/io/iomgr/file.c [iso-8859-1] Sun Dec 28 10:05:29 2014
@@ -14,6 +14,8 @@
#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
+
+extern ERESOURCE IopSecurityResource;
/* PRIVATE FUNCTIONS *********************************************************/
@@ -1308,6 +1310,174 @@
}
}
+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 @@
/* Return success */
return STATUS_SUCCESS;
}
- else
- {
- DPRINT1("FIXME: Set SD unimplemented for Devices\n");
+ else if (OperationCode == SetSecurityDescriptor)
+ {
+ /* 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)
{