]> git.saurik.com Git - apple/security.git/blobdiff - Security/libsecurityd/lib/SharedMemoryClient.cpp
Security-57031.1.35.tar.gz
[apple/security.git] / Security / libsecurityd / lib / SharedMemoryClient.cpp
diff --git a/Security/libsecurityd/lib/SharedMemoryClient.cpp b/Security/libsecurityd/lib/SharedMemoryClient.cpp
new file mode 100644 (file)
index 0000000..923767d
--- /dev/null
@@ -0,0 +1,189 @@
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <architecture/byte_order.h>
+#include <security_cdsa_utilities/cssmdb.h>
+#include "SharedMemoryClient.h"
+#include <string>
+#include <security_utilities/crc.h>
+
+static const char* kPrefix = "/var/db/mds/messages/se_";
+
+using namespace Security;
+
+SharedMemoryClient::SharedMemoryClient (const char* segmentName, SegmentOffsetType segmentSize)
+{
+       StLock<Mutex> _(mMutex);
+       
+       mSegmentName = segmentName;
+       mSegmentSize = segmentSize;
+       mSegment = mDataArea = mDataPtr = 0;
+       
+       // make the name
+       int segmentDescriptor;
+       {
+               std::string name (kPrefix);
+               name += segmentName;
+               
+               // make a connection to the shared memory block
+               segmentDescriptor = open (name.c_str (), O_RDONLY, S_IROTH);
+               if (segmentDescriptor < 0) // error on opening the shared memory segment?
+               {
+                       // CssmError::throwMe (CSSM_ERRCODE_INTERNAL_ERROR);
+                       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)
+       {
+               return;
+       }
+       
+       mDataArea = mSegment + sizeof (SegmentOffsetType);
+       mDataMax = mSegment + segmentSize;
+       mDataPtr = mDataArea + GetProducerCount ();
+}
+
+
+
+SharedMemoryClient::~SharedMemoryClient ()
+{
+       StLock<Mutex> _(mMutex);
+       if (mSegment == NULL || mSegment == MAP_FAILED) // error on opening the shared memory segment?
+       {
+               CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR);
+       }
+       munmap (mSegment, mSegmentSize);
+}
+
+
+
+SegmentOffsetType SharedMemoryClient::GetProducerCount ()
+{
+       if (mSegment == NULL || mSegment == MAP_FAILED) // error on opening the shared memory segment?
+       {
+               CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR);
+       }
+       return OSSwapBigToHostInt32 (*(u_int32_t*) mSegment);
+}
+
+
+
+const char* SharedMemoryClient::GetSegmentName ()
+{
+       return mSegmentName.c_str ();
+}
+
+
+
+size_t SharedMemoryClient::GetSegmentSize ()
+{
+       return mSegmentSize;
+}
+
+
+
+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);
+       }
+
+       u_int8_t* bptr = (u_int8_t*) buffer;
+
+       SegmentOffsetType bytesToEnd = (SegmentOffsetType)(mDataMax - mDataPtr);
+       
+       // figure out how many bytes we can read
+       SegmentOffsetType bytesToRead = (length <= bytesToEnd) ? length : bytesToEnd;
+
+       // move the first part of the data
+       memcpy (bptr, mDataPtr, bytesToRead);
+       bptr += bytesToRead;
+       
+       // see if we have anything else to read
+       mDataPtr += bytesToRead;
+       
+       length -= bytesToRead;
+       if (length != 0)
+       {
+               mDataPtr = mDataArea;
+               memcpy(bptr, mDataPtr, length);
+               mDataPtr += length;
+       }
+}
+
+
+
+SegmentOffsetType SharedMemoryClient::ReadOffset()
+{
+       SegmentOffsetType offset;
+       ReadData(&offset, sizeof(SegmentOffsetType));
+       offset = OSSwapBigToHostInt32 (offset);
+       return offset;
+}
+
+
+
+bool SharedMemoryClient::ReadMessage (void* message, SegmentOffsetType &length, UnavailableReason &ur)
+{
+       StLock<Mutex> _(mMutex);
+
+       if (mSegment == NULL || mSegment == MAP_FAILED) // error on opening the shared memory segment?
+       {
+               CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR);
+       }
+
+       ur = kURNone;
+       
+       size_t offset = mDataPtr - mDataArea;
+       if (offset == GetProducerCount())
+       {
+               ur = kURNoMessage;
+               return false;
+       }
+       
+       // get the length of the message in the buffer
+       length = ReadOffset();
+       
+       // we have the possibility that data is correct, figure out where the data is actually located
+       // get the length of the message stored there
+       if (length == 0 || length >= kPoolAvailableForData)
+       {
+               if (length == 0)
+               {
+                       ur = kURNoMessage;
+               }
+               else
+               {
+                       ur = kURBufferCorrupt;
+               }
+
+               // something's gone wrong, reset.
+               mDataPtr = mDataArea + GetProducerCount ();
+               return false;
+       }
+       
+       // read the crc
+       SegmentOffsetType crc = ReadOffset();
+
+       // read the data into the buffer
+       ReadData (message, length);
+       
+       // calculate the CRC
+       SegmentOffsetType crc2 = CalculateCRC((u_int8_t*) message, length);
+       if (crc != crc2)
+       {
+               ur = kURBufferCorrupt;
+               mDataPtr = mDataArea + GetProducerCount ();
+               return false;
+       }
+
+       return true;
+}