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