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