X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/5c19dc3ae3bd8e40a9c028b0deddd50ff337692c..914fc88e61be54aed6b18205ff2775b48793a3b6:/OSX/libsecurityd/lib/SharedMemoryClient.cpp diff --git a/OSX/libsecurityd/lib/SharedMemoryClient.cpp b/OSX/libsecurityd/lib/SharedMemoryClient.cpp index 923767dc..3acb37d2 100644 --- a/OSX/libsecurityd/lib/SharedMemoryClient.cpp +++ b/OSX/libsecurityd/lib/SharedMemoryClient.cpp @@ -8,45 +8,87 @@ #include "SharedMemoryClient.h" #include #include - -static const char* kPrefix = "/var/db/mds/messages/se_"; +#include +#include using namespace Security; -SharedMemoryClient::SharedMemoryClient (const char* segmentName, SegmentOffsetType segmentSize) +//================================================================================= +// SharedMemoryClient +//================================================================================= + +static std::string unixerrorstr(int errnum) { + string errstr; + char buf[1024]; + // might return ERANGE + /* int rx = */ strerror_r(errnum, buf, sizeof(buf)); + errstr = string(buf); + errstr += "(" + to_string(errnum) + ")"; + return errstr; +} + +SharedMemoryClient::SharedMemoryClient (const char* segmentName, SegmentOffsetType segmentSize, uid_t uid) { StLock _(mMutex); mSegmentName = segmentName; mSegmentSize = segmentSize; - mSegment = mDataArea = mDataPtr = 0; - + mSegment = (u_int8_t*) MAP_FAILED; + mDataArea = mDataPtr = 0; + mUID = uid; + + secdebug("MDSPRIVACY","[%03d] creating SharedMemoryClient with segmentName %s, size: %d", mUID, segmentName, segmentSize); + + if (segmentSize < sizeof(u_int32_t)) + return; + // make the name int segmentDescriptor; { - std::string name (kPrefix); - name += segmentName; - + std::string name(SharedMemoryCommon::SharedMemoryFilePath(mSegmentName.c_str(), mUID)); + // make a connection to the shared memory block - segmentDescriptor = open (name.c_str (), O_RDONLY, S_IROTH); + segmentDescriptor = open (name.c_str(), O_RDONLY, S_IROTH); if (segmentDescriptor < 0) // error on opening the shared memory segment? { + secdebug("MDSPRIVACY","[%03d] SharedMemoryClient open of %s failed: %s", mUID, name.c_str(), unixerrorstr(errno).c_str()); // CssmError::throwMe (CSSM_ERRCODE_INTERNAL_ERROR); return; } } + // check that the file size is large enough to support operations + struct stat statResult = {}; + int result = fstat(segmentDescriptor, &statResult); + if(result) { + secdebug("MDSPRIVACY","[%03d] SharedMemoryClient fstat failed: %d/%s", mUID, result, unixerrorstr(errno).c_str()); + UnixError::throwMe(errno); + } + + off_t sz = statResult.st_size; + if(sz < sizeof(SegmentOffsetType)) { + close(segmentDescriptor); + return; + } + + if(sz > 4*segmentSize) { + // File is too ridiculously large. Quit. + close(segmentDescriptor); + return; + } + // map the segment into place mSegment = (u_int8_t*) mmap (NULL, segmentSize, PROT_READ, MAP_SHARED, segmentDescriptor, 0); close (segmentDescriptor); if (mSegment == MAP_FAILED) { + secdebug("MDSPRIVACY","[%03d] SharedMemoryClient mmap failed: %d", mUID, errno); return; } mDataArea = mSegment + sizeof (SegmentOffsetType); - mDataMax = mSegment + segmentSize; + mDataMax = mSegment + sz; mDataPtr = mDataArea + GetProducerCount (); } @@ -54,48 +96,41 @@ SharedMemoryClient::SharedMemoryClient (const char* segmentName, SegmentOffsetTy SharedMemoryClient::~SharedMemoryClient () { - StLock _(mMutex); - if (mSegment == NULL || mSegment == MAP_FAILED) // error on opening the shared memory segment? - { - CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); - } - munmap (mSegment, mSegmentSize); + if (!uninitialized()) { + StLock _(mMutex); + munmap (mSegment, mSegmentSize); + } } - SegmentOffsetType SharedMemoryClient::GetProducerCount () { - if (mSegment == NULL || mSegment == MAP_FAILED) // error on opening the shared memory segment? - { + if (uninitialized()) { + secdebug("MDSPRIVACY","[%03d] SharedMemoryClient::GetProducerCount uninitialized", mUID); CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); } - return OSSwapBigToHostInt32 (*(u_int32_t*) mSegment); -} - - - -const char* SharedMemoryClient::GetSegmentName () -{ - return mSegmentName.c_str (); -} - - + if( ((u_int8_t*) (((u_int32_t*) mSegment) + 1)) > mDataMax) { + // Check we can actually read this u_int32_t + secdebug("MDSPRIVACY","[%03d] SharedMemoryClient::GetProducerCount uint > mDataMax", mUID); + CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); + } + + SegmentOffsetType offset = OSSwapBigToHostInt32 (*(u_int32_t*) mSegment); + if (&mSegment[offset] >= mDataMax) { + secdebug("MDSPRIVACY","[%03d] SharedMemoryClient::GetProducerCount offset > mDataMax", mUID); + CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); + } -size_t SharedMemoryClient::GetSegmentSize () -{ - return mSegmentSize; + return offset; } - - void SharedMemoryClient::ReadData (void* buffer, SegmentOffsetType length) { - if (mSegment == NULL || mSegment == MAP_FAILED) // error on opening the shared memory segment? - { - CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); - } - + if (uninitialized()) { + secdebug("MDSPRIVACY","[%03d] ReadData mSegment fail uninitialized: %p", mUID, mSegment); + CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); + } + u_int8_t* bptr = (u_int8_t*) buffer; SegmentOffsetType bytesToEnd = (SegmentOffsetType)(mDataMax - mDataPtr); @@ -135,8 +170,8 @@ bool SharedMemoryClient::ReadMessage (void* message, SegmentOffsetType &length, { StLock _(mMutex); - if (mSegment == NULL || mSegment == MAP_FAILED) // error on opening the shared memory segment? - { + if (uninitialized()) { + secdebug("MDSPRIVACY","[%03d] ReadMessage mSegment fail uninitialized: %p", mUID, mSegment); CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR); } @@ -145,6 +180,7 @@ bool SharedMemoryClient::ReadMessage (void* message, SegmentOffsetType &length, size_t offset = mDataPtr - mDataArea; if (offset == GetProducerCount()) { + secdebug("MDSPRIVACY","[%03d] ReadMessage GetProducerCount()", mUID); ur = kURNoMessage; return false; } @@ -156,14 +192,8 @@ bool SharedMemoryClient::ReadMessage (void* message, SegmentOffsetType &length, // get the length of the message stored there if (length == 0 || length >= kPoolAvailableForData) { - if (length == 0) - { - ur = kURNoMessage; - } - else - { - ur = kURBufferCorrupt; - } + secdebug("MDSPRIVACY","[%03d] ReadMessage length error: %d", mUID, length); + ur = (length == 0) ? kURNoMessage : kURBufferCorrupt; // something's gone wrong, reset. mDataPtr = mDataArea + GetProducerCount (); @@ -187,3 +217,52 @@ bool SharedMemoryClient::ReadMessage (void* message, SegmentOffsetType &length, return true; } + +//================================================================================= +// SharedMemoryCommon +//================================================================================= + +std::string SharedMemoryCommon::SharedMemoryFilePath(const char *segmentName, uid_t uid) { + std::string path; + uid = SharedMemoryCommon::fixUID(uid); + path = SharedMemoryCommon::kMDSMessagesDirectory; // i.e. /private/var/db/mds/messages/ + if (uid != 0) { + path += std::to_string(uid) + "/"; // e.g. /private/var/db/mds/messages/501/ + } + + path += SharedMemoryCommon::kUserPrefix; // e.g. /var/db/mds/messages/se_ + path += segmentName; // e.g. /var/db/mds/messages/501/se_SecurityMessages + return path; +} + +std::string SharedMemoryCommon::notificationDescription(int domain, int event) { + string domainstr, eventstr; + + switch (domain) { + case Security::SecurityServer::kNotificationDomainAll: domainstr = "all"; break; + case Security::SecurityServer::kNotificationDomainDatabase: domainstr = "database"; break; + case Security::SecurityServer::kNotificationDomainPCSC: domainstr = "pcsc"; break; + case Security::SecurityServer::kNotificationDomainCDSA: domainstr = "CDSA"; break; + default: + domainstr = "unknown"; + break; + } + + switch (event) { + case kSecLockEvent: eventstr = "lock"; break; + case kSecUnlockEvent: eventstr = "unlock"; break; + case kSecAddEvent: eventstr = "add"; break; + case kSecDeleteEvent: eventstr = "delete"; break; + case kSecUpdateEvent: eventstr = "update"; break; + case kSecPasswordChangedEvent: eventstr = "passwordChange"; break; + case kSecDefaultChangedEvent: eventstr = "defaultChange"; break; + case kSecDataAccessEvent: eventstr = "dataAccess"; break; + case kSecKeychainListChangedEvent: eventstr = "listChange"; break; + case kSecTrustSettingsChangedEvent: eventstr = "trustSettings"; break; + default: + domainstr = "unknown"; + break; + } + + return "Domain: " + domainstr + ", Event: " + eventstr; +}