[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[XENIFACE PATCH 1/2] Fix Registry Isolation issues with Server 2025



Use MmGetSystemRoutineAddress to dynamically get IoOpenDriverRegistryKey,
which is not present on Server 2016.
Where possible, use IoOpenDriverRegistryKey to avoid opening absolute registry
paths, which is a driver verifier violation on Server 2025 WHQL testing.

Also refactors all registry access to use functions in registry.h and cleans up
driver.c to be more inline with other drivers.

Signed-off-by: Owen Smith <owen.smith@xxxxxxxxx>
---
 src/xeniface/driver.c   | 146 +++++++++++++++++++++++++++++++---------
 src/xeniface/driver.h   |  17 ++---
 src/xeniface/fdo.c      |  94 ++++++++++----------------
 src/xeniface/registry.c |  81 +++++++++++++++++++++-
 src/xeniface/registry.h |  14 +++-
 src/xeniface/wmi.c      |   7 +-
 6 files changed, 258 insertions(+), 101 deletions(-)

diff --git a/src/xeniface/driver.c b/src/xeniface/driver.c
index 6c3032b..3b5b16d 100644
--- a/src/xeniface/driver.c
+++ b/src/xeniface/driver.c
@@ -36,32 +36,99 @@
 
 #include "fdo.h"
 #include "driver.h"
+#include "registry.h"
 
 #include "assert.h"
 #include "wmi.h"
 #include "util.h"
 
-PDRIVER_OBJECT      DriverObject;
+typedef struct _XENIFACE_DRIVER {
+    PDRIVER_OBJECT      DriverObject;
+    HANDLE              ParametersKey;
+} XENIFACE_DRIVER, *PXENIFACE_DRIVER;
 
-DRIVER_UNLOAD       DriverUnload;
+static XENIFACE_DRIVER  Driver;
+
+static FORCEINLINE VOID
+__DriverSetDriverObject(
+    IN  PDRIVER_OBJECT  DriverObject
+    )
+{
+    Driver.DriverObject = DriverObject;
+}
+
+static FORCEINLINE PDRIVER_OBJECT
+__DriverGetDriverObject(
+    VOID
+    )
+{
+    return Driver.DriverObject;
+}
+
+PDRIVER_OBJECT
+DriverGetDriverObject(
+    VOID
+    )
+{
+    return __DriverGetDriverObject();
+}
+
+static FORCEINLINE VOID
+__DriverSetParametersKey(
+    IN  HANDLE  Key
+    )
+{
+    Driver.ParametersKey = Key;
+}
+
+static FORCEINLINE HANDLE
+__DriverGetParametersKey(
+    VOID
+    )
+{
+    return Driver.ParametersKey;
+}
+
+HANDLE
+DriverGetParametersKey(
+    VOID
+    )
+{
+    return __DriverGetParametersKey();
+}
 
-XENIFACE_PARAMETERS DriverParameters;
+DRIVER_UNLOAD       DriverUnload;
 
 VOID
 DriverUnload(
-    IN  PDRIVER_OBJECT  _DriverObject
+    IN  PDRIVER_OBJECT  DriverObject
     )
 {
-    ASSERT3P(_DriverObject, ==, DriverObject);
+    HANDLE              ParametersKey;
+
+    ASSERT3P(DriverObject, ==, __DriverGetDriverObject());
 
     Trace("====>\n");
 
-    if (DriverParameters.RegistryPath.Buffer != NULL) {
-        __FreePoolWithTag(DriverParameters.RegistryPath.Buffer,
-                          XENIFACE_POOL_TAG);
-    }
+    ParametersKey = __DriverGetParametersKey();
+    __DriverSetParametersKey(NULL);
+
+    RegistryCloseKey(ParametersKey);
+
+    RegistryTeardown();
+
+    Info("XENIFACE %d.%d.%d (%d) (%02d.%02d.%04d)\n",
+         MAJOR_VERSION,
+         MINOR_VERSION,
+         MICRO_VERSION,
+         BUILD_NUMBER,
+         DAY,
+         MONTH,
+         YEAR);
+
+    __DriverSetDriverObject(NULL);
 
-    DriverObject = NULL;
+    ASSERT(IsZeroMemory(&Driver, sizeof (XENIFACE_DRIVER)));
 
     Trace("<====\n");
 }
@@ -70,13 +137,13 @@ DRIVER_ADD_DEVICE   AddDevice;
 
 NTSTATUS
 AddDevice(
-    IN  PDRIVER_OBJECT  _DriverObject,
+    IN  PDRIVER_OBJECT  DriverObject,
     IN  PDEVICE_OBJECT  DeviceObject
     )
 {
     NTSTATUS            status;
 
-    ASSERT3P(_DriverObject, ==, DriverObject);
+    ASSERT3P(DriverObject, ==, __DriverGetDriverObject());
 
     status = FdoCreate(DeviceObject);
     if (!NT_SUCCESS(status))
@@ -147,40 +214,45 @@ done:
 
 DRIVER_INITIALIZE   DriverEntry;
 
-
 NTSTATUS
 DriverEntry(
-    IN  PDRIVER_OBJECT  _DriverObject,
+    IN  PDRIVER_OBJECT  DriverObject,
     IN  PUNICODE_STRING RegistryPath
     )
 {
+    HANDLE              ParametersKey;
     ULONG               Index;
-    NTSTATUS status = STATUS_UNSUCCESSFUL;
-    ASSERT3P(DriverObject, ==, NULL);
+    NTSTATUS            status;
+
+    ASSERT3P(__DriverGetDriverObject(), ==, NULL);
 
     ExInitializeDriverRuntime(DrvRtPoolNxOptIn);
     WdmlibProcgrpInitialize();
 
     Trace("====>\n");
 
-    Info("%s (%s)\n",
-         MAJOR_VERSION_STR "." MINOR_VERSION_STR "." MICRO_VERSION_STR "." 
BUILD_NUMBER_STR,
-         DAY_STR "/" MONTH_STR "/" YEAR_STR);
-
-    DriverParameters.RegistryPath.MaximumLength = RegistryPath->Length + 
sizeof(UNICODE_NULL);
-    DriverParameters.RegistryPath.Length = RegistryPath->Length;
-    DriverParameters.RegistryPath.Buffer = __AllocatePoolWithTag(PagedPool,
-                                                
DriverParameters.RegistryPath.MaximumLength,
-                                                XENIFACE_POOL_TAG);
-    if (NULL == DriverParameters.RegistryPath.Buffer) {
-        status = STATUS_INSUFFICIENT_RESOURCES;
+    __DriverSetDriverObject(DriverObject);
+
+    DriverObject->DriverUnload = DriverUnload;
+
+    Info("XENIFACE %d.%d.%d (%d) (%02d.%02d.%04d)\n",
+         MAJOR_VERSION,
+         MINOR_VERSION,
+         MICRO_VERSION,
+         BUILD_NUMBER,
+         DAY,
+         MONTH,
+         YEAR);
+
+    status = RegistryInitialize(DriverObject, RegistryPath);
+    if (!NT_SUCCESS(status))
         goto fail1;
-    }
-    RtlCopyUnicodeString(&DriverParameters.RegistryPath, RegistryPath);
 
+    status = RegistryOpenParametersKey(KEY_READ, &ParametersKey);
+    if (!NT_SUCCESS(status))
+        goto fail2;
 
-    DriverObject = _DriverObject;
-    DriverObject->DriverUnload = DriverUnload;
+    __DriverSetParametersKey(ParametersKey);
 
     DriverObject->DriverExtension->AddDevice = AddDevice;
 
@@ -193,7 +265,19 @@ DriverEntry(
     Trace("<====\n");
 
     return STATUS_SUCCESS;
+
+
+fail2:
+    Error("fail2\n");
+
+    RegistryTeardown();
+
 fail1:
     Error("fail1 (%08x)\n", status);
+
+    __DriverSetDriverObject(NULL);
+
+    ASSERT(IsZeroMemory(&Driver, sizeof (XENIFACE_DRIVER)));
+
     return status;
 }
diff --git a/src/xeniface/driver.h b/src/xeniface/driver.h
index 27cd453..9007d97 100644
--- a/src/xeniface/driver.h
+++ b/src/xeniface/driver.h
@@ -46,19 +46,20 @@
 
 #include <wmilib.h>
 #include <ntifs.h>
-extern PDRIVER_OBJECT   DriverObject;
-
 
 #define MAX_DEVICE_ID_LEN   200
 
-typedef struct _XENIFACE_PARAMETERS {
-    UNICODE_STRING RegistryPath;
-
-} XENIFACE_PARAMETERS, *PXENIFACE_PARAMETERS;
-
 #define XENIFACE_POOL_TAG (ULONG) 'XIfc'
 
-extern XENIFACE_PARAMETERS DriverParameters;
+extern PDRIVER_OBJECT
+DriverGetDriverObject(
+    VOID
+    );
+
+extern HANDLE
+DriverGetParametersKey(
+    VOID
+    );
 
 typedef struct _XENIFACE_DX {
     PDEVICE_OBJECT      DeviceObject;
diff --git a/src/xeniface/fdo.c b/src/xeniface/fdo.c
index 29f8338..a2cb713 100644
--- a/src/xeniface/fdo.c
+++ b/src/xeniface/fdo.c
@@ -61,85 +61,63 @@
 
 #define MAXNAMELEN  128
 
-
-static void
+static NTSTATUS
 FdoInitialiseXSRegistryEntries(
     IN PXENIFACE_FDO        Fdo
     )
 {
-    OBJECT_ATTRIBUTES Attributes;
-    HANDLE RegHandle;
-    UNICODE_STRING UnicodeValueName;
-    UNICODE_STRING UnicodeValue;
-    ANSI_STRING AnsiValue;
-    char *value;
-    NTSTATUS status;
+    ANSI_STRING             Ansi[2];
+    HANDLE                  Key;
+    PCHAR                   Value;
+    NTSTATUS                status;
+
     NT_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
+
     status = XENBUS_STORE(Read,
                           &Fdo->StoreInterface,
                           NULL,
                           NULL,
                           "/mh/boot-time/management-mac-address",
-                          &value);
-    if (!NT_SUCCESS(status)){
-        Error("no such xenstore key\n");
-        goto failXS;
-    }
-
-    InitializeObjectAttributes(&Attributes, &DriverParameters.RegistryPath,
-                                OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
-                                NULL,
-                                NULL);
-
-    status = ZwOpenKey(&RegHandle, KEY_WRITE, &Attributes);
+                          &Value);
+    if (!NT_SUCCESS(status))
+        goto fail1;
 
-    if (!NT_SUCCESS(status)) {
-        Error("no such registry key %s\n", DriverParameters.RegistryPath);
-        goto failReg;
-    }
+    status = RegistryOpenParametersKey(KEY_WRITE, &Key);
+    if (!NT_SUCCESS(status))
+        goto fail2;
 
-    RtlInitUnicodeString(&UnicodeValueName, L"MgmtMacAddr");
-    RtlInitUnicodeString(&UnicodeValue, NULL);
-    RtlInitAnsiString(&AnsiValue, value);
+    RtlInitAnsiString(&Ansi[0], Value);
+    RtlZeroMemory(&Ansi[1], sizeof(ANSI_STRING));
 
-    Info("About to convert unicode string\n");
-    status = RtlAnsiStringToUnicodeString(&UnicodeValue, &AnsiValue, TRUE);
-    if (!NT_SUCCESS(status)) {
-        Error("Can't convert string\n");
-        goto failReg;
-    }
+    status = RegistryUpdateSzValue(Key,
+                                   "MgmtMacAddr",
+                                   REG_SZ,
+                                   &Ansi[0]);
+    if (!NT_SUCCESS(status))
+        goto fail3;
 
-    Info("About to write unicode string\n");
-    status = ZwSetValueKey(RegHandle, &UnicodeValueName, 0, REG_SZ, 
UnicodeValue.Buffer, UnicodeValue.Length+sizeof(WCHAR));
-    if (!NT_SUCCESS(status)) {
-        Error("Can't write key\n");
-        goto failWrite;
-    }
+    RegistryCloseKey(Key);
 
-    ZwClose(RegHandle);
+    XENBUS_STORE(Free, &Fdo->StoreInterface, Value);
 
-    RtlFreeUnicodeString(&UnicodeValue);
-    XENBUS_STORE(Free, &Fdo->StoreInterface, value);
+    return STATUS_SUCCESS;
 
-    return;
+fail3:
+    Error("fail3\n");
 
-failWrite:
+    RegistryCloseKey(Key);
 
-    Error("Fail : Write\n");
-    ZwClose(RegHandle);
-    RtlFreeUnicodeString(&UnicodeValue);
+fail2:
+    Error("fail2\n");
 
-failReg:
+    XENBUS_STORE(Free, &Fdo->StoreInterface, Value);
 
-    Error("Fail : Reg\n");
-    XENBUS_STORE(Free, &Fdo->StoreInterface, value);
+fail1:
+    Error("fail1 %08x\n", status);
 
-failXS:
-    Error("Failed to initialise registry (%08x)\n", status);
-    return;
+    return status;
 }
 
-
 #define REGISTRY_WRITE_EVENT 0
 #define REGISTRY_THREAD_END_EVENT 1
 #define REGISTRY_EVENTS 2
@@ -163,7 +141,7 @@ static NTSTATUS FdoRegistryThreadHandler(IN  
PXENIFACE_THREAD  Self,
         if ((status>=STATUS_WAIT_0) && (status < 
STATUS_WAIT_0+REGISTRY_EVENTS)) {
             if (status == STATUS_WAIT_0+REGISTRY_WRITE_EVENT) {
                 Info("WriteRegistry\n");
-                FdoInitialiseXSRegistryEntries(Fdo);
+                (VOID) FdoInitialiseXSRegistryEntries(Fdo);
                 KeClearEvent(threadevents[REGISTRY_WRITE_EVENT]);
             }
             if (status == STATUS_WAIT_0+REGISTRY_THREAD_END_EVENT) {
@@ -2475,7 +2453,7 @@ FdoCreate(
     NTSTATUS            status;
 
 #pragma prefast(suppress:28197) // Possibly leaking memory 
'FunctionDeviceObject'
-    status = IoCreateDevice(DriverObject,
+    status = IoCreateDevice(DriverGetDriverObject(),
                             sizeof (XENIFACE_DX),
                             NULL,
                             FILE_DEVICE_UNKNOWN,
@@ -2585,7 +2563,7 @@ FdoCreate(
     InitializeListHead(&Dx->ListEntry);
     Fdo->References = 1;
 
-    FdoInitialiseXSRegistryEntries(Fdo);
+    (VOID) FdoInitialiseXSRegistryEntries(Fdo);
 
     KeInitializeEvent(&Fdo->registryWriteEvent, NotificationEvent, FALSE);
 
diff --git a/src/xeniface/registry.c b/src/xeniface/registry.c
index 8f84818..1ab85c9 100644
--- a/src/xeniface/registry.c
+++ b/src/xeniface/registry.c
@@ -38,8 +38,13 @@
 
 #define REGISTRY_TAG 'GERX'
 
+static PDRIVER_OBJECT   RegistryDriverObject;
 static UNICODE_STRING   RegistryPath;
 
+typedef NTSTATUS(*IOOPENDRIVERREGISTRYKEY)(PDRIVER_OBJECT, DRIVER_REGKEY_TYPE, 
ACCESS_MASK, ULONG, PHANDLE);
+
+static IOOPENDRIVERREGISTRYKEY __IoOpenDriverRegistryKey;
+
 static FORCEINLINE PVOID
 __RegistryAllocate(
     IN  ULONG   Length
@@ -58,9 +63,12 @@ __RegistryFree(
 
 NTSTATUS
 RegistryInitialize(
-    IN PUNICODE_STRING  Path
+    IN  PDRIVER_OBJECT  DriverObject,
+    IN  PUNICODE_STRING Path
     )
 {
+    UNICODE_STRING      Unicode;
+    PVOID               Func;
     NTSTATUS            status;
 
     ASSERT3P(RegistryPath.Buffer, ==, NULL);
@@ -69,6 +77,16 @@ RegistryInitialize(
     if (!NT_SUCCESS(status))
         goto fail1;
 
+    ASSERT3P(RegistryDriverObject, ==, NULL);
+    RegistryDriverObject = DriverObject;
+
+    ASSERT3P(__IoOpenDriverRegistryKey, ==, NULL);
+    RtlInitUnicodeString(&Unicode, L"IoOpenDriverRegistryKey");
+
+    Func = MmGetSystemRoutineAddress(&Unicode);
+    if (Func != NULL)
+        __IoOpenDriverRegistryKey = (IOOPENDRIVERREGISTRYKEY)Func;
+
     return STATUS_SUCCESS;
 
 fail1:
@@ -82,11 +100,24 @@ RegistryTeardown(
     VOID
     )
 {
+    __IoOpenDriverRegistryKey = NULL;
+
+    RegistryDriverObject = NULL;
+
     RtlFreeUnicodeString(&RegistryPath);
     RegistryPath.Buffer = NULL;
     RegistryPath.MaximumLength = RegistryPath.Length = 0;
 }
 
+PUNICODE_STRING
+RegistryGetPath(
+    VOID
+    )
+{
+    return &RegistryPath;
+}
+
+
 NTSTATUS
 RegistryOpenKey(
     IN  HANDLE          Parent,
@@ -266,6 +297,54 @@ RegistryCreateServiceKey(
     return RegistryCreateKey(NULL, &RegistryPath, REG_OPTION_NON_VOLATILE, 
Key);
 }
 
+NTSTATUS
+RegistryOpenParametersKey(
+    IN  ACCESS_MASK     DesiredAccess,
+    OUT PHANDLE         Key
+    )
+{
+    HANDLE              ServiceKey;
+    NTSTATUS            status;
+
+    if (__IoOpenDriverRegistryKey != NULL) {
+        status = __IoOpenDriverRegistryKey(RegistryDriverObject,
+                                           DriverRegKeyParameters,
+                                           DesiredAccess,
+                                           0,
+                                           Key);
+        if (!NT_SUCCESS(status))
+            goto fail1;
+
+        goto done;
+    }
+
+    status = RegistryOpenKey(NULL, &RegistryPath, DesiredAccess, &ServiceKey);
+    if (!NT_SUCCESS(status))
+        goto fail2;
+
+    status = RegistryOpenSubKey(ServiceKey, "Parameters", DesiredAccess, Key);
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
+    RegistryCloseKey(ServiceKey);
+
+done:
+    return STATUS_SUCCESS;
+
+fail3:
+    Error("fail3\n");
+
+    RegistryCloseKey(ServiceKey);
+
+fail2:
+    Error("fail2\n");
+
+fail1:
+    Error("fail1 %08x\n", status);
+
+    return status;
+}
+
 NTSTATUS
 RegistryOpenSoftwareKey(
     IN  PDEVICE_OBJECT  DeviceObject,
diff --git a/src/xeniface/registry.h b/src/xeniface/registry.h
index 1cf8671..42ee9c8 100644
--- a/src/xeniface/registry.h
+++ b/src/xeniface/registry.h
@@ -37,7 +37,8 @@
 
 extern NTSTATUS
 RegistryInitialize(
-    IN PUNICODE_STRING  Path
+    IN  PDRIVER_OBJECT  DriverObject,
+    IN  PUNICODE_STRING Path
     );
 
 extern VOID
@@ -45,6 +46,11 @@ RegistryTeardown(
     VOID
     );
 
+extern PUNICODE_STRING
+RegistryGetPath(
+    VOID
+    );
+
 extern NTSTATUS
 RegistryOpenKey(
     IN  HANDLE          Parent,
@@ -72,6 +78,12 @@ RegistryCreateServiceKey(
     OUT PHANDLE     Key
     );
 
+extern NTSTATUS
+RegistryOpenParametersKey(
+    IN  ACCESS_MASK     DesiredAccess,
+    OUT PHANDLE         Key
+    );
+
 extern NTSTATUS
 RegistryOpenSoftwareKey(
     IN  PDEVICE_OBJECT  DeviceObject,
diff --git a/src/xeniface/wmi.c b/src/xeniface/wmi.c
index 97ef2c3..95b4bb1 100644
--- a/src/xeniface/wmi.c
+++ b/src/xeniface/wmi.c
@@ -41,6 +41,7 @@
 #include <ntstrsafe.h>
 #include "wmi.h"
 #include "driver.h"
+#include "registry.h"
 #include "store_interface.h"
 #include "suspend_interface.h"
 #include "log.h"
@@ -2999,6 +3000,7 @@ WmiRegInfo(
     UCHAR*                  mofnameptr;
     UCHAR*                  regpath;
     ULONG                   RequiredSize;
+    PUNICODE_STRING         RegistryPath;
 
     const int entries = 4;
     const static UNICODE_STRING mofname = RTL_CONSTANT_STRING(L"XENIFACEMOF");
@@ -3010,13 +3012,14 @@ WmiRegInfo(
     else
         mofnamesz = 0;
 
+    RegistryPath = RegistryGetPath();
     if (!AccessWmiBuffer(Stack->Parameters.WMI.Buffer, FALSE,
                          &RequiredSize,
                          Stack->Parameters.WMI.BufferSize,
                          WMI_BUFFER, sizeof(WMIREGINFO), (UCHAR **)&reginfo,
                          WMI_BUFFER, entries * sizeof(WMIREGGUID), (UCHAR 
**)&guiddata,
                          WMI_STRING, mofnamesz, &mofnameptr,
-                         WMI_STRING, DriverParameters.RegistryPath.Length + 
sizeof(USHORT), &regpath,
+                         WMI_STRING, RegistryPath->Length + sizeof(USHORT), 
&regpath,
                          WMI_DONE)) {
         reginfo->BufferSize = RequiredSize;
         *BytesWritten = sizeof(ULONG);
@@ -3027,7 +3030,7 @@ WmiRegInfo(
         reginfo->MofResourceName = (ULONG)((ULONG_PTR)mofnameptr - 
(ULONG_PTR)reginfo);
         WriteCountedUnicodeString(&mofname, mofnameptr);
         reginfo->RegistryPath = (ULONG)((ULONG_PTR)regpath - 
(ULONG_PTR)reginfo);
-        WriteCountedUnicodeString(&DriverParameters.RegistryPath, regpath);
+        WriteCountedUnicodeString(RegistryPath, regpath);
     }
 
     reginfo->BufferSize = RequiredSize;
-- 
2.44.0.windows.1




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.