From: VMware, Inc <> Date: Mon, 21 Nov 2011 23:36:24 +0000 (-0800) Subject: lib/lock: if you can't beat'em, join'em X-Git-Tag: 2011.11.20-535097~30 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=67808f366a18d5c2e77b01af951cd349643143c2;p=thirdparty%2Fopen-vm-tools.git lib/lock: if you can't beat'em, join'em 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 --- diff --git a/open-vm-tools/lib/lock/ul.c b/open-vm-tools/lib/lock/ul.c index 607368172..2bedd7575 100644 --- a/open-vm-tools/lib/lock/ul.c +++ b/open-vm-tools/lib/lock/ul.c @@ -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 diff --git a/open-vm-tools/lib/lock/ulBarrier.c b/open-vm-tools/lib/lock/ulBarrier.c index 2b427b543..9455224ac 100644 --- a/open-vm-tools/lib/lock/ulBarrier.c +++ b/open-vm-tools/lib/lock/ulBarrier.c @@ -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(); diff --git a/open-vm-tools/lib/lock/ulExcl.c b/open-vm-tools/lib/lock/ulExcl.c index 06d155d23..7a504a6f7 100644 --- a/open-vm-tools/lib/lock/ulExcl.c +++ b/open-vm-tools/lib/lock/ulExcl.c @@ -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(); diff --git a/open-vm-tools/lib/lock/ulInt.h b/open-vm-tools/lib/lock/ulInt.h index 063542719..61fa6e88b 100644 --- a/open-vm-tools/lib/lock/ulInt.h +++ b/open-vm-tools/lib/lock/ulInt.h @@ -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; } diff --git a/open-vm-tools/lib/lock/ulRW.c b/open-vm-tools/lib/lock/ulRW.c index 3d21b1f18..8d0471a3a 100644 --- a/open-vm-tools/lib/lock/ulRW.c +++ b/open-vm-tools/lib/lock/ulRW.c @@ -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(); diff --git a/open-vm-tools/lib/lock/ulRec.c b/open-vm-tools/lib/lock/ulRec.c index ff5e75805..b01f33a0c 100644 --- a/open-vm-tools/lib/lock/ulRec.c +++ b/open-vm-tools/lib/lock/ulRec.c @@ -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(); diff --git a/open-vm-tools/lib/lock/ulSema.c b/open-vm-tools/lib/lock/ulSema.c index f1f4a2547..c84f0cea4 100644 --- a/open-vm-tools/lib/lock/ulSema.c +++ b/open-vm-tools/lib/lock/ulSema.c @@ -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();