]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurityd/lib/SharedMemoryClient.cpp
Security-57740.20.22.tar.gz
[apple/security.git] / OSX / libsecurityd / lib / SharedMemoryClient.cpp
1 #include <sys/mman.h>
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <unistd.h>
5 #include <fcntl.h>
6 #include <architecture/byte_order.h>
7 #include <security_cdsa_utilities/cssmdb.h>
8 #include "SharedMemoryClient.h"
9 #include <string>
10 #include <security_utilities/crc.h>
11
12 static const char* kPrefix = "/var/db/mds/messages/se_";
13
14 using namespace Security;
15
16 SharedMemoryClient::SharedMemoryClient (const char* segmentName, SegmentOffsetType segmentSize)
17 {
18 StLock<Mutex> _(mMutex);
19
20 mSegmentName = segmentName;
21 mSegmentSize = segmentSize;
22 mSegment = (u_int8_t*) MAP_FAILED;
23 mDataArea = mDataPtr = 0;
24
25 if (segmentSize < sizeof(u_int32_t))
26 return;
27
28 // make the name
29 int segmentDescriptor;
30 {
31 std::string name (kPrefix);
32 name += segmentName;
33
34 // make a connection to the shared memory block
35 segmentDescriptor = open (name.c_str (), O_RDONLY, S_IROTH);
36 if (segmentDescriptor < 0) // error on opening the shared memory segment?
37 {
38 // CssmError::throwMe (CSSM_ERRCODE_INTERNAL_ERROR);
39 return;
40 }
41 }
42
43 // check the file size is large enough to support Operations
44 struct stat statResult = {};
45 int result = fstat(segmentDescriptor, &statResult);
46 if(result) {
47 UnixError::throwMe(errno);
48 }
49
50 off_t sz = statResult.st_size;
51 if(sz < sizeof(SegmentOffsetType)) {
52 close(segmentDescriptor);
53 return;
54 }
55
56 if(sz > 4*segmentSize) {
57 // File is too ridiculously large. Quit.
58 close(segmentDescriptor);
59 return;
60 }
61
62 // map the segment into place
63 mSegment = (u_int8_t*) mmap (NULL, segmentSize, PROT_READ, MAP_SHARED, segmentDescriptor, 0);
64 close (segmentDescriptor);
65
66 if (mSegment == MAP_FAILED)
67 {
68 return;
69 }
70
71 mDataArea = mSegment + sizeof (SegmentOffsetType);
72 mDataMax = mSegment + sz;
73 mDataPtr = mDataArea + GetProducerCount ();
74 }
75
76
77
78 SharedMemoryClient::~SharedMemoryClient ()
79 {
80 StLock<Mutex> _(mMutex);
81 if (mSegment == NULL || mSegment == MAP_FAILED) // error on opening the shared memory segment?
82 {
83 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR);
84 }
85 munmap (mSegment, mSegmentSize);
86 }
87
88
89
90 SegmentOffsetType SharedMemoryClient::GetProducerCount ()
91 {
92 if (mSegment == NULL || mSegment == MAP_FAILED) // error on opening the shared memory segment?
93 {
94 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR);
95 }
96 if( ((u_int8_t*) (((u_int32_t*) mSegment) + 1)) > mDataMax) {
97 // Check we can actually read this u_int32_t
98 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR);
99 }
100
101 SegmentOffsetType offset = OSSwapBigToHostInt32 (*(u_int32_t*) mSegment);
102 if (&mSegment[offset] >= mDataMax)
103 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR);
104 else
105 return offset;
106 }
107
108
109
110 const char* SharedMemoryClient::GetSegmentName ()
111 {
112 return mSegmentName.c_str ();
113 }
114
115
116
117 size_t SharedMemoryClient::GetSegmentSize ()
118 {
119 return mSegmentSize;
120 }
121
122
123
124 void SharedMemoryClient::ReadData (void* buffer, SegmentOffsetType length)
125 {
126 if (mSegment == NULL || mSegment == MAP_FAILED) // error on opening the shared memory segment?
127 {
128 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR);
129 }
130
131 u_int8_t* bptr = (u_int8_t*) buffer;
132
133 SegmentOffsetType bytesToEnd = (SegmentOffsetType)(mDataMax - mDataPtr);
134
135 // figure out how many bytes we can read
136 SegmentOffsetType bytesToRead = (length <= bytesToEnd) ? length : bytesToEnd;
137
138 // move the first part of the data
139 memcpy (bptr, mDataPtr, bytesToRead);
140 bptr += bytesToRead;
141
142 // see if we have anything else to read
143 mDataPtr += bytesToRead;
144
145 length -= bytesToRead;
146 if (length != 0)
147 {
148 mDataPtr = mDataArea;
149 memcpy(bptr, mDataPtr, length);
150 mDataPtr += length;
151 }
152 }
153
154
155
156 SegmentOffsetType SharedMemoryClient::ReadOffset()
157 {
158 SegmentOffsetType offset;
159 ReadData(&offset, sizeof(SegmentOffsetType));
160 offset = OSSwapBigToHostInt32 (offset);
161 return offset;
162 }
163
164
165
166 bool SharedMemoryClient::ReadMessage (void* message, SegmentOffsetType &length, UnavailableReason &ur)
167 {
168 StLock<Mutex> _(mMutex);
169
170 if (mSegment == NULL || mSegment == MAP_FAILED) // error on opening the shared memory segment?
171 {
172 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR);
173 }
174
175 ur = kURNone;
176
177 size_t offset = mDataPtr - mDataArea;
178 if (offset == GetProducerCount())
179 {
180 ur = kURNoMessage;
181 return false;
182 }
183
184 // get the length of the message in the buffer
185 length = ReadOffset();
186
187 // we have the possibility that data is correct, figure out where the data is actually located
188 // get the length of the message stored there
189 if (length == 0 || length >= kPoolAvailableForData)
190 {
191 if (length == 0)
192 {
193 ur = kURNoMessage;
194 }
195 else
196 {
197 ur = kURBufferCorrupt;
198 }
199
200 // something's gone wrong, reset.
201 mDataPtr = mDataArea + GetProducerCount ();
202 return false;
203 }
204
205 // read the crc
206 SegmentOffsetType crc = ReadOffset();
207
208 // read the data into the buffer
209 ReadData (message, length);
210
211 // calculate the CRC
212 SegmentOffsetType crc2 = CalculateCRC((u_int8_t*) message, length);
213 if (crc != crc2)
214 {
215 ur = kURBufferCorrupt;
216 mDataPtr = mDataArea + GetProducerCount ();
217 return false;
218 }
219
220 return true;
221 }