]> git.saurik.com Git - apple/securityd.git/blob - src/SharedMemoryServer.cpp
securityd-32661.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
7
8 SharedMemoryServer::SharedMemoryServer (const char* segmentName, SegmentOffsetType segmentSize) :
9 mSegmentName (segmentName), mSegmentSize (segmentSize)
10 {
11 // open the file
12 int segmentDescriptor = shm_open (segmentName, O_RDWR | O_CREAT, S_IRWXU | S_IRGRP | S_IROTH);
13 if (segmentDescriptor < 0)
14 {
15 return;
16 }
17
18 // set the segment size
19 ftruncate (segmentDescriptor, segmentSize);
20
21 // map it into memory
22 mSegment = (u_int8_t*) mmap (NULL, mSegmentSize, PROT_READ | PROT_WRITE, MAP_SHARED, segmentDescriptor, 0);
23 close (segmentDescriptor);
24
25 if (mSegment == (u_int8_t*) -1) // can't map the memory?
26 {
27 mSegment = NULL;
28 shm_unlink (segmentName);
29 }
30
31 SetProducerCount (0);
32 }
33
34
35
36 SharedMemoryServer::~SharedMemoryServer ()
37 {
38 // go away
39 if (mSegment == NULL)
40 {
41 return;
42 }
43
44 // get out of memory
45 munmap (mSegment, mSegmentSize);
46
47 // mark the segment for deletion
48 shm_unlink (mSegmentName.c_str ());
49 }
50
51
52
53 const SegmentOffsetType
54 kSegmentLength = 0,
55 kDomainOffset = kSegmentLength + sizeof (SegmentOffsetType),
56 kEventTypeOffset = kDomainOffset + sizeof (SegmentOffsetType),
57 kHeaderLength = kEventTypeOffset + sizeof (SegmentOffsetType);
58
59 void SharedMemoryServer::WriteMessage (SegmentOffsetType domain, SegmentOffsetType event, const void *message, SegmentOffsetType messageLength)
60 {
61 // get the current producer count
62 SegmentOffsetType pCount = GetProducerCount ();
63
64 SegmentOffsetType actualLength = messageLength + kHeaderLength;
65
66 // for now, write a 0 for the length -- this will give clients the opportunity to not process an
67 // incomplete message
68 WriteOffsetAtOffset (pCount, 0);
69
70 // extend the overall write count by enough data to hold the message length and message
71 SetProducerCount (pCount + actualLength);
72
73 // write the data
74 WriteDataAtOffset (pCount + kHeaderLength, message, messageLength);
75
76 // write the domain
77 WriteOffsetAtOffset (pCount + kDomainOffset, domain);
78
79 // write the event type
80 WriteOffsetAtOffset (pCount + kEventTypeOffset, event);
81
82 // write the data count
83 WriteOffsetAtOffset (pCount, actualLength);
84 }
85
86
87
88 const char* SharedMemoryServer::GetSegmentName ()
89 {
90 return mSegmentName.c_str ();
91 }
92
93
94
95 size_t SharedMemoryServer::GetSegmentSize ()
96 {
97 return mSegmentSize;
98 }
99
100
101
102 SegmentOffsetType SharedMemoryServer::GetProducerCount ()
103 {
104 // the data is stored in the buffer in network byte order
105 u_int32_t pCount = *(u_int32_t*) mSegment;
106 return OSSwapHostToBigInt32 (pCount);
107 }
108
109
110
111 void SharedMemoryServer::SetProducerCount (SegmentOffsetType producerCount)
112 {
113 *((u_int32_t*) mSegment) = OSSwapHostToBigInt32 (producerCount);
114 }
115
116
117
118 void SharedMemoryServer::WriteOffsetAtOffset (SegmentOffsetType offset, SegmentOffsetType data)
119 {
120 // convert data to network byte order
121 u_int8_t buffer[4];
122 *((u_int32_t*) buffer) = OSSwapHostToBigInt32 (data);
123
124 WriteDataAtOffset (offset, buffer, sizeof (buffer));
125 }
126
127
128
129 void SharedMemoryServer::WriteDataAtOffset (SegmentOffsetType offset, const void* data, SegmentOffsetType length)
130 {
131 // figure out where in the buffer we actually need to write the data
132 SegmentOffsetType realOffset = offset % kPoolAvailableForData;
133
134 // figure out how many bytes we can write without overflowing the buffer
135 SegmentOffsetType bytesToEnd = kPoolAvailableForData - realOffset;
136
137 // figure out how many bytes we can write
138 SegmentOffsetType bytesToWrite = bytesToEnd < length ? bytesToEnd : length;
139
140 // move the first part of the data, making sure to skip the producer pointer
141 memmove (mSegment + sizeof (SegmentOffsetType) + realOffset, data, bytesToWrite);
142
143 // deduct the bytes just written
144 length -= bytesToWrite;
145
146 if (length != 0) // did we wrap around?
147 {
148 memmove (mSegment + sizeof (SegmentOffsetType), ((u_int8_t*) data) + bytesToWrite, length);
149 }
150 }