[NTOSKRNL] Fix remaining access computation on open
[reactos.git] / ntoskrnl / io / iomgr / file.c
index 15504ad..1768bc2 100644 (file)
@@ -7,6 +7,7 @@
  *                  Gunnar Dalsnes
  *                  Eric Kohl
  *                  Filip Navara (navaraf@reactos.org)
+ *                  Pierre Schweitzer
  */
 
 /* INCLUDES *****************************************************************/
@@ -431,7 +432,7 @@ IopParseDevice(IN PVOID ParseObject,
                 {
                     /* Update access state */
                     AccessState->PreviouslyGrantedAccess |= GrantedAccess;
-                    AccessState->RemainingDesiredAccess &= ~(GrantedAccess &
+                    AccessState->RemainingDesiredAccess &= ~(GrantedAccess |
                                                              MAXIMUM_ALLOWED);
                     OpenPacket->Override= TRUE;
                 }
@@ -641,7 +642,70 @@ IopParseDevice(IN PVOID ParseObject,
             ((OpenPacket->RelatedFileObject) || (RemainingName->Length)) &&
             (!VolumeOpen))
         {
-            DPRINT("Fix Secure FSD support!!!\n");
+            Privileges = NULL;
+            GrantedAccess = 0;
+
+            KeEnterCriticalRegion();
+            ExAcquireResourceSharedLite(&IopSecurityResource, TRUE);
+
+            /* Lock the subject context */
+            SeLockSubjectContext(&AccessState->SubjectSecurityContext);
+
+            /* Do access check */
+            AccessGranted = SeAccessCheck(OriginalDeviceObject->SecurityDescriptor,
+                                          &AccessState->SubjectSecurityContext,
+                                          TRUE,
+                                          DesiredAccess,
+                                          0,
+                                          &Privileges,
+                                          &IoFileObjectType->TypeInfo.GenericMapping,
+                                          UserMode,
+                                          &GrantedAccess,
+                                          &Status);
+            if (Privileges != NULL)
+            {
+                /* Append and free the privileges */
+                SeAppendPrivileges(AccessState, Privileges);
+                SeFreePrivileges(Privileges);
+            }
+
+            /* Check if we got access */
+            if (GrantedAccess)
+            {
+                AccessState->PreviouslyGrantedAccess |= GrantedAccess;
+                AccessState->RemainingDesiredAccess &= ~(GrantedAccess | MAXIMUM_ALLOWED);
+            }
+
+            FileString.Length = 8;
+            FileString.MaximumLength = 8;
+            FileString.Buffer = L"File";
+
+            /* Do Audit/Alarm for open operation
+             * NOTA: we audit target device object
+             */
+            SeOpenObjectAuditAlarm(&FileString,
+                                   DeviceObject,
+                                   CompleteName,
+                                   OriginalDeviceObject->SecurityDescriptor,
+                                   AccessState,
+                                   FALSE,
+                                   AccessGranted,
+                                   UserMode,
+                                   &AccessState->GenerateOnClose);
+
+            SeUnlockSubjectContext(&AccessState->SubjectSecurityContext);
+
+            ExReleaseResourceLite(&IopSecurityResource);
+            KeLeaveCriticalRegion();
+
+            /* Check if access failed */
+            if (!AccessGranted)
+            {
+                /* Dereference the device and fail */
+                IopDereferenceDeviceObject(OriginalDeviceObject, FALSE);
+                if (Vpb) IopDereferenceVpbAndFree(Vpb);
+                return STATUS_ACCESS_DENIED;
+            }
         }
 
         /* Allocate the IRP */
@@ -1938,6 +2002,7 @@ IopCloseFile(IN PEPROCESS Process OPTIONAL,
     NTSTATUS Status;
     PDEVICE_OBJECT DeviceObject;
     KIRQL OldIrql;
+    IO_STATUS_BLOCK IoStatusBlock;
     IOTRACE(IO_FILE_DEBUG, "ObjectBody: %p\n", ObjectBody);
 
     /* If this isn't the last handle for the current process, quit */
@@ -1946,8 +2011,71 @@ IopCloseFile(IN PEPROCESS Process OPTIONAL,
     /* Check if the file is locked and has more then one handle opened */
     if ((FileObject->LockOperation) && (SystemHandleCount != 1))
     {
-        DPRINT1("We need to unlock this file!\n");
-        ASSERT(FALSE);
+        /* Check if this is a direct open or not */
+        if (BooleanFlagOn(FileObject->Flags, FO_DIRECT_DEVICE_OPEN))
+        {
+            /* Get the attached device */
+            DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
+        }
+        else
+        {
+            /* Get the FO's device */
+            DeviceObject = IoGetRelatedDeviceObject(FileObject);
+        }
+
+        /* Check if this is a sync FO and lock it */
+        if (BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO))
+        {
+            IopLockFileObject(FileObject);
+        }
+
+        /* Go the FastIO path if possible, otherwise fall back to IRP */
+        if (DeviceObject->DriverObject->FastIoDispatch == NULL ||
+            DeviceObject->DriverObject->FastIoDispatch->FastIoUnlockAll == NULL ||
+            !DeviceObject->DriverObject->FastIoDispatch->FastIoUnlockAll(FileObject, PsGetCurrentProcess(), &IoStatusBlock, DeviceObject))
+        {
+            /* Clear and set up Events */
+            KeClearEvent(&FileObject->Event);
+            KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
+
+            /* Allocate an IRP */
+            Irp = IopAllocateIrpMustSucceed(DeviceObject->StackSize);
+
+            /* Set it up */
+            Irp->UserEvent = &Event;
+            Irp->UserIosb = &Irp->IoStatus;
+            Irp->Tail.Overlay.Thread = PsGetCurrentThread();
+            Irp->Tail.Overlay.OriginalFileObject = FileObject;
+            Irp->RequestorMode = KernelMode;
+            Irp->Flags = IRP_SYNCHRONOUS_API;
+            Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;
+            ObReferenceObject(FileObject);
+
+            /* Set up Stack Pointer Data */
+            StackPtr = IoGetNextIrpStackLocation(Irp);
+            StackPtr->MajorFunction = IRP_MJ_LOCK_CONTROL;
+            StackPtr->MinorFunction = IRP_MN_UNLOCK_ALL;
+            StackPtr->FileObject = FileObject;
+
+            /* Queue the IRP */
+            IopQueueIrpToThread(Irp);
+
+            /* Call the FS Driver */
+            Status = IoCallDriver(DeviceObject, Irp);
+            if (Status == STATUS_PENDING)
+            {
+                /* Wait for completion */
+                KeWaitForSingleObject(&Event, UserRequest, KernelMode, FALSE, NULL);
+            }
+
+            /* IO will unqueue & free for us */
+        }
+
+        /* Release the lock if we were holding it */
+        if (BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO))
+        {
+            IopUnlockFileObject(FileObject);
+        }
     }
 
     /* Make sure this is the last handle */
@@ -1969,7 +2097,11 @@ IopCloseFile(IN PEPROCESS Process OPTIONAL,
     FileObject->Flags |= FO_HANDLE_CREATED;
 
     /* Check if this is a sync FO and lock it */
-    if (FileObject->Flags & FO_SYNCHRONOUS_IO) IopLockFileObject(FileObject);
+    if (Process != NULL &&
+        BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO))
+    {
+        IopLockFileObject(FileObject);
+    }
 
     /* Clear and set up Events */
     KeClearEvent(&FileObject->Event);
@@ -2014,7 +2146,11 @@ IopCloseFile(IN PEPROCESS Process OPTIONAL,
     IoFreeIrp(Irp);
 
     /* Release the lock if we were holding it */
-    if (FileObject->Flags & FO_SYNCHRONOUS_IO) IopUnlockFileObject(FileObject);
+    if (Process != NULL &&
+        BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO))
+    {
+        IopUnlockFileObject(FileObject);
+    }
 }
 
 NTSTATUS