X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/securityd/src/SharedMemoryServer.cpp?ds=sidebyside diff --git a/securityd/src/SharedMemoryServer.cpp b/securityd/src/SharedMemoryServer.cpp new file mode 100644 index 00000000..699542c6 --- /dev/null +++ b/securityd/src/SharedMemoryServer.cpp @@ -0,0 +1,169 @@ +#include "SharedMemoryServer.h" +#include +#include +#include +#include +#include +#include +#include +#include + +static const char* kPrefix = "/private/var/db/mds/messages/se_"; + +SharedMemoryServer::SharedMemoryServer (const char* segmentName, SegmentOffsetType segmentSize) : + mSegmentName (segmentName), mSegmentSize (segmentSize) +{ + mFileName = kPrefix; + mFileName += segmentName; + + // make the mds directory, just in case it doesn't exist + mkdir("/var/db/mds", 1777); + mkdir("/var/db/mds/messages", 0755); + + // make the file name + // clean any old file away + unlink (mFileName.c_str ()); + + // open the file + int segmentDescriptor = open (mFileName.c_str (), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + if (segmentDescriptor < 0) + { + return; + } + + // set the segment size + ftruncate (segmentDescriptor, segmentSize); + + // map it into memory + mSegment = (u_int8_t*) mmap (NULL, mSegmentSize, PROT_READ | PROT_WRITE, MAP_SHARED, segmentDescriptor, 0); + close (segmentDescriptor); + + if (mSegment == (u_int8_t*) -1) // can't map the memory? + { + mSegment = NULL; + unlink (mFileName.c_str()); + } + + mDataPtr = mDataArea = mSegment + sizeof(SegmentOffsetType); + mDataMax = mSegment + segmentSize;; + + SetProducerOffset (0); +} + + + +SharedMemoryServer::~SharedMemoryServer () +{ + // go away + if (mSegment == NULL) + { + return; + } + + // get out of memory + munmap (mSegment, mSegmentSize); + + // mark the segment for deletion + unlink (mFileName.c_str ()); +} + + + +const SegmentOffsetType + kSegmentLength = 0, + kCRCOffset = kSegmentLength + sizeof(SegmentOffsetType), + kDomainOffset = kCRCOffset + sizeof(SegmentOffsetType), + kEventTypeOffset = kDomainOffset + sizeof(SegmentOffsetType), + kHeaderLength = kEventTypeOffset + sizeof(SegmentOffsetType) - kCRCOffset; + +void SharedMemoryServer::WriteMessage (SegmentOffsetType domain, SegmentOffsetType event, const void *message, SegmentOffsetType messageLength) +{ + // assemble the final message + ssize_t messageSize = kHeaderLength + messageLength; + u_int8_t finalMessage[messageSize]; + SegmentOffsetType *fm = (SegmentOffsetType*) finalMessage; + fm[0] = OSSwapHostToBigInt32(domain); + fm[1] = OSSwapHostToBigInt32(event); + memcpy(&fm[2], message, messageLength); + + SegmentOffsetType crc = CalculateCRC(finalMessage, messageSize); + + // write the length + WriteOffset(messageSize); + + // write the crc + WriteOffset(crc); + + // write the data + WriteData (finalMessage, messageSize); + + // write the data count + SetProducerOffset(mDataPtr - mDataArea); +} + + + +const char* SharedMemoryServer::GetSegmentName () +{ + return mSegmentName.c_str (); +} + + + +size_t SharedMemoryServer::GetSegmentSize () +{ + return mSegmentSize; +} + + + +SegmentOffsetType SharedMemoryServer::GetProducerOffset () +{ + // the data is stored in the buffer in network byte order + u_int32_t pCount = OSSwapBigToHostInt32 (*(u_int32_t*) mSegment); + return OSSwapHostToBigInt32 (pCount); +} + + + +void SharedMemoryServer::SetProducerOffset (SegmentOffsetType producerCount) +{ + *((SegmentOffsetType*) mSegment) = OSSwapHostToBigInt32 (producerCount); +} + + + +void SharedMemoryServer::WriteOffset(SegmentOffsetType offset) +{ + u_int8_t buffer[4]; + *((u_int32_t*) buffer) = OSSwapHostToBigInt32(offset); + WriteData(buffer, 4); +} + + + +void SharedMemoryServer::WriteData(const void* data, SegmentOffsetType length) +{ + // figure out where in the buffer we actually need to write the data + // figure out how many bytes we can write without overflowing the buffer + const u_int8_t* dp = (const u_int8_t*) data; + SegmentOffsetType bytesToEnd = mDataMax - mDataPtr; + + // figure out how many bytes we can write + SegmentOffsetType bytesToWrite = (length <= bytesToEnd) ? length : bytesToEnd; + + // move the first part of the data, making sure to skip the producer pointer + memcpy (mDataPtr, dp, bytesToWrite); + mDataPtr += bytesToWrite; + dp += bytesToWrite; + + // deduct the bytes just written + length -= bytesToWrite; + + if (length != 0) // did we wrap around? + { + mDataPtr = mDataArea; + memcpy (mDataPtr, dp, length); + mDataPtr += length; + } +}