@@ -463,6 +463,113 @@ static BOOL CheckStringLength (const wchar_t* str, size_t cchSize, size_t minLen
463463 return TRUE;
464464}
465465
466+
467+ /* Exact object-manager path grammars accepted from user mode by metadata IOCTLs. */
468+ static BOOL ConsumePathLiteral (const wchar_t * * path , const wchar_t * literal )
469+ {
470+ const wchar_t * current = * path ;
471+
472+ while (* literal )
473+ {
474+ if (!* current || UpperCaseUnicodeChar (* current ) != UpperCaseUnicodeChar (* literal ))
475+ return FALSE;
476+
477+ ++ current ;
478+ ++ literal ;
479+ }
480+
481+ * path = current ;
482+ return TRUE;
483+ }
484+
485+
486+ static BOOL ConsumeDecimalNumber (const wchar_t * * path , ULONG * value )
487+ {
488+ const wchar_t * current = * path ;
489+ ULONG number = 0 ;
490+
491+ if (* current < L'0' || * current > L'9' )
492+ return FALSE;
493+
494+ do
495+ {
496+ ULONG digit = (ULONG ) (* current - L'0' );
497+
498+ if (number > (MAXULONG - digit ) / 10 )
499+ return FALSE;
500+
501+ number = number * 10 + digit ;
502+ ++ current ;
503+ } while (* current >= L'0' && * current <= L'9' );
504+
505+ * path = current ;
506+ if (value )
507+ * value = number ;
508+
509+ return TRUE;
510+ }
511+
512+
513+ static BOOL IsHarddiskPartitionPath (const wchar_t * path , BOOL partitionZeroOnly )
514+ {
515+ const wchar_t * current = path ;
516+ ULONG partitionNumber ;
517+
518+ if (!path
519+ || !ConsumePathLiteral (& current , L"\\Device\\Harddisk" )
520+ || !ConsumeDecimalNumber (& current , NULL )
521+ || !ConsumePathLiteral (& current , L"\\Partition" )
522+ || !ConsumeDecimalNumber (& current , & partitionNumber )
523+ || * current != 0 )
524+ {
525+ return FALSE;
526+ }
527+
528+ return !partitionZeroOnly || partitionNumber == 0 ;
529+ }
530+
531+
532+ static BOOL IsHarddiskVolumePath (const wchar_t * path )
533+ {
534+ const wchar_t * current = path ;
535+
536+ return path
537+ && ConsumePathLiteral (& current , L"\\Device\\HarddiskVolume" )
538+ && ConsumeDecimalNumber (& current , NULL )
539+ && * current == 0 ;
540+ }
541+
542+
543+ static BOOL IsDriveLetterSymbolicLinkPath (const wchar_t * path )
544+ {
545+ const wchar_t * current = path ;
546+
547+ if (!path )
548+ return FALSE;
549+
550+ if (!ConsumePathLiteral (& current , L"\\DosDevices\\" ))
551+ {
552+ current = path ;
553+ if (!ConsumePathLiteral (& current , L"\\??\\" ))
554+ return FALSE;
555+ }
556+
557+ return ((current [0 ] >= L'A' && current [0 ] <= L'Z' )
558+ || (current [0 ] >= L'a' && current [0 ] <= L'z' ))
559+ && current [1 ] == L':'
560+ && current [2 ] == 0 ;
561+ }
562+
563+
564+ static BOOL IsAllowedDevicePathForMetadata (const wchar_t * path , BOOL symbolicLink )
565+ {
566+ if (IsHarddiskPartitionPath (path , FALSE))
567+ return TRUE;
568+
569+ return symbolicLink ? IsDriveLetterSymbolicLinkPath (path ) : IsHarddiskVolumePath (path );
570+ }
571+
572+
466573BOOL ValidateIOBufferSize (PIRP irp , size_t requiredBufferSize , ValidateIOBufferSizeType type )
467574{
468575 PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (irp );
@@ -2588,6 +2695,12 @@ NTSTATUS ProcessMainDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION Ex
25882695 NTSTATUS ntStatusLocal ;
25892696
25902697 EnsureNullTerminatedString (resolve -> symLinkName , sizeof (resolve -> symLinkName ));
2698+ if (!IsAllowedDevicePathForMetadata (resolve -> symLinkName , TRUE))
2699+ {
2700+ Irp -> IoStatus .Information = 0 ;
2701+ Irp -> IoStatus .Status = STATUS_INVALID_PARAMETER ;
2702+ break ;
2703+ }
25912704
25922705 ntStatusLocal = SymbolicLinkToTarget (resolve -> symLinkName ,
25932706 resolve -> targetName ,
@@ -2608,6 +2721,12 @@ NTSTATUS ProcessMainDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION Ex
26082721 NTSTATUS ntStatusLocal ;
26092722
26102723 EnsureNullTerminatedString (info -> deviceName , sizeof (info -> deviceName ));
2724+ if (!IsAllowedDevicePathForMetadata (info -> deviceName , FALSE))
2725+ {
2726+ Irp -> IoStatus .Information = 0 ;
2727+ Irp -> IoStatus .Status = STATUS_INVALID_PARAMETER ;
2728+ break ;
2729+ }
26112730
26122731 ntStatusLocal = TCDeviceIoControl (info -> deviceName , IOCTL_DISK_GET_PARTITION_INFO_EX , NULL , 0 , & pi , sizeof (pi ));
26132732 if (NT_SUCCESS (ntStatusLocal ))
@@ -2660,36 +2779,25 @@ NTSTATUS ProcessMainDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION Ex
26602779 }
26612780 break ;
26622781
2663- case TC_IOCTL_GET_DRIVE_GEOMETRY :
2664- if (ValidateIOBufferSize (Irp , sizeof (DISK_GEOMETRY_STRUCT ), ValidateInputOutput ))
2665- {
2666- DISK_GEOMETRY_STRUCT * g = (DISK_GEOMETRY_STRUCT * ) Irp -> AssociatedIrp .SystemBuffer ;
2667- {
2668- NTSTATUS ntStatusLocal ;
2669-
2670- EnsureNullTerminatedString (g -> deviceName , sizeof (g -> deviceName ));
2671- Dump ("Calling IOCTL_DISK_GET_DRIVE_GEOMETRY on %ls\n" , g -> deviceName );
2672-
2673- ntStatusLocal = TCDeviceIoControl (g -> deviceName ,
2674- IOCTL_DISK_GET_DRIVE_GEOMETRY ,
2675- NULL , 0 , & g -> diskGeometry , sizeof (g -> diskGeometry ));
2676-
2677- Irp -> IoStatus .Information = sizeof (DISK_GEOMETRY_STRUCT );
2678- Irp -> IoStatus .Status = ntStatusLocal ;
2679- }
2680- }
2681- break ;
2682-
26832782 case VC_IOCTL_GET_DRIVE_GEOMETRY_EX :
26842783 if (ValidateIOBufferSize (Irp , sizeof (DISK_GEOMETRY_EX_STRUCT ), ValidateInputOutput ))
26852784 {
26862785 DISK_GEOMETRY_EX_STRUCT * g = (DISK_GEOMETRY_EX_STRUCT * ) Irp -> AssociatedIrp .SystemBuffer ;
26872786 {
26882787 NTSTATUS ntStatusLocal ;
2689- PVOID buffer = TCalloc (256 ); // enough for DISK_GEOMETRY_EX and padded data
2788+ PVOID buffer ;
2789+
2790+ EnsureNullTerminatedString (g -> deviceName , sizeof (g -> deviceName ));
2791+ if (!IsAllowedDevicePathForMetadata (g -> deviceName , FALSE))
2792+ {
2793+ Irp -> IoStatus .Information = 0 ;
2794+ Irp -> IoStatus .Status = STATUS_INVALID_PARAMETER ;
2795+ break ;
2796+ }
2797+
2798+ buffer = TCalloc (256 ); // enough for DISK_GEOMETRY_EX and padded data
26902799 if (buffer )
26912800 {
2692- EnsureNullTerminatedString (g -> deviceName , sizeof (g -> deviceName ));
26932801 Dump ("Calling IOCTL_DISK_GET_DRIVE_GEOMETRY_EX on %ls\n" , g -> deviceName );
26942802
26952803 ntStatusLocal = TCDeviceIoControl (g -> deviceName ,
@@ -2754,7 +2862,20 @@ NTSTATUS ProcessMainDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION Ex
27542862 PFILE_OBJECT fileObject ;
27552863 PDEVICE_OBJECT deviceObject ;
27562864
2865+ if (!UserCanAccessDriveDevice ())
2866+ {
2867+ Irp -> IoStatus .Information = 0 ;
2868+ Irp -> IoStatus .Status = STATUS_ACCESS_DENIED ;
2869+ break ;
2870+ }
2871+
27572872 EnsureNullTerminatedString (request -> DeviceName , sizeof (request -> DeviceName ));
2873+ if (!IsHarddiskPartitionPath (request -> DeviceName , TRUE))
2874+ {
2875+ Irp -> IoStatus .Information = 0 ;
2876+ Irp -> IoStatus .Status = STATUS_INVALID_PARAMETER ;
2877+ break ;
2878+ }
27582879
27592880 RtlInitUnicodeString (& name , request -> DeviceName );
27602881 status = IoGetDeviceObjectPointer (& name , FILE_READ_ATTRIBUTES , & fileObject , & deviceObject );
@@ -2886,7 +3007,8 @@ NTSTATUS ProcessMainDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION Ex
28863007
28873008 case VC_IOCTL_EMERGENCY_CLEAR_ALL_KEYS :
28883009 EmergencyClearAllKeys (Irp );
2889- WipeCache ();
3010+ if (NT_SUCCESS (Irp -> IoStatus .Status ))
3011+ WipeCache ();
28903012 break ;
28913013
28923014 case TC_IOCTL_BOOT_ENCRYPTION_SETUP :
@@ -4508,7 +4630,7 @@ NTSTATUS SymbolicLinkToTarget (PWSTR symlinkName, PWSTR targetName, USHORT maxTa
45084630 HANDLE handle ;
45094631
45104632 RtlInitUnicodeString (& fullFileName , symlinkName );
4511- InitializeObjectAttributes (& objectAttributes , & fullFileName , OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE , NULL , NULL );
4633+ InitializeObjectAttributes (& objectAttributes , & fullFileName , OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE | OBJ_FORCE_ACCESS_CHECK , NULL , NULL );
45124634
45134635 ntStatus = ZwOpenSymbolicLinkObject (& handle , GENERIC_READ , & objectAttributes );
45144636
0 commit comments