Skip to content

Commit ca35405

Browse files
authored
Merge commit from fork
Restrict caller-supplied object-manager and disk paths used by metadata IOCTLs to the forms required by VeraCrypt. Also force symlink access checks, remove the unused legacy geometry handler, authorize real-drive probing before name resolution, and gate cache wiping on successful emergency key clearing. Security advisory: GHSA-9mgv-w2fw-3m78
1 parent 301496c commit ca35405

2 files changed

Lines changed: 148 additions & 27 deletions

File tree

‎src/Common/Apidrvr.h‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,7 @@
8585
// TODO: need IOCTL_DISK_GET_PARTITION_INFO_EX to support GPT
8686
#define TC_IOCTL_GET_DRIVE_PARTITION_INFO TC_IOCTL (14)
8787

88-
// result IOCTL_DISK_GET_DRIVE_GEOMETRY
89-
// IN OUT - DISK_GEOMETRY_STRUCT
88+
// Legacy IOCTL number retained for compatibility, the driver handler has been removed.
9089
#define TC_IOCTL_GET_DRIVE_GEOMETRY TC_IOCTL (15)
9190

9291
// result IOCTL_DISK_GET_LENGTH_INFO
@@ -254,7 +253,7 @@ typedef struct
254253
WCHAR deviceName[TC_MAX_PATH];
255254
DISK_GEOMETRY diskGeometry;
256255
}
257-
DISK_GEOMETRY_STRUCT;
256+
DISK_GEOMETRY_STRUCT; // unused legacy structure, retained for compatibility.
258257

259258
typedef struct
260259
{

‎src/Driver/Ntdriver.c‎

Lines changed: 146 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
466573
BOOL 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

Comments
 (0)