]> git.saurik.com Git - apple/securityd.git/blob - src/SharedMemoryServer.cpp
securityd-55199.2.tar.gz
[apple/securityd.git] / src / SharedMemoryServer.cpp
1 #include "SharedMemoryServer.h"
2 #include <stdlib.h>
3 #include <sys/mman.h>
4 #include <fcntl.h>
5 #include <machine/byte_order.h>
6 #include <string>
7 #include <sys/stat.h>
8 #include <security_utilities/crc.h>
9 #include <unistd.h>
10
11 static const char* kPrefix = "/private/var/db/mds/messages/se_";
12
13 SharedMemoryServer::SharedMemoryServer (const char* segmentName, SegmentOffsetType segmentSize) :
14 mSegmentName (segmentName), mSegmentSize (segmentSize)
15 {
16 mFileName = kPrefix;
17 mFileName += segmentName;
18
19 // make the mds directory, just in case it doesn't exist
20 mkdir("/var/db/mds", 1777);
21 mkdir("/var/db/mds/messages", 0755);
22
23 // make the file name
24 // clean any old file away
25 unlink (mFileName.c_str ());
26
27 // open the file
28 int segmentDescriptor = open (mFileName.c_str (), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
29 if (segmentDescriptor < 0)
30 {
31 return;
32 }
33
34 // set the segment size
35 ftruncate (segmentDescriptor, segmentSize);
36
37 // map it into memory
38 mSegment = (u_int8_t*) mmap (NULL, mSegmentSize, PROT_READ | PROT_WRITE, MAP_SHARED, segmentDescriptor, 0);
39 close (segmentDescriptor);
40
41 if (mSegment == (u_int8_t*) -1) // can't map the memory?
42 {
43 mSegment = NULL;
44 unlink (mFileName.c_str());
45 }
46
47 mDataPtr = mDataArea = mSegment + sizeof(SegmentOffsetType);
48 mDataMax = mSegment + segmentSize;;
49
50 SetProducerOffset (0);
51 }
52
53
54
55 SharedMemoryServer::~SharedMemoryServer ()
56 {
57 // go away
58 if (mSegment == NULL)
59 {
60 return;
61 }
62
63 // get out of memory
64 munmap (mSegment, mSegmentSize);
65
66 // mark the segment for deletion
67 unlink (mFileName.c_str ());
68 }
69
70
71
72 const SegmentOffsetType
73 kSegmentLength = 0,
74 kCRCOffset = kSegmentLength + sizeof(SegmentOffsetType),
75 kDomainOffset = kCRCOffset + sizeof(SegmentOffsetType),
76 kEventTypeOffset = kDomainOffset + sizeof(SegmentOffsetType),
77 kHeaderLength = kEventTypeOffset + sizeof(SegmentOffsetType) - kCRCOffset;
78
79 void SharedMemoryServer::WriteMessage (SegmentOffsetType domain, SegmentOffsetType event, const void *message, SegmentOffsetType messageLength)
80 {
81 // assemble the final message
82 ssize_t messageSize = kHeaderLength + messageLength;
83 u_int8_t finalMessage[messageSize];
84 SegmentOffsetType *fm = (SegmentOffsetType*) finalMessage;
85 fm[0] = OSSwapHostToBigInt32(domain);
86 fm[1] = OSSwapHostToBigInt32(event);
87 memcpy(&fm[2], message, messageLength);
88
89 SegmentOffsetType crc = CalculateCRC(finalMessage, messageSize);
90
91 // write the length
92 WriteOffset(messageSize);
93
94 // write the crc
95 WriteOffset(crc);
96
97 // write the data
98 WriteData (finalMessage, messageSize);
99
100 // write the data count
101 SetProducerOffset(mDataPtr - mDataArea);
102 }
103
104
105
106 const char* SharedMemoryServer::GetSegmentName ()
107 {
108 return mSegmentName.c_str ();
109 }
110
111
112
113 size_t SharedMemoryServer::GetSegmentSize ()
114 {
115 return mSegmentSize;
116 }
117
118
119
120 SegmentOffsetType SharedMemoryServer::GetProducerOffset ()
121 {
122 // the data is stored in the buffer in network byte order
123 u_int32_t pCount = OSSwapBigToHostInt32 (*(u_int32_t*) mSegment);
124 return OSSwapHostToBigInt32 (pCount);
125 }
126
127
128
129 void SharedMemoryServer::SetProducerOffset (SegmentOffsetType producerCount)
130 {
131 *((SegmentOffsetType*) mSegment) = OSSwapHostToBigInt32 (producerCount);
132 }
133
134
135
136 void SharedMemoryServer::WriteOffset(SegmentOffsetType offset)
137 {
138 u_int8_t buffer[4];
139 *((u_int32_t*) buffer) = OSSwapHostToBigInt32(offset);
140 WriteData(buffer, 4);
141 }
142
143
144
145 void SharedMemoryServer::WriteData(const void* data, SegmentOffsetType length)
146 {
147 // figure out where in the buffer we actually need to write the data
148 // figure out how many bytes we can write without overflowing the buffer
149 const u_int8_t* dp = (const u_int8_t*) data;
150 SegmentOffsetType bytesToEnd = mDataMax - mDataPtr;
151
152 // figure out how many bytes we can write
153 SegmentOffsetType bytesToWrite = (length <= bytesToEnd) ? length : bytesToEnd;
154
155 // move the first part of the data, making sure to skip the producer pointer
156 memcpy (mDataPtr, dp, bytesToWrite);
157 mDataPtr += bytesToWrite;
158 dp += bytesToWrite;
159
160 // deduct the bytes just written
161 length -= bytesToWrite;
162
163 if (length != 0) // did we wrap around?
164 {
165 mDataPtr = mDataArea;
166 memcpy (mDataPtr, dp, length);
167 mDataPtr += length;
168 }
169 }