]> git.saurik.com Git - apple/security.git/blob - Security/libsecurityd/lib/SharedMemoryClient.cpp
Security-57031.40.6.tar.gz
[apple/security.git] / Security / 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 = mDataArea = mDataPtr = 0;
23
24 // make the name
25 int segmentDescriptor;
26 {
27 std::string name (kPrefix);
28 name += segmentName;
29
30 // make a connection to the shared memory block
31 segmentDescriptor = open (name.c_str (), O_RDONLY, S_IROTH);
32 if (segmentDescriptor < 0) // error on opening the shared memory segment?
33 {
34 // CssmError::throwMe (CSSM_ERRCODE_INTERNAL_ERROR);
35 return;
36 }
37 }
38
39 // map the segment into place
40 mSegment = (u_int8_t*) mmap (NULL, segmentSize, PROT_READ, MAP_SHARED, segmentDescriptor, 0);
41 close (segmentDescriptor);
42
43 if (mSegment == MAP_FAILED)
44 {
45 return;
46 }
47
48 mDataArea = mSegment + sizeof (SegmentOffsetType);
49 mDataMax = mSegment + segmentSize;
50 mDataPtr = mDataArea + GetProducerCount ();
51 }
52
53
54
55 SharedMemoryClient::~SharedMemoryClient ()
56 {
57 StLock<Mutex> _(mMutex);
58 if (mSegment == NULL || mSegment == MAP_FAILED) // error on opening the shared memory segment?
59 {
60 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR);
61 }
62 munmap (mSegment, mSegmentSize);
63 }
64
65
66
67 SegmentOffsetType SharedMemoryClient::GetProducerCount ()
68 {
69 if (mSegment == NULL || mSegment == MAP_FAILED) // error on opening the shared memory segment?
70 {
71 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR);
72 }
73 return OSSwapBigToHostInt32 (*(u_int32_t*) mSegment);
74 }
75
76
77
78 const char* SharedMemoryClient::GetSegmentName ()
79 {
80 return mSegmentName.c_str ();
81 }
82
83
84
85 size_t SharedMemoryClient::GetSegmentSize ()
86 {
87 return mSegmentSize;
88 }
89
90
91
92 void SharedMemoryClient::ReadData (void* buffer, SegmentOffsetType length)
93 {
94 if (mSegment == NULL || mSegment == MAP_FAILED) // error on opening the shared memory segment?
95 {
96 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR);
97 }
98
99 u_int8_t* bptr = (u_int8_t*) buffer;
100
101 SegmentOffsetType bytesToEnd = (SegmentOffsetType)(mDataMax - mDataPtr);
102
103 // figure out how many bytes we can read
104 SegmentOffsetType bytesToRead = (length <= bytesToEnd) ? length : bytesToEnd;
105
106 // move the first part of the data
107 memcpy (bptr, mDataPtr, bytesToRead);
108 bptr += bytesToRead;
109
110 // see if we have anything else to read
111 mDataPtr += bytesToRead;
112
113 length -= bytesToRead;
114 if (length != 0)
115 {
116 mDataPtr = mDataArea;
117 memcpy(bptr, mDataPtr, length);
118 mDataPtr += length;
119 }
120 }
121
122
123
124 SegmentOffsetType SharedMemoryClient::ReadOffset()
125 {
126 SegmentOffsetType offset;
127 ReadData(&offset, sizeof(SegmentOffsetType));
128 offset = OSSwapBigToHostInt32 (offset);
129 return offset;
130 }
131
132
133
134 bool SharedMemoryClient::ReadMessage (void* message, SegmentOffsetType &length, UnavailableReason &ur)
135 {
136 StLock<Mutex> _(mMutex);
137
138 if (mSegment == NULL || mSegment == MAP_FAILED) // error on opening the shared memory segment?
139 {
140 CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR);
141 }
142
143 ur = kURNone;
144
145 size_t offset = mDataPtr - mDataArea;
146 if (offset == GetProducerCount())
147 {
148 ur = kURNoMessage;
149 return false;
150 }
151
152 // get the length of the message in the buffer
153 length = ReadOffset();
154
155 // we have the possibility that data is correct, figure out where the data is actually located
156 // get the length of the message stored there
157 if (length == 0 || length >= kPoolAvailableForData)
158 {
159 if (length == 0)
160 {
161 ur = kURNoMessage;
162 }
163 else
164 {
165 ur = kURBufferCorrupt;
166 }
167
168 // something's gone wrong, reset.
169 mDataPtr = mDataArea + GetProducerCount ();
170 return false;
171 }
172
173 // read the crc
174 SegmentOffsetType crc = ReadOffset();
175
176 // read the data into the buffer
177 ReadData (message, length);
178
179 // calculate the CRC
180 SegmentOffsetType crc2 = CalculateCRC((u_int8_t*) message, length);
181 if (crc != crc2)
182 {
183 ur = kURBufferCorrupt;
184 mDataPtr = mDataArea + GetProducerCount ();
185 return false;
186 }
187
188 return true;
189 }