]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
Changes to common source files; not directly applicable to open-vm-tools
authorOliver Kurth <okurth@vmware.com>
Fri, 27 Jul 2018 18:46:20 +0000 (11:46 -0700)
committerOliver Kurth <okurth@vmware.com>
Fri, 27 Jul 2018 18:46:20 +0000 (11:46 -0700)
MXUser: Lock tracking causes panic

MXUser locks require a unique serial number so the lock stats code
can proprly differentiate between each lock. We can't depend on the
name to be unique as some locks are created and deleted many times,
reusing their names.

The serial number is also used to avoid ASLR attacks... we can't use
the address of a lock... and even if we did, it's possible for that
address to be reused... MXUser locks are dynamically allocated.

The lock tracking code tracks the number of locks and this is now
causing an issue. Way back when it was thought that seeing what
was deemed a huge number of locks indicated a problem... but today
we think those limits are getting quite small.

Enlarge the serial number space to 64-bits. If we constantly create 1M
locks per second it would take over 500000 years before we would have
a problem like this again.

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/ulIntShared.h
open-vm-tools/lib/lock/ulRW.c
open-vm-tools/lib/lock/ulRec.c
open-vm-tools/lib/lock/ulSema.c
open-vm-tools/lib/lock/ulStats.c

index b68d8c5b5bcb6b339c1e2cb4c05f385850bd0463..eb9c6a58bf4acda36973d2b173ce83e18c4c1ff7 100644 (file)
@@ -1,5 +1,5 @@
 /*********************************************************
- * Copyright (C) 2009-2017 VMware, Inc. All rights reserved.
+ * Copyright (C) 2009-2018 VMware, Inc. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU Lesser General Public License as published
@@ -813,7 +813,7 @@ MXUserAcquisitionTracking(MXUserHeader *header,  // IN:
          header = perThread->lockArray[i];
 
          node = MXUserLockTreeAdd(node, header->name,
-                                  header->bits.serialNumber, header->rank);
+                                  header->serialNumber, header->rank);
       }
 
       MXUserLockTreeRelease();
@@ -930,12 +930,12 @@ MXUserValidateHeader(MXUserHeader *header,         // IN:
 {
    uint32 expected = MXUserGetSignature(objectType);
 
-   if (header->bits.badHeader == 1) {
+   if (header->badHeader) {
       return; // No need to panic on a bad header repeatedly...
    }
 
    if (header->signature != expected) {
-      header->bits.badHeader = 1;
+      header->badHeader = TRUE;
 
       MXUserDumpAndPanic(header,
                         "%s: signature failure! expected 0x%X observed 0x%X\n",
@@ -943,8 +943,8 @@ MXUserValidateHeader(MXUserHeader *header,         // IN:
 
    }
 
-   if (header->bits.serialNumber == 0) {
-      header->bits.badHeader = 1;
+   if (header->serialNumber == 0) {
+      header->badHeader = TRUE;
 
       MXUserDumpAndPanic(header, "%s: Invalid serial number!\n",
                          __FUNCTION__);
index f88758b69776f6f9e21293d5dee75ef495ef8a2f..b207fe63001263d465fe9865e63def21f5e58d18 100644 (file)
@@ -1,5 +1,5 @@
 /*********************************************************
- * Copyright (C) 2010-2016 VMware, Inc. All rights reserved.
+ * Copyright (C) 2010-2018 VMware, Inc. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU Lesser General Public License as published
@@ -67,7 +67,7 @@ MXUserDumpBarrier(MXUserHeader *header)  // IN:
    Warning("\tsignature 0x%X\n", barrier->header.signature);
    Warning("\tname %s\n", barrier->header.name);
    Warning("\trank 0x%X\n", barrier->header.rank);
-   Warning("\tserial number %u\n", barrier->header.bits.serialNumber);
+   Warning("\tserial number %"FMT64"u\n", barrier->header.serialNumber);
 
    Warning("\tlock 0x%p\n", barrier->lock);
    Warning("\tconfigured count %u\n", barrier->configCount);
@@ -136,7 +136,7 @@ MXUser_CreateBarrier(const char *userName,  // IN: shall be known as
    barrier->header.signature = MXUserGetSignature(MXUSER_TYPE_BARRIER);
    barrier->header.name = properName;
    barrier->header.rank = rank;
-   barrier->header.bits.serialNumber = MXUserAllocSerialNumber();
+   barrier->header.serialNumber = MXUserAllocSerialNumber();
    barrier->header.dumpFunc = MXUserDumpBarrier;
    barrier->header.statsFunc = NULL;
 
index a9eef59ca8107a3d1bbdfc165f94d02657779093..81c5ab26f2a6419ca4bfd71285441386102b0af3 100644 (file)
@@ -1,5 +1,5 @@
 /*********************************************************
- * Copyright (C) 2009-2017 VMware, Inc. All rights reserved.
+ * Copyright (C) 2009-2018 VMware, Inc. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU Lesser General Public License as published
@@ -304,7 +304,7 @@ MXUserDumpExclLock(MXUserHeader *header)  // IN:
    Warning("\tsignature 0x%X\n", lock->header.signature);
    Warning("\tname %s\n", lock->header.name);
    Warning("\trank 0x%X\n", lock->header.rank);
-   Warning("\tserial number %u\n", lock->header.bits.serialNumber);
+   Warning("\tserial number %"FMT64"u\n", lock->header.serialNumber);
 
    Warning("\tlock count %d\n", MXRecLockCount(&lock->recursiveLock));
 
@@ -350,7 +350,7 @@ MXUser_CreateExclLock(const char *userName,  // IN:
    lock->header.signature = MXUserGetSignature(MXUSER_TYPE_EXCL);
    lock->header.name = properName;
    lock->header.rank = rank;
-   lock->header.bits.serialNumber = MXUserAllocSerialNumber();
+   lock->header.serialNumber = MXUserAllocSerialNumber();
    lock->header.dumpFunc = MXUserDumpExclLock;
 
    statsMode = MXUserStatsMode();
index 49334d65e10bf5142934ffd56975cebb45ac97ad..f6e6ce7082a263a7f9a0ac5a9dcfed8abaef4f1f 100644 (file)
@@ -454,18 +454,16 @@ typedef enum {
  */
 
 typedef struct MXUserHeader {
-   uint32       signature;
    char        *name;
+   uint32       signature;
    MX_Rank      rank;
 
-   struct {
-      unsigned int serialNumber : 24;
-      unsigned int badHeader: 1;
-   } bits;
-
    void       (*dumpFunc)(struct MXUserHeader *);
    void       (*statsFunc)(struct MXUserHeader *);
    ListItem     item;
+
+   uint64       serialNumber;
+   Bool         badHeader;
 } MXUserHeader;
 
 
@@ -568,7 +566,7 @@ typedef struct
    Atomic_Ptr        histo;
 } MXUserHeldStats;
 
-uint32 MXUserAllocSerialNumber(void);
+uint64 MXUserAllocSerialNumber(void);
 
 void MXUserAddToList(MXUserHeader *header);
 void MXUserRemoveFromList(MXUserHeader *header);
index 8ed59b5f86619531b201fbb1869e2251b6134a37..2f4ba000e3b536a5206dc39d4ee9c374f3e493b2 100644 (file)
@@ -1,5 +1,5 @@
 /*********************************************************
- * Copyright (C) 2010-2016 VMware, Inc. All rights reserved.
+ * Copyright (C) 2010-2018 VMware, Inc. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU Lesser General Public License as published
@@ -49,7 +49,7 @@ void MXUserLockTreeRelease(void);
 
 MXUserLockTreeNode *MXUserLockTreeAdd(MXUserLockTreeNode *searchNode,
                                       const char *name,
-                                      uint32 serialNumber,
+                                      uint64 serialNumber,
                                       MX_Rank rank);
 
 #endif
index fc801f44e5c0d696be2f8275b9bc9bdb0734350c..19654a7a5bfa9920716f83e59f1f91668c78a365 100644 (file)
@@ -1,5 +1,5 @@
 /*********************************************************
- * Copyright (C) 2009-2017 VMware, Inc. All rights reserved.
+ * Copyright (C) 2009-2018 VMware, Inc. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU Lesser General Public License as published
@@ -352,7 +352,7 @@ MXUserDumpRWLock(MXUserHeader *header)  // IN:
    Warning("\tsignature 0x%X\n", lock->header.signature);
    Warning("\tname %s\n", lock->header.name);
    Warning("\trank 0x%X\n", lock->header.rank);
-   Warning("\tserial number %u\n", lock->header.bits.serialNumber);
+   Warning("\tserial number %"FMT64"u\n", lock->header.serialNumber);
 
    if (LIKELY(lock->useNative)) {
       Warning("\taddress of native lock 0x%p\n", &lock->nativeLock);
@@ -413,7 +413,7 @@ MXUser_CreateRWLock(const char *userName,  // IN:
    lock->header.signature = MXUserGetSignature(MXUSER_TYPE_RW);
    lock->header.name = properName;
    lock->header.rank = rank;
-   lock->header.bits.serialNumber = MXUserAllocSerialNumber();
+   lock->header.serialNumber = MXUserAllocSerialNumber();
    lock->header.dumpFunc = MXUserDumpRWLock;
 
    /*
index f366bae5439bfcb13f24fa97bdd535204bbc8856..1dc9257580fe451a75604c7a05c886e582ac05be 100644 (file)
@@ -1,5 +1,5 @@
 /*********************************************************
- * Copyright (C) 2009-2017 VMware, Inc. All rights reserved.
+ * Copyright (C) 2009-2018 VMware, Inc. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU Lesser General Public License as published
@@ -318,7 +318,7 @@ MXUserDumpRecLock(MXUserHeader *header)  // IN:
    Warning("\tsignature 0x%X\n", lock->header.signature);
    Warning("\tname %s\n", lock->header.name);
    Warning("\trank 0x%X\n", lock->header.rank);
-   Warning("\tserial number %u\n", lock->header.bits.serialNumber);
+   Warning("\tserial number %"FMT64"u\n", lock->header.serialNumber);
    Warning("\treference count %u\n", Atomic_Read(&lock->refCount));
 
    if (lock->vmmLock == NULL) {
@@ -375,7 +375,7 @@ MXUser_CreateRecLock(const char *userName,  // IN:
    lock->header.signature = MXUserGetSignature(MXUSER_TYPE_REC);
    lock->header.name = properName;
    lock->header.rank = rank;
-   lock->header.bits.serialNumber = MXUserAllocSerialNumber();
+   lock->header.serialNumber = MXUserAllocSerialNumber();
    lock->header.dumpFunc = MXUserDumpRecLock;
 
    statsMode = MXUserStatsMode();
@@ -992,7 +992,7 @@ MXUser_BindMXMutexRec(struct MX_MutexRec *mutex,  // IN:
    }
 
    lock->header.rank = rank;
-   lock->header.bits.serialNumber = MXUserAllocSerialNumber();
+   lock->header.serialNumber = MXUserAllocSerialNumber();
    lock->header.dumpFunc = NULL;
    lock->header.statsFunc = NULL;
 
index 82ec5367f6894cd8cd718a47bfcd4eb3d17b87b6..31993aeff08940d7c004fd8e4596083054e7bf4f 100644 (file)
@@ -1,5 +1,5 @@
 /*********************************************************
- * Copyright (C) 2010-2017 VMware, Inc. All rights reserved.
+ * Copyright (C) 2010-2018 VMware, Inc. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU Lesser General Public License as published
@@ -418,7 +418,7 @@ MXUserDumpSemaphore(MXUserHeader *header)  // IN:
    Warning("\tsignature 0x%X\n", sema->header.signature);
    Warning("\tname %s\n", sema->header.name);
    Warning("\trank 0x%X\n", sema->header.rank);
-   Warning("\tserial number %u\n", sema->header.bits.serialNumber);
+   Warning("\tserial number %"FMT64"u\n", sema->header.serialNumber);
 
    Warning("\treference count %u\n", Atomic_Read(&sema->activeUserCount));
    Warning("\taddress of native semaphore %p\n", &sema->nativeSemaphore);
@@ -464,7 +464,7 @@ MXUser_CreateSemaphore(const char *userName,  // IN:
       sema->header.signature = MXUserGetSignature(MXUSER_TYPE_SEMA);
       sema->header.name = properName;
       sema->header.rank = rank;
-      sema->header.bits.serialNumber = MXUserAllocSerialNumber();
+      sema->header.serialNumber = MXUserAllocSerialNumber();
       sema->header.dumpFunc = MXUserDumpSemaphore;
 
       statsMode = MXUserStatsMode();
index 58bc68747cecc9e782e56464abb8405fb81538fd..32e696e4b292f31fa47bf7d3d0aa396bc7048621 100644 (file)
@@ -347,8 +347,9 @@ MXUserHistoDump(MXUserHisto *histo,    // IN:
       ASSERT(mxUserHistoLine != NULL);
 
       i = Str_Sprintf(mxUserHistoLine, mxUserMaxLineLength,
-                      "MXUser: h l=%u t=%s min=%"FMT64"u max=%"FMT64"u\n",
-                      header->bits.serialNumber, histo->typeName,
+                      "MXUser: h l=%"FMT64"u t=%s min=%"FMT64"u "
+                      "max=%"FMT64"u\n",
+                      header->serialNumber, histo->typeName,
                       histo->minValue, histo->maxValue);
 
       /*
@@ -525,9 +526,9 @@ MXUserDumpBasicStats(MXUserBasicStats *stats,  // IN:
       stdDev = (variance < 0.0) ? 0 : (uint64) (MXUserSqrt(variance) + 0.5);
    }
 
-   MXUserStatsLog("MXUser: e l=%u t=%s c=%"FMT64"u min=%"FMT64"u "
+   MXUserStatsLog("MXUser: e l=%"FMT64"u t=%s c=%"FMT64"u min=%"FMT64"u "
                   "max=%"FMT64"u mean=%"FMT64"u sd=%"FMT64"u\n",
-                  header->bits.serialNumber, stats->typeName,
+                  header->serialNumber, stats->typeName,
                   stats->numSamples, stats->minTime, stats->maxTime,
                   stats->timeSum/stats->numSamples, stdDev);
 }
@@ -658,9 +659,9 @@ MXUserDumpAcquisitionStats(MXUserAcquisitionStats *stats,  // IN:
          MXUserDumpBasicStats(&stats->basicStats, header);
       }
 
-      MXUserStatsLog("MXUser: ce l=%u a=%"FMT64"u s=%"FMT64"u sc=%"FMT64"u "
-                     "sct=%"FMT64"u t=%"FMT64"u\n",
-                     header->bits.serialNumber,
+      MXUserStatsLog("MXUser: ce l=%"FMT64"u a=%"FMT64"u s=%"FMT64"u "
+                     "sc=%"FMT64"u sct=%"FMT64"u t=%"FMT64"u\n",
+                     header->serialNumber,
                      stats->numAttempts,
                      stats->numSuccesses,
                      stats->numSuccessesContended,
@@ -1018,8 +1019,8 @@ MXUser_PerLockData(void)
 
    if (listLock && MXRecLockTryAcquire(listLock)) {
       ListItem *entry;
-      uint32 highestSerialNumber;
-      static uint32 lastReportedSerialNumber = 0;
+      uint64 highestSerialNumber;
+      static uint64 lastReportedSerialNumber = 0;
 
       highestSerialNumber = lastReportedSerialNumber;
 
@@ -1027,12 +1028,12 @@ MXUser_PerLockData(void)
          MXUserHeader *header = CIRC_LIST_CONTAINER(entry, MXUserHeader, item);
 
          /* Log the ID information for a lock that did exist previously */
-         if (header->bits.serialNumber > lastReportedSerialNumber) {
-            MXUserStatsLog("MXUser: n n=%s l=%d r=0x%x\n", header->name,
-                           header->bits.serialNumber, header->rank);
+         if (header->serialNumber > lastReportedSerialNumber) {
+            MXUserStatsLog("MXUser: n n=%s l=%"FMT64"u r=0x%x\n", header->name,
+                           header->serialNumber, header->rank);
 
-            if (header->bits.serialNumber > highestSerialNumber) {
-               highestSerialNumber = header->bits.serialNumber;
+            if (header->serialNumber > highestSerialNumber) {
+               highestSerialNumber = header->serialNumber;
             }
          }
 
@@ -1070,21 +1071,16 @@ MXUser_PerLockData(void)
  *-----------------------------------------------------------------------------
  */
 
-uint32
+uint64
 MXUserAllocSerialNumber(void)
 {
-   uint32 value;
-
-   static Atomic_uint32 firstFreeSerialNumber = { 1 };  // must start not zero
+   uint64 value;
 
-   value = Atomic_ReadInc32(&firstFreeSerialNumber);
+   static Atomic_uint64 firstFreeSerialNumber = { 1 };  // must start not zero
 
-   /*
-    * The serial number must be able to fit into the serial number field
-    * (see ulInt.h).
-    */
+   value = Atomic_ReadInc64(&firstFreeSerialNumber);
 
-   if (value > 0xFFFFFF) {
+   if (value == 0) {  // We wrapped! Zounds!
       Panic("%s: too many locks!\n", __FUNCTION__);
    }