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