Author: pschweitzer Date: Sat Sep 19 21:23:45 2015 New Revision: 69295
URL: http://svn.reactos.org/svn/reactos?rev=69295&view=rev Log: [MOUNTMGR] Fix CVE-2015-1769: - When opening remote databases, don't attempt to migrate w2k database to current format. - Also, when opening/creating the remote database, don't allow following symlinks anymore. In case a symlink would be detected, an error message will be printed.
Commit dedicated to Alex :-).
CORE-10216 #resolve #comment Fixed with r69295
Modified: trunk/reactos/drivers/filters/mountmgr/database.c
Modified: trunk/reactos/drivers/filters/mountmgr/database.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/filters/mountmgr/da... ============================================================================== --- trunk/reactos/drivers/filters/mountmgr/database.c [iso-8859-1] (original) +++ trunk/reactos/drivers/filters/mountmgr/database.c [iso-8859-1] Sat Sep 19 21:23:45 2015 @@ -32,7 +32,6 @@ PWSTR OfflinePath = L"\Registry\Machine\System\MountedDevices\Offline";
UNICODE_STRING RemoteDatabase = RTL_CONSTANT_STRING(L"\System Volume Information\MountPointManagerRemoteDatabase"); -UNICODE_STRING RemoteDatabaseFile = RTL_CONSTANT_STRING(L"\:$MountMgrRemoteDatabase");
/* * @implemented @@ -1664,22 +1663,16 @@ */ VOID NTAPI -MigrateRemoteDatabaseWorker(IN PDEVICE_OBJECT DeviceObject, - IN PVOID Context) -{ - ULONG Length; +CreateRemoteDatabaseWorker(IN PDEVICE_OBJECT DeviceObject, + IN PVOID Context) +{ NTSTATUS Status; - PVOID TmpBuffer; - CHAR Disposition; - LARGE_INTEGER ByteOffset; + HANDLE Database = 0; + UNICODE_STRING DatabaseName; PMIGRATE_WORK_ITEM WorkItem; IO_STATUS_BLOCK IoStatusBlock; - HANDLE Migrate = 0, Database = 0; + OBJECT_ATTRIBUTES ObjectAttributes; PDEVICE_INFORMATION DeviceInformation; - BOOLEAN PreviousMode, Complete = FALSE; - UNICODE_STRING DatabaseName, DatabaseFile; - OBJECT_ATTRIBUTES ObjectAttributes, MigrateAttributes; -#define TEMP_BUFFER_SIZE 0x200
UNREFERENCED_PARAMETER(DeviceObject);
@@ -1690,15 +1683,8 @@ /* Reconstruct appropriate string */ DatabaseName.Length = DeviceInformation->DeviceName.Length + RemoteDatabase.Length; DatabaseName.MaximumLength = DatabaseName.Length + sizeof(WCHAR); - - DatabaseFile.Length = DeviceInformation->DeviceName.Length + RemoteDatabaseFile.Length; - DatabaseFile.MaximumLength = DatabaseFile.Length + sizeof(WCHAR); - DatabaseName.Buffer = AllocatePool(DatabaseName.MaximumLength); - DatabaseFile.Buffer = AllocatePool(DatabaseFile.MaximumLength); - /* Allocate buffer that will be used to swap contents */ - TmpBuffer = AllocatePool(TEMP_BUFFER_SIZE); - if (!DatabaseName.Buffer || !DatabaseFile.Buffer || !TmpBuffer) + if (DatabaseName.Buffer == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto Cleanup; @@ -1715,13 +1701,9 @@
/* Finish initating strings */ RtlCopyMemory(DatabaseName.Buffer, DeviceInformation->DeviceName.Buffer, DeviceInformation->DeviceName.Length); - RtlCopyMemory(DatabaseFile.Buffer, DeviceInformation->DeviceName.Buffer, DeviceInformation->DeviceName.Length); RtlCopyMemory(DatabaseName.Buffer + (DeviceInformation->DeviceName.Length / sizeof(WCHAR)), RemoteDatabase.Buffer, RemoteDatabase.Length); - RtlCopyMemory(DatabaseFile.Buffer + (DeviceInformation->DeviceName.Length / sizeof(WCHAR)), - RemoteDatabaseFile.Buffer, RemoteDatabaseFile.Length); DatabaseName.Buffer[DatabaseName.Length / sizeof(WCHAR)] = UNICODE_NULL; - DatabaseFile.Buffer[DatabaseFile.Length / sizeof(WCHAR)] = UNICODE_NULL;
/* Create database */ InitializeObjectAttributes(&ObjectAttributes, @@ -1730,7 +1712,7 @@ NULL, NULL);
- Status = ZwCreateFile(&Database, + Status = IoCreateFile(&Database, SYNCHRONIZE | READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES | FILE_WRITE_PROPERTIES | FILE_READ_PROPERTIES | FILE_APPEND_DATA | FILE_WRITE_DATA | FILE_READ_DATA, @@ -1742,123 +1724,32 @@ FILE_CREATE, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_ALERT, NULL, - 0); + 0, + CreateFileTypeNone, + NULL, + IO_STOP_ON_SYMLINK); if (!NT_SUCCESS(Status)) { + if (Status == STATUS_STOPPED_ON_SYMLINK) + { + DPRINT1("Attempt to exploit CVE-2015-1769. See CORE-10216\n"); + } + Database = 0; goto Cleanup; }
- InitializeObjectAttributes(&MigrateAttributes, - &DatabaseFile, - OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, - NULL, - NULL); - - /* Disable hard errors and open the database that will be copied */ - PreviousMode = IoSetThreadHardErrorMode(FALSE); - Status = ZwCreateFile(&Migrate, - SYNCHRONIZE | READ_CONTROL | FILE_WRITE_ATTRIBUTES | - FILE_READ_ATTRIBUTES | FILE_WRITE_PROPERTIES | FILE_READ_PROPERTIES | - FILE_APPEND_DATA | FILE_WRITE_DATA | FILE_READ_DATA, - &MigrateAttributes, - &IoStatusBlock, - NULL, - FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN, - 0, - FILE_OPEN, - FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_ALERT, - NULL, - 0); - IoSetThreadHardErrorMode(PreviousMode); - if (!NT_SUCCESS(Status)) - { - Migrate = 0; - } - if (Status == STATUS_OBJECT_NAME_NOT_FOUND) - { - Status = STATUS_SUCCESS; - Complete = TRUE; - } - if (!NT_SUCCESS(Status) || Complete) - { - goto Cleanup; - } - - ByteOffset.QuadPart = 0LL; - PreviousMode = IoSetThreadHardErrorMode(FALSE); - /* Now, loop as long it's possible */ - while (Status == STATUS_SUCCESS) - { - /* Read data from existing database */ - Status = ZwReadFile(Migrate, - NULL, - NULL, - NULL, - &IoStatusBlock, - TmpBuffer, - TEMP_BUFFER_SIZE, - &ByteOffset, - NULL); - if (!NT_SUCCESS(Status)) - { - break; - } - - /* And write them into new database */ - Length = (ULONG)IoStatusBlock.Information; - Status = ZwWriteFile(Database, - NULL, - NULL, - NULL, - &IoStatusBlock, - TmpBuffer, - Length, - &ByteOffset, - NULL); - ByteOffset.QuadPart += Length; - } - IoSetThreadHardErrorMode(PreviousMode); - - /* Delete old databse if it was well copied */ - if (Status == STATUS_END_OF_FILE) - { - Disposition = 1; - Status = ZwSetInformationFile(Migrate, - &IoStatusBlock, - &Disposition, - sizeof(Disposition), - FileDispositionInformation); - } - - /* Migration is over */ - Cleanup: - if (TmpBuffer) - { - FreePool(TmpBuffer); - } - - if (DatabaseFile.Buffer) - { - FreePool(DatabaseFile.Buffer); - } - if (DatabaseName.Buffer) { FreePool(DatabaseName.Buffer); }
- if (Migrate) - { - ZwClose(Migrate); - } - if (NT_SUCCESS(Status)) { DeviceInformation->Migrated = 1; } - else if (Database) + else if (Database != 0) { ZwClose(Database); } @@ -1870,15 +1761,14 @@ WorkItem->Database = Database;
KeSetEvent(WorkItem->Event, 0, FALSE); -#undef TEMP_BUFFER_SIZE }
/* * @implemented */ NTSTATUS -MigrateRemoteDatabase(IN PDEVICE_INFORMATION DeviceInformation, - IN OUT PHANDLE Database) +CreateRemoteDatabase(IN PDEVICE_INFORMATION DeviceInformation, + IN OUT PHANDLE Database) { KEVENT Event; NTSTATUS Status; @@ -1907,7 +1797,7 @@
/* And queue it */ IoQueueWorkItem(WorkItem->WorkItem, - MigrateRemoteDatabaseWorker, + CreateRemoteDatabaseWorker, DelayedWorkQueue, WorkItem);
@@ -1960,7 +1850,7 @@ /* Disable hard errors */ PreviousMode = IoSetThreadHardErrorMode(FALSE);
- Status = ZwCreateFile(&Database, + Status = IoCreateFile(&Database, SYNCHRONIZE | READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES | FILE_WRITE_PROPERTIES | FILE_READ_PROPERTIES | FILE_APPEND_DATA | FILE_WRITE_DATA | FILE_READ_DATA, @@ -1972,12 +1862,19 @@ (!MigrateDatabase || DeviceInformation->Migrated == 0) ? FILE_OPEN_IF : FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_ALERT, NULL, - 0); + 0, + CreateFileTypeNone, + NULL, + IO_STOP_ON_SYMLINK); + if (Status == STATUS_STOPPED_ON_SYMLINK) + { + DPRINT1("Attempt to exploit CVE-2015-1769. See CORE-10216\n"); + }
/* If base it to be migrated and was opened successfully, go ahead */ if (MigrateDatabase && NT_SUCCESS(Status)) { - MigrateRemoteDatabase(DeviceInformation, &Database); + CreateRemoteDatabase(DeviceInformation, &Database); }
IoSetThreadHardErrorMode(PreviousMode);