From: Oliver Kurth Date: Fri, 27 Jul 2018 18:46:20 +0000 (-0700) Subject: Changes to common source files; not directly applicable to open-vm-tools X-Git-Tag: stable-11.0.0~520 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=58a05f680a7c11eeb2fbb576579969c1895bb01d;p=thirdparty%2Fopen-vm-tools.git Changes to common source files; not directly applicable to open-vm-tools 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. --- diff --git a/open-vm-tools/lib/lock/ul.c b/open-vm-tools/lib/lock/ul.c index b68d8c5b5..eb9c6a58b 100644 --- a/open-vm-tools/lib/lock/ul.c +++ b/open-vm-tools/lib/lock/ul.c @@ -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__); diff --git a/open-vm-tools/lib/lock/ulBarrier.c b/open-vm-tools/lib/lock/ulBarrier.c index f88758b69..b207fe630 100644 --- a/open-vm-tools/lib/lock/ulBarrier.c +++ b/open-vm-tools/lib/lock/ulBarrier.c @@ -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; diff --git a/open-vm-tools/lib/lock/ulExcl.c b/open-vm-tools/lib/lock/ulExcl.c index a9eef59ca..81c5ab26f 100644 --- a/open-vm-tools/lib/lock/ulExcl.c +++ b/open-vm-tools/lib/lock/ulExcl.c @@ -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(); diff --git a/open-vm-tools/lib/lock/ulInt.h b/open-vm-tools/lib/lock/ulInt.h index 49334d65e..f6e6ce708 100644 --- a/open-vm-tools/lib/lock/ulInt.h +++ b/open-vm-tools/lib/lock/ulInt.h @@ -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); diff --git a/open-vm-tools/lib/lock/ulIntShared.h b/open-vm-tools/lib/lock/ulIntShared.h index 8ed59b5f8..2f4ba000e 100644 --- a/open-vm-tools/lib/lock/ulIntShared.h +++ b/open-vm-tools/lib/lock/ulIntShared.h @@ -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 diff --git a/open-vm-tools/lib/lock/ulRW.c b/open-vm-tools/lib/lock/ulRW.c index fc801f44e..19654a7a5 100644 --- a/open-vm-tools/lib/lock/ulRW.c +++ b/open-vm-tools/lib/lock/ulRW.c @@ -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; /* diff --git a/open-vm-tools/lib/lock/ulRec.c b/open-vm-tools/lib/lock/ulRec.c index f366bae54..1dc925758 100644 --- a/open-vm-tools/lib/lock/ulRec.c +++ b/open-vm-tools/lib/lock/ulRec.c @@ -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; diff --git a/open-vm-tools/lib/lock/ulSema.c b/open-vm-tools/lib/lock/ulSema.c index 82ec5367f..31993aeff 100644 --- a/open-vm-tools/lib/lock/ulSema.c +++ b/open-vm-tools/lib/lock/ulSema.c @@ -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(); diff --git a/open-vm-tools/lib/lock/ulStats.c b/open-vm-tools/lib/lock/ulStats.c index 58bc68747..32e696e4b 100644 --- a/open-vm-tools/lib/lock/ulStats.c +++ b/open-vm-tools/lib/lock/ulStats.c @@ -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__); }