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

[win-pv-devel] [PATCH] Re-work identity stealing code



The change introduced by patch 04c391d9 "Replace copying network
settings with identity stealing" had a flaw...

If a PV device that aliases an emulated device is installed then it
will only steal linkage if that emulated device is operational at the
time. This works on initial driver install, but not if the PV network
device driver is removed and then re-installed without an interim
reboot (which would make the emulated device operational). Instead,
after re-installation, the PV device has a brand new stack binding and
thus any network settings changes that were previously made are
apparently lost.

To fix this problem, this patch breaks the process of stealing the
emulated device's stack binding into two phases:

1) Discovery: When the PV device driver is installed, if an aliasing
   emulated device is operational, a DWORD value called "VIF" is
   created under the emulated devices software key. The value is set
   to the PV device instance.

2) Theft: When the PV device is being brought online, the registry is
   checked to see if any network device has a software key containing
   a "VIF" value that patches the PV device instance.
   If such an entry is found then the stack binding is stolen from
   that device. Since the "VIF" value is in the *emulated* device's
   software key, it will not be removed if the PV device driver is
   removed and re-installed and so the problem described above will
   not occur.

Because this patch avoids stealing the emulated device's stack bindings
if it is actually operational (i.e. we're in phase 1) this results in the
class installer building a new set of stack bindings for the PV device
during initial installation.
These are then restored any time a PV device with a stolen stack binding
is offlined. So, when a PV device is offline there is no evidence that
any stack binding has been stolen and hence, during driver removal, there
is no risk of an emulated device's stack binding being torn down.

Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx>
---
 src/xenvif/frontend.c |   6 +-
 src/xenvif/pdo.c      |  63 +++++++++--
 src/xenvif/settings.c | 298 ++++++++++++++++++++++++++++++++++++++++++++++----
 src/xenvif/settings.h |  21 +++-
 4 files changed, 348 insertions(+), 40 deletions(-)

diff --git a/src/xenvif/frontend.c b/src/xenvif/frontend.c
index 7d682ab..d21c798 100644
--- a/src/xenvif/frontend.c
+++ b/src/xenvif/frontend.c
@@ -498,9 +498,6 @@ FrontendProcessInterfaceTable(
         if (!Row->InterfaceAndOperStatusFlags.ConnectorPresent)
             continue;
 
-        if (Row->OperStatus != IfOperStatusUp)
-            continue;
-
         if (Row->PhysicalAddressLength != sizeof (ETHERNET_ADDRESS))
             continue;
 
@@ -509,6 +506,9 @@ FrontendProcessInterfaceTable(
                    sizeof (ETHERNET_ADDRESS)) != 0)
             continue;
 
+        if (Row->OperStatus != IfOperStatusUp)
+            continue;
+
         goto found;
     }
 
diff --git a/src/xenvif/pdo.c b/src/xenvif/pdo.c
index 6c4c9bd..5fefaeb 100644
--- a/src/xenvif/pdo.c
+++ b/src/xenvif/pdo.c
@@ -98,7 +98,9 @@ struct _XENVIF_PDO {
     PXENVIF_VIF_CONTEXT         VifContext;
     XENVIF_VIF_INTERFACE        VifInterface;
 
+    ULONG                       Number;
     BOOLEAN                     HasAlias;
+    BOOLEAN                     HasStolenLinkage;
 };
 
 static FORCEINLINE PVOID
@@ -298,6 +300,23 @@ PdoGetName(
     return __PdoGetName(Pdo);
 }
 
+static FORCEINLINE VOID
+__PdoSetNumber(
+    IN  PXENVIF_PDO Pdo,
+    IN  ULONG       Number
+    )
+{
+    Pdo->Number = Number;
+}
+
+static FORCEINLINE ULONG
+__PdoGetNumber(
+    IN  PXENVIF_PDO Pdo
+    )
+{
+    return Pdo->Number;
+}
+
 static FORCEINLINE BOOLEAN
 __PdoSetEjectRequested(
     IN  PXENVIF_PDO Pdo
@@ -1257,9 +1276,6 @@ PdoStartDevice(
         if (!Row->InterfaceAndOperStatusFlags.ConnectorPresent)
             continue;
 
-        if (Row->OperStatus != IfOperStatusUp)
-            continue;
-
         if (Row->PhysicalAddressLength != sizeof (ETHERNET_ADDRESS))
             continue;
 
@@ -1268,14 +1284,28 @@ PdoStartDevice(
                    sizeof (ETHERNET_ADDRESS)) != 0)
             continue;
 
+        if (Row->OperStatus != IfOperStatusUp)
+            continue;
+
+        (VOID) SettingsSetAlias(Row->Alias,
+                                Row->Description,
+                                &Row->InterfaceGuid,
+                                __PdoGetNumber(Pdo));
+
         Pdo->HasAlias = TRUE;
+    }
 
+    if (Pdo->HasAlias) {
         PdoUnplugRequest(Pdo, TRUE);
 
         status = STATUS_UNSUCCESSFUL;
         goto fail9;
     }
 
+    status = SettingsStealAliasLinkage(__PdoGetSoftwareKey(Pdo),
+                                       __PdoGetNumber(Pdo));
+    Pdo->HasStolenLinkage = (NT_SUCCESS(status)) ? TRUE : FALSE;
+
     StackLocation = IoGetCurrentIrpStackLocation(Irp);
 
     status = PdoD3ToD0(Pdo);
@@ -1296,6 +1326,11 @@ PdoStartDevice(
 fail10:
     Error("fail10\n");
 
+    if (Pdo->HasStolenLinkage) {
+        (VOID) SettingsRestoreLinkage(__PdoGetSoftwareKey(Pdo));
+        Pdo->HasStolenLinkage = FALSE;
+    }
+
     __FreeMibTable(Table);
 
     goto fail6;
@@ -1303,11 +1338,6 @@ fail10:
 fail9:
     Error("fail9\n");
 
-    (VOID) SettingsStealIdentity(__PdoGetSoftwareKey(Pdo),
-                                 Row->Alias,
-                                 Row->Description,
-                                 &Row->InterfaceGuid);
-
     DriverRequestReboot();
     __FreeMibTable(Table);
 
@@ -1398,6 +1428,11 @@ PdoStopDevice(
 
     PdoD0ToD3(Pdo);
 
+    if (Pdo->HasStolenLinkage) {
+        (VOID) SettingsRestoreLinkage(__PdoGetSoftwareKey(Pdo));
+        Pdo->HasStolenLinkage = FALSE;
+    }
+
 done:
     RtlZeroMemory(&Pdo->CurrentAddress, sizeof (ETHERNET_ADDRESS));
 
@@ -1489,6 +1524,11 @@ PdoRemoveDevice(
 
     PdoD0ToD3(Pdo);
 
+    if (Pdo->HasStolenLinkage) {
+        (VOID) SettingsRestoreLinkage(__PdoGetSoftwareKey(Pdo));
+        Pdo->HasStolenLinkage = FALSE;
+    }
+
 done:
     RtlZeroMemory(&Pdo->CurrentAddress, sizeof (ETHERNET_ADDRESS));
 
@@ -2654,6 +2694,7 @@ PdoCreate(
         goto fail4;
 
     __PdoSetName(Pdo, Number);
+    __PdoSetNumber(Pdo, Number);
 
     status = __PdoSetPermanentAddress(Pdo, Address);
     if (!NT_SUCCESS(status))
@@ -2757,6 +2798,8 @@ fail4:
 fail3:
     Error("fail3\n");
 
+    Pdo->Number = 0;
+
     Pdo->Fdo = NULL;
     Pdo->Dx = NULL;
 
@@ -2783,9 +2826,9 @@ PdoDestroy(
     PDEVICE_OBJECT  PhysicalDeviceObject = Dx->DeviceObject;
     PXENVIF_FDO     Fdo = __PdoGetFdo(Pdo);
 
-    ASSERT(!Pdo->UnplugRequested);
     ASSERT3U(__PdoGetDevicePnpState(Pdo), ==, Deleted);
 
+    Pdo->UnplugRequested = FALSE;
     Pdo->HasAlias = FALSE;
 
     ASSERT(__PdoIsMissing(Pdo));
@@ -2831,6 +2874,8 @@ PdoDestroy(
     ThreadJoin(Pdo->SystemPowerThread);
     Pdo->SystemPowerThread = NULL;
 
+    Pdo->Number = 0;
+
     Pdo->Fdo = NULL;
     Pdo->Dx = NULL;
 
diff --git a/src/xenvif/settings.c b/src/xenvif/settings.c
index e684b82..dcfeb60 100644
--- a/src/xenvif/settings.c
+++ b/src/xenvif/settings.c
@@ -374,7 +374,7 @@ fail1:
 }
 
 static NTSTATUS
-SettingsGetAliasNetInstance(
+SettingsGetNetInstance(
     IN  LPGUID                                      NetCfgInstanceID,
     OUT PANSI_STRING                                SubKeyName
     )
@@ -411,7 +411,7 @@ SettingsGetAliasNetInstance(
     if (Parameters.SubKeyName.Length == 0)
         goto fail5;
 
-    Info("%Z\n", &Parameters.SubKeyName);
+    Trace("%Z\n", &Parameters.SubKeyName);
 
     *SubKeyName = Parameters.SubKeyName;
 
@@ -447,6 +447,199 @@ fail1:
     return status;
 }
 
+typedef struct _SETTINGS_MATCH_NUMBER_PARAMETERS {
+    ULONG       Number;
+    ANSI_STRING SubKeyName;
+} SETTINGS_MATCH_NUMBER_PARAMETERS, *PSETTINGS_MATCH_NUMBER_PARAMETERS;
+
+static NTSTATUS
+SettingsMatchNumber(
+    IN  PVOID                           Context,
+    IN  HANDLE                          Key,
+    IN  PANSI_STRING                    SubKeyName
+    )
+{
+    PSETTINGS_MATCH_NUMBER_PARAMETERS   Parameters = Context;
+    HANDLE                              SubKey;
+    ANSI_STRING                         Ansi;
+    ULONG                               Value;
+    NTSTATUS                            status;
+
+    Trace("====> (%Z)\n", SubKeyName);
+
+    if (Parameters->SubKeyName.Length != 0)
+        goto done;
+
+    RtlInitAnsiString(&Ansi, "Properties");
+
+    if (RtlCompareString(&Ansi, SubKeyName, TRUE) == 0)
+        goto done;
+
+    status = RegistryOpenSubKey(Key,
+                                SubKeyName->Buffer,
+                                KEY_READ,
+                                &SubKey);
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    status = RegistryQueryDwordValue(SubKey,
+                                     "VIF",
+                                     &Value);
+    if (NT_SUCCESS(status) &&
+        Parameters->Number == Value) {
+        Parameters->SubKeyName.MaximumLength = SubKeyName->MaximumLength;
+        Parameters->SubKeyName.Buffer = 
__SettingsAllocate(Parameters->SubKeyName.MaximumLength);
+
+        status = STATUS_NO_MEMORY;
+        if (Parameters->SubKeyName.Buffer == NULL)
+            goto fail2;
+
+        RtlCopyMemory(Parameters->SubKeyName.Buffer,
+                      SubKeyName->Buffer,
+                      SubKeyName->Length);
+
+        Parameters->SubKeyName.Length = SubKeyName->Length;
+    }
+
+    RegistryCloseKey(SubKey);
+
+done:
+    Trace("<====\n");
+
+    return STATUS_SUCCESS;
+
+fail2:
+    Error("fail2\n");
+
+    RegistryCloseKey(SubKey);
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+static NTSTATUS
+SettingsGetAliasNetInstance(
+    IN  ULONG                          Number,
+    OUT PANSI_STRING                   SubKeyName
+    )
+{
+    HANDLE                             NetKey;
+    SETTINGS_MATCH_NUMBER_PARAMETERS   Parameters;
+    NTSTATUS                           status;
+
+    status = SettingsOpenNetKey(KEY_READ, &NetKey);
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    RtlZeroMemory(&Parameters, sizeof (Parameters));
+
+    Parameters.Number = Number;
+
+    status = RegistryEnumerateSubKeys(NetKey,
+                                      SettingsMatchNumber,
+                                      &Parameters);
+    if (!NT_SUCCESS(status))
+        goto fail2;
+
+    status = STATUS_UNSUCCESSFUL;
+    if (Parameters.SubKeyName.Length == 0)
+        goto fail3;
+
+    Trace("%Z\n", &Parameters.SubKeyName);
+
+    *SubKeyName = Parameters.SubKeyName;
+
+    RegistryCloseKey(NetKey);
+
+    return STATUS_SUCCESS;
+
+fail3:
+    Error("fail3\n");
+
+fail2:
+    Error("fail2\n");
+
+    RegistryCloseKey(NetKey);
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+NTSTATUS
+SettingsSetAlias(
+    IN  PWCHAR      Alias,
+    IN  PWCHAR      Description,
+    IN  LPGUID      NetCfgInstanceID,
+    IN  ULONG       Number
+    )
+{
+    ANSI_STRING     SubKeyName;
+    HANDLE          NetKey;
+    HANDLE          SubKey;
+    NTSTATUS        status;
+
+    Trace("====>\n");
+
+    Info("%ws (%ws)\n", Alias, Description);
+
+    status = SettingsGetNetInstance(NetCfgInstanceID,
+                                    &SubKeyName);
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    status = SettingsOpenNetKey(KEY_READ,
+                                &NetKey);
+    if (!NT_SUCCESS(status))
+        goto fail2;
+
+    status = RegistryOpenSubKey(NetKey,
+                                SubKeyName.Buffer,
+                                KEY_READ,
+                                &SubKey);
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
+    status = RegistryUpdateDwordValue(SubKey,
+                                      "VIF",
+                                      Number);
+    if (!NT_SUCCESS(status))
+        goto fail4;
+
+    RegistryCloseKey(SubKey);
+
+    RegistryCloseKey(NetKey);
+
+    __SettingsFree(SubKeyName.Buffer);
+
+    Trace("<====\n");
+
+    return STATUS_SUCCESS;
+
+fail4:
+    Error("fail4\n");
+
+    RegistryCloseKey(SubKey);
+
+fail3:
+    Error("fail3\n");
+
+    RegistryCloseKey(NetKey);
+
+fail2:
+    Error("fail2\n");
+
+    __SettingsFree(SubKeyName.Buffer);
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
 static NTSTATUS
 SettingsCopyLinkage(
     IN HANDLE       DestinationKey,
@@ -494,69 +687,87 @@ fail1:
 }
 
 NTSTATUS
-SettingsStealIdentity(
-    IN HANDLE   SoftwareKey,
-    IN PWCHAR   Alias,
-    IN PWCHAR   Description,
-    IN LPGUID   NetCfgInstanceID
+SettingsStealAliasLinkage(
+    IN  HANDLE      SoftwareKey,
+    IN  ULONG       Number
     )
 {
-    ANSI_STRING SubKeyName;
-    HANDLE      NetKey;
-    HANDLE      SubKey;
-    NTSTATUS    status;
+    ANSI_STRING     SubKeyName;
+    HANDLE          BackupKey;
+    HANDLE          NetKey;
+    HANDLE          SubKey;
+    NTSTATUS        status;
 
-    Info("%ws (%ws)\n", Alias, Description);
+    Trace("====>\n");
 
-    status = SettingsGetAliasNetInstance(NetCfgInstanceID,
+    status = SettingsGetAliasNetInstance(Number,
                                          &SubKeyName);
     if (!NT_SUCCESS(status))
         goto fail1;
 
-    status = RegistryUpdateSzValue(SoftwareKey,
-                                   "AliasNetInstance",
-                                   REG_SZ,
-                                   &SubKeyName);
+    Info("FROM %s\n", SubKeyName);
+
+    status = RegistryCreateSubKey(SoftwareKey,
+                                  "Backup",
+                                  REG_OPTION_NON_VOLATILE,
+                                  &BackupKey);
     if (!NT_SUCCESS(status))
         goto fail2;
 
-    status = SettingsOpenNetKey(KEY_READ, &NetKey);
+    status = SettingsCopyLinkage(BackupKey,
+                                 SoftwareKey);
     if (!NT_SUCCESS(status))
         goto fail3;
 
+    status = SettingsOpenNetKey(KEY_READ,
+                                &NetKey);
+    if (!NT_SUCCESS(status))
+        goto fail4;
+
     status = RegistryOpenSubKey(NetKey,
                                 SubKeyName.Buffer,
                                 KEY_READ,
                                 &SubKey);
     if (!NT_SUCCESS(status))
-        goto fail4;
+        goto fail5;
 
     status = SettingsCopyLinkage(SoftwareKey,
                                  SubKey);
     if (!NT_SUCCESS(status))
-        goto fail5;
+        goto fail6;
 
     RegistryCloseKey(SubKey);
 
     RegistryCloseKey(NetKey);
 
+    RegistryCloseKey(BackupKey);
+
     __SettingsFree(SubKeyName.Buffer);
 
+    Trace("<====\n");
+
     return STATUS_SUCCESS;
 
+fail6:
+    Error("fail6\n");
+
+    RegistryCloseKey(SubKey);
+
 fail5:
     Error("fail5\n");
 
-    RegistryCloseKey(SubKey);
+    RegistryCloseKey(NetKey);
 
 fail4:
     Error("fail4\n");
 
-    RegistryCloseKey(NetKey);
-
 fail3:
     Error("fail3\n");
 
+    RegistryCloseKey(BackupKey);
+
+    (VOID) RegistryDeleteSubKey(SoftwareKey, "Backup");
+
 fail2:
     Error("fail2\n");
 
@@ -567,3 +778,44 @@ fail1:
 
     return status;
 }
+
+NTSTATUS
+SettingsRestoreLinkage(
+    IN  HANDLE  SoftwareKey
+    )
+{
+    HANDLE      BackupKey;
+    NTSTATUS    status;
+
+    Trace("====>\n");
+
+    status = RegistryOpenSubKey(SoftwareKey,
+                                "Backup",
+                                KEY_READ,
+                                &BackupKey);
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    status = SettingsCopyLinkage(SoftwareKey,
+                                 BackupKey);
+    if (!NT_SUCCESS(status))
+        goto fail2;
+
+    RegistryCloseKey(BackupKey);
+
+    (VOID) RegistryDeleteSubKey(SoftwareKey, "Backup");
+
+    Trace("<====\n");
+
+    return STATUS_SUCCESS;
+
+fail2:
+    Error("fail2\n");
+
+    RegistryCloseKey(BackupKey);
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
diff --git a/src/xenvif/settings.h b/src/xenvif/settings.h
index 08221f2..eb77ec8 100644
--- a/src/xenvif/settings.h
+++ b/src/xenvif/settings.h
@@ -33,11 +33,22 @@
 #define _XENVIF_SETTINGS_H
 
 extern NTSTATUS
-SettingsStealIdentity(
-     IN HANDLE      SoftwareKey,
-     IN PWCHAR      Alias,
-     IN PWCHAR      Description,
-     IN LPGUID      InterfaceGuid
+SettingsSetAlias(
+     IN PWCHAR  Alias,
+     IN PWCHAR  Description,
+     IN LPGUID  InterfaceGuid,
+     IN ULONG   Number
+     );
+
+extern NTSTATUS
+SettingsStealAliasLinkage(
+     IN HANDLE  SoftwareKey,
+     IN ULONG   Number
+     );
+
+extern NTSTATUS
+SettingsRestoreLinkage(
+     IN HANDLE  SoftwareKey
      );
 
 #endif  // _XENVIF_SETTINGS_H
-- 
2.1.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

 


Rackspace

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