"Fossies" - the Fresh Open Source Software Archive

Member "src/Driver/VolumeFilter.c" (10 Oct 2018, 9699 Bytes) of package /windows/misc/VeraCrypt_1.23-Hotfix-2_Source.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "VolumeFilter.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  Derived from source code of TrueCrypt 7.1a, which is
    3  Copyright (c) 2008-2012 TrueCrypt Developers Association and which is governed
    4  by the TrueCrypt License 3.0.
    5 
    6  Modifications and additions to the original source code (contained in this file)
    7  and all other portions of this file are Copyright (c) 2013-2017 IDRIX
    8  and are governed by the Apache License 2.0 the full text of which is
    9  contained in the file License.txt included in VeraCrypt binary and source
   10  code distribution packages.
   11 */
   12 
   13 #include "TCdefs.h"
   14 #include "Ntdriver.h"
   15 #include "Ntvol.h"
   16 #include "DriveFilter.h"
   17 #include "VolumeFilter.h"
   18 
   19 typedef DriveFilterExtension VolumeFilterExtension;
   20 
   21 // Number of times the filter driver answered that an unencrypted volume
   22 // is read-only (or mounted an outer/normal TrueCrypt volume as read only)
   23 uint32 HiddenSysLeakProtectionCount = 0;
   24 
   25 
   26 NTSTATUS VolumeFilterAddDevice (PDRIVER_OBJECT driverObject, PDEVICE_OBJECT pdo)
   27 {
   28     VolumeFilterExtension *Extension;
   29     NTSTATUS status;
   30     PDEVICE_OBJECT filterDeviceObject = NULL;
   31     PDEVICE_OBJECT attachedDeviceObject;
   32 
   33     Dump ("VolumeFilterAddDevice pdo=%p\n", pdo);
   34 
   35     attachedDeviceObject = IoGetAttachedDeviceReference (pdo);
   36     status = IoCreateDevice (driverObject, sizeof (VolumeFilterExtension), NULL, attachedDeviceObject->DeviceType, 0, FALSE, &filterDeviceObject);
   37 
   38     ObDereferenceObject (attachedDeviceObject);
   39 
   40     if (!NT_SUCCESS (status))
   41     {
   42         filterDeviceObject = NULL;
   43         goto err;
   44     }
   45 
   46     Extension = (VolumeFilterExtension *) filterDeviceObject->DeviceExtension;
   47     memset (Extension, 0, sizeof (VolumeFilterExtension));
   48 
   49     status = IoAttachDeviceToDeviceStackSafe (filterDeviceObject, pdo, &(Extension->LowerDeviceObject));
   50     if (status != STATUS_SUCCESS)
   51     {
   52         goto err;
   53     }
   54 
   55     if (!Extension->LowerDeviceObject)
   56     {
   57         status = STATUS_DEVICE_REMOVED;
   58         goto err;
   59     }
   60 
   61     Extension->IsVolumeFilterDevice = TRUE;
   62     Extension->DeviceObject = filterDeviceObject;
   63     Extension->Pdo = pdo;
   64 
   65     IoInitializeRemoveLock (&Extension->Queue.RemoveLock, 'LRCV', 0, 0);
   66 
   67     filterDeviceObject->Flags |= Extension->LowerDeviceObject->Flags & (DO_DIRECT_IO | DO_BUFFERED_IO | DO_POWER_PAGABLE);
   68     filterDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
   69 
   70     return status;
   71 
   72 err:
   73     if (filterDeviceObject)
   74     {
   75         if (Extension->LowerDeviceObject)
   76             IoDetachDevice (Extension->LowerDeviceObject);
   77 
   78         IoDeleteDevice (filterDeviceObject);
   79     }
   80 
   81     return status;
   82 }
   83 
   84 
   85 static NTSTATUS PassIrp (PDEVICE_OBJECT deviceObject, PIRP irp)
   86 {
   87     IoSkipCurrentIrpStackLocation (irp);
   88     return IoCallDriver (deviceObject, irp);
   89 }
   90 
   91 
   92 static NTSTATUS PassFilteredIrp (PDEVICE_OBJECT deviceObject, PIRP irp, PIO_COMPLETION_ROUTINE completionRoutine, PVOID completionRoutineArg)
   93 {
   94     IoCopyCurrentIrpStackLocationToNext (irp);
   95 
   96     if (completionRoutine)
   97         IoSetCompletionRoutine (irp, completionRoutine, completionRoutineArg, TRUE, TRUE, TRUE);
   98 
   99     return IoCallDriver (deviceObject, irp);
  100 }
  101 
  102 
  103 static NTSTATUS OnDeviceUsageNotificationCompleted (PDEVICE_OBJECT filterDeviceObject, PIRP Irp, VolumeFilterExtension *Extension)
  104 {
  105     if (Irp->PendingReturned)
  106         IoMarkIrpPending (Irp);
  107 
  108     if (!(Extension->LowerDeviceObject->Flags & DO_POWER_PAGABLE))
  109         filterDeviceObject->Flags &= ~DO_POWER_PAGABLE;
  110 
  111     IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp);
  112     return STATUS_CONTINUE_COMPLETION;
  113 }
  114 
  115 
  116 static NTSTATUS OnStartDeviceCompleted (PDEVICE_OBJECT filterDeviceObject, PIRP Irp, VolumeFilterExtension *Extension)
  117 {
  118     if (Irp->PendingReturned)
  119         IoMarkIrpPending (Irp);
  120 
  121     if (Extension->LowerDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
  122         filterDeviceObject->Characteristics |= FILE_REMOVABLE_MEDIA;
  123 
  124     IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp);
  125     return STATUS_CONTINUE_COMPLETION;
  126 }
  127 
  128 
  129 static NTSTATUS DispatchControl (PDEVICE_OBJECT DeviceObject, PIRP Irp, VolumeFilterExtension *Extension, PIO_STACK_LOCATION irpSp)
  130 {
  131     NTSTATUS status = IoAcquireRemoveLock (&Extension->Queue.RemoveLock, Irp);
  132     if (!NT_SUCCESS (status))
  133         return TCCompleteIrp (Irp, status, 0);
  134 
  135     if (IsHiddenSystemRunning())
  136     {
  137         switch (irpSp->Parameters.DeviceIoControl.IoControlCode)
  138         {
  139         case IOCTL_DISK_IS_WRITABLE:
  140             {
  141                 // All volumes except the system volume must be read-only
  142 
  143                 DriveFilterExtension *bootDriveExtension = GetBootDriveFilterExtension();
  144                 STORAGE_DEVICE_NUMBER storageDeviceNumber;
  145 
  146                 if (!bootDriveExtension->SystemStorageDeviceNumberValid)
  147                     TC_BUG_CHECK (STATUS_INVALID_PARAMETER);
  148 
  149                 status = SendDeviceIoControlRequest (Extension->LowerDeviceObject, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &storageDeviceNumber, sizeof (storageDeviceNumber));
  150 
  151                 if (NT_SUCCESS (status) && bootDriveExtension->SystemStorageDeviceNumber == storageDeviceNumber.DeviceNumber)
  152                 {
  153                     PARTITION_INFORMATION_EX partition;
  154                     status = SendDeviceIoControlRequest (Extension->LowerDeviceObject, IOCTL_DISK_GET_PARTITION_INFO_EX, NULL, 0, &partition, sizeof (partition));
  155 
  156                     if (NT_SUCCESS (status) && partition.StartingOffset.QuadPart == bootDriveExtension->ConfiguredEncryptedAreaStart)
  157                     {
  158                         IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp);
  159                         return TCCompleteDiskIrp (Irp, STATUS_SUCCESS, 0);
  160                     }
  161                 }
  162 
  163                 IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp);
  164 
  165                 ++HiddenSysLeakProtectionCount;
  166                 return TCCompleteDiskIrp (Irp, STATUS_MEDIA_WRITE_PROTECTED, 0);
  167             }
  168 
  169         case TC_IOCTL_DISK_IS_WRITABLE:
  170             Dump ("TC_IOCTL_DISK_IS_WRITABLE pdo=%p\n", Extension->Pdo);
  171 
  172             if (!ProbingHostDeviceForWrite)
  173                 break;
  174 
  175             // Probe the real state of the device as the user is mounting a TrueCrypt volume.
  176 
  177             // Volume filter may be attached to a merged drive+volume PDO. First test if TC_IOCTL_DISK_IS_WRITABLE works for the underlying device.
  178             status = SendDeviceIoControlRequest (Extension->LowerDeviceObject, TC_IOCTL_DISK_IS_WRITABLE, NULL, 0, NULL, 0);
  179 
  180             if (NT_SUCCESS (status) || status == STATUS_MEDIA_WRITE_PROTECTED)
  181             {
  182                 IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp);
  183                 return TCCompleteDiskIrp (Irp, status, 0);
  184             }
  185 
  186             status = SendDeviceIoControlRequest (Extension->LowerDeviceObject, IOCTL_DISK_IS_WRITABLE, NULL, 0, NULL, 0);
  187 
  188             IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp);
  189             return TCCompleteDiskIrp (Irp, status, 0);
  190 
  191         case IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES:
  192 
  193             // Filter IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES to enable potential future use of hidden systems on drives that use the trim operation but not wear-leveling (if any appear in future). The documentation forbids users to create hidden volumes/systems on drives that use wear-leveling and consequently also on drives that use trim (as trim is used only by drives that use wear-leveling, as of 2010).
  194 
  195             IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp);
  196             return TCCompleteDiskIrp (Irp, STATUS_SUCCESS, 0);
  197         }
  198     }
  199 
  200     status = PassIrp (Extension->LowerDeviceObject, Irp);
  201     IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp);
  202     return status;
  203 }
  204 
  205 
  206 static NTSTATUS DispatchPnp (PDEVICE_OBJECT DeviceObject, PIRP Irp, VolumeFilterExtension *Extension, PIO_STACK_LOCATION irpSp)
  207 {
  208     NTSTATUS status;
  209 
  210     status = IoAcquireRemoveLock (&Extension->Queue.RemoveLock, Irp);
  211     if (!NT_SUCCESS (status))
  212         return TCCompleteIrp (Irp, status, 0);
  213 
  214     switch (irpSp->MinorFunction)
  215     {
  216     case IRP_MN_START_DEVICE:
  217         Dump ("IRP_MN_START_DEVICE volume pdo=%p\n", Extension->Pdo);
  218         return PassFilteredIrp (Extension->LowerDeviceObject, Irp, OnStartDeviceCompleted, Extension);
  219 
  220     case IRP_MN_DEVICE_USAGE_NOTIFICATION:
  221         {
  222             PDEVICE_OBJECT attachedDevice = IoGetAttachedDeviceReference (DeviceObject);
  223 
  224             if (attachedDevice == DeviceObject || (attachedDevice->Flags & DO_POWER_PAGABLE))
  225                 DeviceObject->Flags |= DO_POWER_PAGABLE;
  226 
  227             ObDereferenceObject (attachedDevice);
  228         }
  229 
  230         return PassFilteredIrp (Extension->LowerDeviceObject, Irp, OnDeviceUsageNotificationCompleted, Extension);
  231 
  232 
  233     case IRP_MN_REMOVE_DEVICE:
  234         Dump ("IRP_MN_REMOVE_DEVICE volume pdo=%p\n", Extension->Pdo);
  235 
  236         IoReleaseRemoveLockAndWait (&Extension->Queue.RemoveLock, Irp);
  237         status = PassIrp (Extension->LowerDeviceObject, Irp);
  238 
  239         IoDetachDevice (Extension->LowerDeviceObject);
  240 
  241         IoDeleteDevice (DeviceObject);
  242         return status;
  243 
  244     default:
  245         status = PassIrp (Extension->LowerDeviceObject, Irp);
  246         IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp);
  247     }
  248 
  249     return status;
  250 }
  251 
  252 
  253 static NTSTATUS DispatchPower (PDEVICE_OBJECT DeviceObject, PIRP Irp, VolumeFilterExtension *Extension, PIO_STACK_LOCATION irpSp)
  254 {
  255     NTSTATUS status;
  256     PoStartNextPowerIrp (Irp);
  257 
  258     status = IoAcquireRemoveLock (&Extension->Queue.RemoveLock, Irp);
  259     if (!NT_SUCCESS (status))
  260         return TCCompleteIrp (Irp, status, 0);
  261 
  262     IoSkipCurrentIrpStackLocation (Irp);
  263     status = PoCallDriver (Extension->LowerDeviceObject, Irp);
  264 
  265     IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp);
  266     return status;
  267 }
  268 
  269 
  270 NTSTATUS VolumeFilterDispatchIrp (PDEVICE_OBJECT DeviceObject, PIRP Irp)
  271 {
  272     VolumeFilterExtension *Extension = (VolumeFilterExtension *) DeviceObject->DeviceExtension;
  273     PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp);
  274     NTSTATUS status;
  275 
  276     ASSERT (!Extension->bRootDevice && Extension->IsVolumeFilterDevice);
  277 
  278     switch (irpSp->MajorFunction)
  279     {
  280     case IRP_MJ_DEVICE_CONTROL:
  281         return DispatchControl (DeviceObject, Irp, Extension, irpSp);
  282 
  283     case IRP_MJ_PNP:
  284         return DispatchPnp (DeviceObject, Irp, Extension, irpSp);
  285 
  286     case IRP_MJ_POWER:
  287         return DispatchPower (DeviceObject, Irp, Extension, irpSp);
  288 
  289     default:
  290         status = IoAcquireRemoveLock (&Extension->Queue.RemoveLock, Irp);
  291         if (!NT_SUCCESS (status))
  292             return TCCompleteIrp (Irp, status, 0);
  293 
  294         status = PassIrp (Extension->LowerDeviceObject, Irp);
  295 
  296         IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp);
  297         return status;
  298     }
  299 }