]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
lib/lock: if you can't beat'em, join'em
authorVMware, Inc <>
Mon, 21 Nov 2011 23:36:24 +0000 (15:36 -0800)
committerMarcelo Vanzin <mvanzin@vmware.com>
Mon, 21 Nov 2011 23:36:24 +0000 (15:36 -0800)
Every time I change lib/lock to help find a bug it causes
problem if and only if I alter the size of a structure. This
indicates that there are multiple copies of lib/lock floating
around (known; as many as 5 copies have been observed), some that
may be incompatible with each other.

This change adds a real time signature and identification analysis
to lib/lock. It does this without changing any structure sizes. It
will help us catch the culprits and come up with a build plan to
handle this.

The run-time checking is done by having lib/lock always use a
unique signature, regardless of what type of build it is in. Any
lock that comes from a different copy of lib/lock will have a
different signature.

Previously, the signatures were static and also provided debugging
help to the type of lock.

Signed-off-by: Marcelo Vanzin <mvanzin@vmware.com>
open-vm-tools/lib/lock/ul.c
open-vm-tools/lib/lock/ulBarrier.c
open-vm-tools/lib/lock/ulExcl.c
open-vm-tools/lib/lock/ulInt.h
open-vm-tools/lib/lock/ulRW.c
open-vm-tools/lib/lock/ulRec.c
open-vm-tools/lib/lock/ulSema.c

index 6073681726ee34f1bb5d49625c8044d62bfee8ba..2bedd7575e3ac813e789a645b4485a58d6d068d7 100644 (file)
@@ -23,6 +23,7 @@
 #include "ulInt.h"
 #include "ulIntShared.h"
 #include "hashTable.h"
+#include "random.h"
 
 
 static Bool mxInPanic = FALSE;  // track when involved in a panic
@@ -85,6 +86,89 @@ MXUserInternalSingleton(Atomic_Ptr *storage)  // IN:
 }
 
 
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUserSydrome --
+ *
+ *      Generate the syndrome bits for this MXUser library.
+ *
+ *      Each MXUser library has unique syndrome bits enabling the run time
+ *      detection of locks created with one copy of the MXUser library and
+ *      passed to another copy of the MXUser library.
+ *
+ *      The syndrome bits are important as they prevent incompatible versions
+ *      of the MXUser library from trashing each other.
+ *
+ *      The bits are generated by using a source of bits that is external to
+ *      a program and its libraries. This way no code or data based scheme
+ *      can be spoofed or aliased.
+ *
+ * Results:
+ *      As above
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static uint32
+MXUserSyndrome(void)
+{
+   uint32 syndrome;
+   static Atomic_uint32 syndromeMem;  // implicitly zero -- mbellon
+
+   syndrome = Atomic_Read(&syndromeMem);
+
+   if (syndrome == 0) {
+      while (Random_Crypto(sizeof syndrome, &syndrome) && (syndrome == 0))
+         ;
+
+      if (syndrome == 0) {
+         syndrome++;  // Fudge in case of failure
+      }
+
+      /* blind write; if racing one thread or the other will do */
+      Atomic_ReadIfEqualWrite(&syndromeMem, 0, syndrome);
+
+      syndrome = Atomic_Read(&syndromeMem);
+      ASSERT(syndrome);
+   }
+
+   return syndrome;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * MXUserGetSignature --
+ *
+ *      Return a signature appropriate for the specified object type.
+ *
+ * Results:
+ *      As above
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+uint32
+MXUserGetSignature(uint32 objectType)  // IN:
+{
+   uint32 signature;
+
+   ASSERT(objectType < 16);  // 4 bits of object type
+
+   signature = (MXUserSyndrome() & 0x0FFFFFFF) | (objectType << 28);
+   ASSERT(signature);
+
+   return signature;
+}
+
 #if defined(MXUSER_DEBUG)
 #define MXUSER_MAX_LOCKS_PER_THREAD (2 * MXUSER_MAX_REC_DEPTH)
 
@@ -480,11 +564,13 @@ MXUser_TryAcquireFailureControl(Bool (*func)(const char *name))  // IN:
 
 void
 MXUserValidateHeader(MXUserHeader *header,  // IN:
-                     uint32 objectID)       // IN:
+                     uint32 objectType)     // IN:
 {
-   if (header->signature != objectID) {
+   uint32 expected = MXUserGetSignature(objectType);
+
+   if (header->signature != expected) {
       MXUserDumpAndPanic(header, "%s: expected %X observed %X\n", __FUNCTION__,
-                         objectID, header->signature);
+                         expected, header->signature);
    }
 }
 #endif
index 2b427b543472defc34dd6316af3755c2c2561649..9455224ac0feed342a853e7c70fc11842f585a17 100644 (file)
@@ -154,7 +154,7 @@ MXUser_CreateBarrier(const char *userName,  // IN: shall be known as
    barrier->configCount = count;
    barrier->curContext = 0;
 
-   barrier->header.signature = MXUSER_TYPE_BARRIER;
+   barrier->header.signature = MXUserGetSignature(MXUSER_TYPE_BARRIER);
    barrier->header.name = properName;
    barrier->header.rank = rank;
    barrier->header.serialNumber = MXUserAllocSerialNumber();
index 06d155d23a2a6edbfafac1888c089371cb9a74c7..7a504a6f7aa884a392c775d92f50760acc1b9b9b 100644 (file)
@@ -301,7 +301,7 @@ MXUser_CreateExclLock(const char *userName,  // IN:
       return NULL;
    }
 
-   lock->header.signature = MXUSER_TYPE_EXCL;
+   lock->header.signature = MXUserGetSignature(MXUSER_TYPE_EXCL);
    lock->header.name = properName;
    lock->header.rank = rank;
    lock->header.serialNumber = MXUserAllocSerialNumber();
index 063542719df9464513137ea2f3341e9059f62008..61fa6e88b62ce56fae10ef60a77a6f09adf6463f 100644 (file)
@@ -391,13 +391,17 @@ MXUserGetThreadID(void)
    return (void *) (uintptr_t) VThread_CurID();  // unsigned
 }
 
-#define MXUSER_TYPE_RW 0x57524B4C // 'LKRW' in memory
-#define MXUSER_TYPE_REC 0x43524B4C // 'LKRC' in memory
-#define MXUSER_TYPE_RANK 0x4E4B5241 // 'RANK' in memory
-#define MXUSER_TYPE_EXCL 0x58454B4C // 'LKEX' in memory
-#define MXUSER_TYPE_SEMA 0x414D4553 // 'SEMA' in memory
-#define MXUSER_TYPE_CONDVAR 0x444E4F43 // 'COND' in memory
-#define MXUSER_TYPE_BARRIER 0x52524142 // 'BARR' in memory
+/*
+ * MXUser object type ID value. They must never be zero!
+ */
+
+#define MXUSER_TYPE_RW      0x1
+#define MXUSER_TYPE_REC     0x2
+#define MXUSER_TYPE_RANK    0x3
+#define MXUSER_TYPE_EXCL    0x4
+#define MXUSER_TYPE_SEMA    0x5
+#define MXUSER_TYPE_CONDVAR 0x6
+#define MXUSER_TYPE_BARRIER 0x7
 
 /*
  * MXUser header - all MXUser objects start with this
@@ -424,6 +428,8 @@ void MXUserDumpAndPanic(MXUserHeader *header,
 
 MXRecLock *MXUserInternalSingleton(Atomic_Ptr *storage);
 
+uint32 MXUserGetSignature(uint32 objectType);
+
 #if defined(MXUSER_DEBUG)
 void MXUserAcquisitionTracking(MXUserHeader *header,
                            Bool checkRank);
@@ -431,7 +437,7 @@ void MXUserAcquisitionTracking(MXUserHeader *header,
 void MXUserReleaseTracking(MXUserHeader *header);
 
 void MXUserValidateHeader(MXUserHeader *header,
-                          uint32 objectID);
+                          uint32 objectType);
 #else
 static INLINE void
 MXUserAcquisitionTracking(MXUserHeader *header,  // IN:
@@ -448,7 +454,7 @@ MXUserReleaseTracking(MXUserHeader *header)  // IN:
 
 static INLINE void
 MXUserValidateHeader(MXUserHeader *header,  // IN:
-                     uint32 objectID)       // IN:
+                     uint32 objectType)     // IN:
 {
    return;
 }
index 3d21b1f18e93583c185185ef522342d29c6eb6a1..8d0471a3a3cc921ab338c1ed13d3b51ac502a7ca 100644 (file)
@@ -529,7 +529,7 @@ MXUser_CreateRWLock(const char *userName,  // IN:
       properName = Util_SafeStrdup(userName);
    }
 
-   lock->header.signature = MXUSER_TYPE_RW;
+   lock->header.signature = MXUserGetSignature(MXUSER_TYPE_RW);
    lock->header.name = properName;
    lock->header.rank = rank;
    lock->header.serialNumber = MXUserAllocSerialNumber();
index ff5e75805b3ffc00c1d1d275727da2b032c75e61..b01f33a0cac35ae3327be6be96971d53d2efaab3 100644 (file)
@@ -333,7 +333,7 @@ MXUserCreateRecLock(const char *userName,  // IN:
    lock->vmmLock = NULL;
    Atomic_Write(&lock->refCount, 1);
 
-   lock->header.signature = MXUSER_TYPE_REC;
+   lock->header.signature = MXUserGetSignature(MXUSER_TYPE_REC);
    lock->header.name = properName;
    lock->header.rank = rank;
    lock->header.serialNumber = MXUserAllocSerialNumber();
@@ -1014,7 +1014,7 @@ MXUser_BindMXMutexRec(struct MX_MutexRec *mutex,  // IN:
 
    lock = Util_SafeCalloc(1, sizeof(*lock));
 
-   lock->header.signature = MXUSER_TYPE_REC;
+   lock->header.signature = MXUserGetSignature(MXUSER_TYPE_REC);
    lock->header.name = Str_SafeAsprintf(NULL, "MX_%p", mutex);
    lock->header.rank = rank;
    lock->header.serialNumber = MXUserAllocSerialNumber();
index f1f4a254784591a1d418d6b1de4f31b8cc451291..c84f0cea4ceeaa05ca94ff0357cff67ff179e6ce 100644 (file)
@@ -514,7 +514,7 @@ MXUser_CreateSemaphore(const char *userName,  // IN:
    if (LIKELY(MXUserInit(&sema->nativeSemaphore) == 0)) {
       MXUserStats *stats;
 
-      sema->header.signature = MXUSER_TYPE_SEMA;
+      sema->header.signature = MXUserGetSignature(MXUSER_TYPE_SEMA);
       sema->header.name = properName;
       sema->header.rank = rank;
       sema->header.serialNumber = MXUserAllocSerialNumber();