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

[PATCH] Avoid race when checking for an active transaction



From: Paul Durrant <pdurrant@xxxxxxxxxx>

The code in StoreTransactionEnd() checks, under the protection of Context->Lock,
that the transaction is active. It then drops the lock and calls
StorePrepareRequest(), which also tests whether the transaction is active but
*not* under the protection of the lock. If the domain is suspended and resumed
in between the two checks then this will cause StorePrepareRequest() to fail
for non-NULL transactions.
This patch makes sure that Context->Lock is held across all calls to
StorePrepareRequest(), along with any prior tests for whether transactions or
watches are active, and drops the internal acquisition of the lock (which was
done to protect the increment of Context->RequestId).

Reported-by: Owen Smith <owen.smith@xxxxxxxxxx>
Signed-off-by: Paul Durrant <pdurrant@xxxxxxxxxx>
---
 src/xenbus/store.c | 64 +++++++++++++++++++++++++++++++++++-----------
 1 file changed, 49 insertions(+), 15 deletions(-)

diff --git a/src/xenbus/store.c b/src/xenbus/store.c
index 5ffea1fe4859..028fd59f07b6 100644
--- a/src/xenbus/store.c
+++ b/src/xenbus/store.c
@@ -180,7 +180,6 @@ StorePrepareRequest(
     )
 {
     ULONG                           Id;
-    KIRQL                           Irql;
     PXENBUS_STORE_SEGMENT           Segment;
     va_list                         Arguments;
     NTSTATUS                        status;
@@ -200,10 +199,7 @@ StorePrepareRequest(
     Request->Header.type = Type;
     Request->Header.tx_id = Id;
     Request->Header.len = 0;
-
-    KeAcquireSpinLock(&Context->Lock, &Irql);
     Request->Header.req_id = Context->RequestId++;
-    KeReleaseSpinLock(&Context->Lock, Irql);
 
     Request->Count = 0;
     Segment = &Request->Segment[Request->Count++];
@@ -1102,6 +1098,7 @@ StoreRead(
     PXENBUS_STORE_CONTEXT           Context = Interface->Context;
     PVOID                           Caller;
     XENBUS_STORE_REQUEST            Request;
+    KIRQL                           Irql;
     PXENBUS_STORE_RESPONSE          Response;
     PXENBUS_STORE_BUFFER            Buffer;
     NTSTATUS                        status;
@@ -1110,6 +1107,8 @@ StoreRead(
 
     RtlZeroMemory(&Request, sizeof (XENBUS_STORE_REQUEST));
 
+    KeAcquireSpinLock(&Context->Lock, &Irql);
+
     if (Prefix == NULL) {
         status = StorePrepareRequest(Context,
                                      &Request,
@@ -1130,6 +1129,8 @@ StoreRead(
                                      NULL, 0);
     }
 
+    KeReleaseSpinLock(&Context->Lock, Irql);
+
     if (!NT_SUCCESS(status))
         goto fail1;
 
@@ -1177,11 +1178,14 @@ StoreWrite(
     )
 {
     XENBUS_STORE_REQUEST            Request;
+    KIRQL                           Irql;
     PXENBUS_STORE_RESPONSE          Response;
     NTSTATUS                        status;
 
     RtlZeroMemory(&Request, sizeof (XENBUS_STORE_REQUEST));
 
+    KeAcquireSpinLock(&Context->Lock, &Irql);
+
     if (Prefix == NULL) {
         status = StorePrepareRequest(Context,
                                      &Request,
@@ -1204,6 +1208,8 @@ StoreWrite(
                                      NULL, 0);
     }
 
+    KeReleaseSpinLock(&Context->Lock, Irql);
+
     if (!NT_SUCCESS(status))
         goto fail1;
 
@@ -1326,11 +1332,14 @@ StoreRemove(
 {
     PXENBUS_STORE_CONTEXT           Context = Interface->Context;
     XENBUS_STORE_REQUEST            Request;
+    KIRQL                           Irql;
     PXENBUS_STORE_RESPONSE          Response;
     NTSTATUS                        status;
 
     RtlZeroMemory(&Request, sizeof (XENBUS_STORE_REQUEST));
 
+    KeAcquireSpinLock(&Context->Lock, &Irql);
+
     if (Prefix == NULL) {
         status = StorePrepareRequest(Context,
                                      &Request,
@@ -1351,6 +1360,8 @@ StoreRemove(
                                      NULL, 0);
     }
 
+    KeReleaseSpinLock(&Context->Lock, Irql);
+
     if (!NT_SUCCESS(status))
         goto fail1;
 
@@ -1391,6 +1402,7 @@ StoreDirectory(
     PXENBUS_STORE_CONTEXT           Context = Interface->Context;
     PVOID                           Caller;
     XENBUS_STORE_REQUEST            Request;
+    KIRQL                           Irql;
     PXENBUS_STORE_RESPONSE          Response;
     PXENBUS_STORE_BUFFER            Buffer;
     NTSTATUS                        status;
@@ -1399,6 +1411,8 @@ StoreDirectory(
 
     RtlZeroMemory(&Request, sizeof (XENBUS_STORE_REQUEST));
 
+    KeAcquireSpinLock(&Context->Lock, &Irql);
+
     if (Prefix == NULL) {
         status = StorePrepareRequest(Context,
                                      &Request,
@@ -1419,6 +1433,8 @@ StoreDirectory(
                                      NULL, 0);
     }
 
+    KeReleaseSpinLock(&Context->Lock, Irql);
+
     if (!NT_SUCCESS(status))
         goto fail1;
 
@@ -1486,12 +1502,17 @@ StoreTransactionStart(
 
     RtlZeroMemory(&Request, sizeof (XENBUS_STORE_REQUEST));
 
+    KeAcquireSpinLock(&Context->Lock, &Irql);
+
     status = StorePrepareRequest(Context,
                                  &Request,
                                  NULL,
                                  XS_TRANSACTION_START,
                                  "", 1,
                                  NULL, 0);
+
+    KeReleaseSpinLock(&Context->Lock, Irql);
+
     ASSERT(NT_SUCCESS(status));
 
     Response = StoreSubmitRequest(Context, &Request);
@@ -1555,22 +1576,23 @@ StoreTransactionEnd(
 
     ASSERT3U(Transaction->Magic, ==, STORE_TRANSACTION_MAGIC);
 
+    RtlZeroMemory(&Request, sizeof (XENBUS_STORE_REQUEST));
+
     KeAcquireSpinLock(&Context->Lock, &Irql);
 
     status = STATUS_RETRY;
     if (!Transaction->Active)
         goto done;
 
-    KeReleaseSpinLock(&Context->Lock, Irql);
-
-    RtlZeroMemory(&Request, sizeof (XENBUS_STORE_REQUEST));
-
     status = StorePrepareRequest(Context,
                                  &Request,
                                  Transaction,
                                  XS_TRANSACTION_END,
                                  (Commit) ? "T" : "F", 2,
                                  NULL, 0);
+
+    KeReleaseSpinLock(&Context->Lock, Irql);
+
     ASSERT(NT_SUCCESS(status));
 
     Response = StoreSubmitRequest(Context, &Request);
@@ -1678,6 +1700,8 @@ StoreWatchAdd(
 
     RtlZeroMemory(&Request, sizeof (XENBUS_STORE_REQUEST));
 
+    KeAcquireSpinLock(&Context->Lock, &Irql);
+
     status = StorePrepareRequest(Context,
                                  &Request,
                                  NULL,
@@ -1687,6 +1711,9 @@ StoreWatchAdd(
                                  Token, strlen(Token), 
                                  "", 1,
                                  NULL, 0);
+
+    KeReleaseSpinLock(&Context->Lock, Irql);
+
     ASSERT(NT_SUCCESS(status));
 
     Response = StoreSubmitRequest(Context, &Request);
@@ -1760,13 +1787,6 @@ StoreWatchRemove(
 
     Path = Watch->Path;
 
-    KeAcquireSpinLock(&Context->Lock, &Irql);
-
-    if (!Watch->Active)
-        goto done;
-
-    KeReleaseSpinLock(&Context->Lock, Irql);
-
     status = RtlStringCbPrintfA(Token,
                                 sizeof (Token),
                                 "TOK|%p|%04X",
@@ -1777,6 +1797,11 @@ StoreWatchRemove(
 
     RtlZeroMemory(&Request, sizeof (XENBUS_STORE_REQUEST));
 
+    KeAcquireSpinLock(&Context->Lock, &Irql);
+
+    if (!Watch->Active)
+        goto done;
+
     status = StorePrepareRequest(Context,
                                  &Request,
                                  NULL,
@@ -1786,6 +1811,9 @@ StoreWatchRemove(
                                  Token, strlen(Token), 
                                  "", 1,
                                  NULL, 0);
+
+    KeReleaseSpinLock(&Context->Lock, Irql);
+
     ASSERT(NT_SUCCESS(status));
 
     Response = StoreSubmitRequest(Context, &Request);
@@ -2002,6 +2030,7 @@ StorePermissionsSet(
 {
     PXENBUS_STORE_CONTEXT           Context = Interface->Context;
     XENBUS_STORE_REQUEST            Request;
+    KIRQL                           Irql;
     PXENBUS_STORE_RESPONSE          Response;
     NTSTATUS                        status;
     ULONG                           Index;
@@ -2048,6 +2077,8 @@ StorePermissionsSet(
         Length -= Used;
     }
 
+    KeAcquireSpinLock(&Context->Lock, &Irql);
+
     status = StorePrepareRequest(Context,
                                  &Request,
                                  Transaction,
@@ -2056,6 +2087,9 @@ StorePermissionsSet(
                                  "", 1,
                                  PermissionString, XENSTORE_PAYLOAD_MAX - 
Length,
                                  NULL, 0);
+
+    KeReleaseSpinLock(&Context->Lock, Irql);
+
     if (!NT_SUCCESS(status))
         goto fail4;
 
-- 
2.25.1




 


Rackspace

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