1 //
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 // https://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13
14 // Unittest for the sandbox2::Comms class.
15
16 #include "sandboxed_api/sandbox2/comms.h"
17
18 #include <fcntl.h>
19 #include <sys/socket.h>
20 #include <sys/types.h>
21 #include <unistd.h>
22
23 #include <cstdint>
24 #include <cstring>
25 #include <functional>
26 #include <memory>
27 #include <string>
28 #include <thread> // NOLINT(build/c++11)
29 #include <vector>
30
31 #include "gmock/gmock.h"
32 #include "gtest/gtest.h"
33 #include "absl/container/fixed_array.h"
34 #include "absl/log/check.h"
35 #include "absl/log/log.h"
36 #include "absl/status/status.h"
37 #include "absl/strings/string_view.h"
38 #include "sandboxed_api/sandbox2/comms_test.pb.h"
39 #include "sandboxed_api/util/status_matchers.h"
40
41 using ::sapi::IsOk;
42 using ::sapi::StatusIs;
43 using ::testing::Eq;
44 using ::testing::IsFalse;
45 using ::testing::IsTrue;
46
47 namespace sandbox2 {
48
49 using CommunicationHandler = std::function<void(Comms* comms)>;
50
51 constexpr char kProtoStr[] = "ABCD";
NullTestString()52 static absl::string_view NullTestString() {
53 static constexpr char kHelperStr[] = "test\0\n\r\t\x01\x02";
54 return absl::string_view(kHelperStr, sizeof(kHelperStr) - 1);
55 }
56
57 // Helper function that handles the communication between the two handler
58 // functions.
HandleCommunication(const CommunicationHandler & a,const CommunicationHandler & b)59 void HandleCommunication(const CommunicationHandler& a,
60 const CommunicationHandler& b) {
61 int sv[2];
62 CHECK_NE(socketpair(AF_UNIX, SOCK_STREAM, 0, sv), -1);
63 Comms comms(sv[0]);
64
65 // Start handler a.
66 std::thread remote([sv, &a]() {
67 Comms my_comms(sv[1]);
68 a(&my_comms);
69 });
70
71 // Accept connection and run handler b.
72 b(&comms);
73 remote.join();
74 }
75
TEST(CommsTest,TestSendRecv8)76 TEST(CommsTest, TestSendRecv8) {
77 auto a = [](Comms* comms) {
78 // Send Uint8.
79 ASSERT_THAT(comms->SendUint8(192), IsTrue());
80
81 // Recv Int8.
82 int8_t tmp8;
83 ASSERT_THAT(comms->RecvInt8(&tmp8), IsTrue());
84 EXPECT_THAT(tmp8, Eq(-7));
85 };
86 auto b = [](Comms* comms) {
87 // Recv Uint8.
88 uint8_t tmpu8;
89 ASSERT_THAT(comms->RecvUint8(&tmpu8), IsTrue());
90 EXPECT_THAT(tmpu8, Eq(192));
91
92 // Send Int8.
93 ASSERT_THAT(comms->SendInt8(-7), IsTrue());
94 };
95 HandleCommunication(a, b);
96 }
97
TEST(CommsTest,TestSendRecv16)98 TEST(CommsTest, TestSendRecv16) {
99 auto a = [](Comms* comms) {
100 // Send Uint16.
101 ASSERT_THAT(comms->SendUint16(40001), IsTrue());
102
103 // Recv Int16.
104 int16_t tmp16;
105 ASSERT_THAT(comms->RecvInt16(&tmp16), IsTrue());
106 EXPECT_THAT(tmp16, Eq(-22050));
107 };
108 auto b = [](Comms* comms) {
109 // Recv Uint16.
110 uint16_t tmpu16;
111 ASSERT_THAT(comms->RecvUint16(&tmpu16), IsTrue());
112 EXPECT_THAT(tmpu16, Eq(40001));
113
114 // Send Int16.
115 ASSERT_THAT(comms->SendInt16(-22050), IsTrue());
116 };
117 HandleCommunication(a, b);
118 }
119
TEST(CommsTest,TestSendRecv32)120 TEST(CommsTest, TestSendRecv32) {
121 auto a = [](Comms* comms) {
122 // SendUint32.
123 ASSERT_THAT(comms->SendUint32(3221225472UL), IsTrue());
124
125 // Recv Int32.
126 int32_t tmp32;
127 ASSERT_THAT(comms->RecvInt32(&tmp32), IsTrue());
128 EXPECT_THAT(tmp32, Eq(-1073741824));
129 };
130 auto b = [](Comms* comms) {
131 // Recv Uint32.
132 uint32_t tmpu32;
133 ASSERT_THAT(comms->RecvUint32(&tmpu32), IsTrue());
134 EXPECT_THAT(tmpu32, Eq(3221225472UL));
135
136 // Send Int32.
137 ASSERT_THAT(comms->SendInt32(-1073741824), IsTrue());
138 };
139 HandleCommunication(a, b);
140 }
141
TEST(CommsTest,TestSendRecv64)142 TEST(CommsTest, TestSendRecv64) {
143 auto a = [](Comms* comms) {
144 // SendUint64.
145 ASSERT_THAT(comms->SendUint64(1099511627776ULL), IsTrue());
146
147 // Recv Int64.
148 int64_t tmp64;
149 ASSERT_THAT(comms->RecvInt64(&tmp64), IsTrue());
150 EXPECT_THAT(tmp64, Eq(-1099511627776LL));
151 };
152 auto b = [](Comms* comms) {
153 // Recv Uint64.
154 uint64_t tmpu64;
155 ASSERT_THAT(comms->RecvUint64(&tmpu64), IsTrue());
156 EXPECT_THAT(tmpu64, Eq(1099511627776ULL));
157
158 // Send Int64.
159 ASSERT_THAT(comms->SendInt64(-1099511627776LL), IsTrue());
160 };
161 HandleCommunication(a, b);
162 }
163
TEST(CommsTest,TestTypeMismatch)164 TEST(CommsTest, TestTypeMismatch) {
165 auto a = [](Comms* comms) {
166 uint8_t tmpu8;
167 // Receive Int8 (but Uint8 expected).
168 EXPECT_THAT(comms->RecvUint8(&tmpu8), IsFalse());
169 };
170 auto b = [](Comms* comms) {
171 // Send Int8 (but Uint8 expected).
172 ASSERT_THAT(comms->SendInt8(-93), IsTrue());
173 };
174 HandleCommunication(a, b);
175 }
176
TEST(CommsTest,TestSendRecvString)177 TEST(CommsTest, TestSendRecvString) {
178 auto a = [](Comms* comms) {
179 std::string tmps;
180 ASSERT_THAT(comms->RecvString(&tmps), IsTrue());
181 EXPECT_TRUE(tmps == NullTestString());
182 EXPECT_THAT(tmps.size(), Eq(NullTestString().size()));
183 };
184 auto b = [](Comms* comms) {
185 ASSERT_THAT(comms->SendString(std::string(NullTestString())), IsTrue());
186 };
187 HandleCommunication(a, b);
188 }
189
TEST(CommsTest,TestSendRecvArray)190 TEST(CommsTest, TestSendRecvArray) {
191 auto a = [](Comms* comms) {
192 // Receive 1M bytes.
193 std::vector<uint8_t> buffer;
194 ASSERT_THAT(comms->RecvBytes(&buffer), IsTrue());
195 EXPECT_THAT(buffer.size(), Eq(1024 * 1024));
196 };
197 auto b = [](Comms* comms) {
198 // Send 1M bytes.
199 std::vector<uint8_t> buffer(1024 * 1024);
200 memset(buffer.data(), 0, buffer.size());
201 ASSERT_THAT(comms->SendBytes(buffer), IsTrue());
202 };
203 HandleCommunication(a, b);
204 }
205
TEST(CommsTest,TestSendRecvFD)206 TEST(CommsTest, TestSendRecvFD) {
207 auto a = [](Comms* comms) {
208 // Receive FD and test it.
209 int fd = -1;
210 ASSERT_THAT(comms->RecvFD(&fd), IsTrue());
211 EXPECT_GE(fd, 0);
212 EXPECT_NE(fcntl(fd, F_GETFD), -1);
213 };
214 auto b = [](Comms* comms) {
215 // Send our STDERR to the thread.
216 ASSERT_THAT(comms->SendFD(STDERR_FILENO), IsTrue());
217 };
218 HandleCommunication(a, b);
219 }
220
TEST(CommsTest,TestSendRecvEmptyTLV)221 TEST(CommsTest, TestSendRecvEmptyTLV) {
222 auto a = [](Comms* comms) {
223 // Receive TLV without a value.
224 uint32_t tag;
225 std::vector<uint8_t> value;
226 ASSERT_THAT(comms->RecvTLV(&tag, &value), IsTrue()); // NOLINT
227 EXPECT_THAT(tag, Eq(0x00DEADBE));
228 EXPECT_THAT(value.size(), Eq(0));
229 };
230 auto b = [](Comms* comms) {
231 // Send TLV without a value.
232 ASSERT_THAT(comms->SendTLV(0x00DEADBE, 0, nullptr), IsTrue());
233 };
234 HandleCommunication(a, b);
235 }
236
TEST(CommsTest,TestSendRecvEmptyTLV2)237 TEST(CommsTest, TestSendRecvEmptyTLV2) {
238 auto a = [](Comms* comms) {
239 // Receive TLV without a value.
240 uint32_t tag;
241 std::vector<uint8_t> data;
242 ASSERT_THAT(comms->RecvTLV(&tag, &data), IsTrue());
243 EXPECT_THAT(tag, Eq(0x00DEADBE));
244 EXPECT_THAT(data.size(), Eq(0));
245 };
246 auto b = [](Comms* comms) {
247 // Send TLV without a value.
248 ASSERT_THAT(comms->SendTLV(0x00DEADBE, 0, nullptr), IsTrue());
249 };
250 HandleCommunication(a, b);
251 }
252
TEST(CommsTest,TestSendRecvProto)253 TEST(CommsTest, TestSendRecvProto) {
254 auto a = [](Comms* comms) {
255 // Receive a ProtoBuf.
256 std::unique_ptr<CommsTestMsg> comms_msg(new CommsTestMsg());
257 ASSERT_THAT(comms->RecvProtoBuf(comms_msg.get()), IsTrue());
258 ASSERT_THAT(comms_msg->value_size(), Eq(1));
259 EXPECT_THAT(comms_msg->value(0), Eq(kProtoStr));
260 };
261 auto b = [](Comms* comms) {
262 // Send a ProtoBuf.
263 std::unique_ptr<CommsTestMsg> comms_msg(new CommsTestMsg());
264 comms_msg->add_value(kProtoStr);
265 ASSERT_THAT(comms_msg->value_size(), Eq(1));
266 ASSERT_THAT(comms->SendProtoBuf(*comms_msg), IsTrue());
267 };
268 HandleCommunication(a, b);
269 }
270
TEST(CommsTest,TestSendRecvStatusOK)271 TEST(CommsTest, TestSendRecvStatusOK) {
272 auto a = [](Comms* comms) {
273 // Receive a good status.
274 absl::Status status;
275 ASSERT_THAT(comms->RecvStatus(&status), IsTrue());
276 EXPECT_THAT(status, IsOk());
277 };
278 auto b = [](Comms* comms) {
279 // Send a good status.
280 ASSERT_THAT(comms->SendStatus(absl::OkStatus()), IsTrue());
281 };
282 HandleCommunication(a, b);
283 }
284
TEST(CommsTest,TestSendRecvStatusFailing)285 TEST(CommsTest, TestSendRecvStatusFailing) {
286 auto a = [](Comms* comms) {
287 // Receive a failing status.
288 absl::Status status;
289 ASSERT_THAT(comms->RecvStatus(&status), IsTrue());
290 EXPECT_THAT(status, Not(IsOk()));
291 EXPECT_THAT(status, StatusIs(absl::StatusCode::kInternal, "something odd"));
292 };
293 auto b = [](Comms* comms) {
294 // Send a failing status.
295 ASSERT_THAT(comms->SendStatus(
296 absl::Status{absl::StatusCode::kInternal, "something odd"}),
297 IsTrue());
298 };
299 HandleCommunication(a, b);
300 }
301
TEST(CommsTest,TestUsesDistinctBuffers)302 TEST(CommsTest, TestUsesDistinctBuffers) {
303 auto a = [](Comms* comms) {
304 // Receive 1M bytes.
305 std::vector<uint8_t> buffer1, buffer2;
306 ASSERT_THAT(comms->RecvBytes(&buffer1), IsTrue()); // NOLINT
307 EXPECT_THAT(buffer1.size(), Eq(1024 * 1024));
308
309 ASSERT_THAT(comms->RecvBytes(&buffer2), IsTrue()); // NOLINT
310 EXPECT_THAT(buffer2.size(), Eq(1024 * 1024));
311
312 // Make sure we can access the buffer (memory was not free'd).
313 // Probably only useful when running with ASAN/MSAN.
314 EXPECT_THAT(buffer1[1024 * 1024 - 1], Eq(buffer1[1024 * 1024 - 1]));
315 EXPECT_THAT(buffer2[1024 * 1024 - 1], Eq(buffer2[1024 * 1024 - 1]));
316 EXPECT_NE(buffer1.data(), buffer2.data());
317 };
318 auto b = [](Comms* comms) {
319 // Send 1M bytes.
320 absl::FixedArray<uint8_t> buf(1024 * 1024);
321 memset(buf.data(), 0, buf.size());
322 ASSERT_THAT(comms->SendBytes(buf.data(), buf.size()), IsTrue());
323 ASSERT_THAT(comms->SendBytes(buf.data(), buf.size()), IsTrue());
324 };
325 HandleCommunication(a, b);
326 }
327
TEST(CommsTest,TestSendRecvCredentials)328 TEST(CommsTest, TestSendRecvCredentials) {
329 auto a = [](Comms* comms) {
330 // Check credentials.
331 pid_t pid;
332 uid_t uid;
333 gid_t gid;
334 ASSERT_THAT(comms->RecvCreds(&pid, &uid, &gid), IsTrue());
335 EXPECT_THAT(pid, Eq(getpid()));
336 EXPECT_THAT(uid, Eq(getuid()));
337 EXPECT_THAT(gid, Eq(getgid()));
338 };
339 auto b = [](Comms* comms) {
340 // Nothing to do here.
341 };
342 HandleCommunication(a, b);
343 }
344
TEST(CommsTest,TestSendTooMuchData)345 TEST(CommsTest, TestSendTooMuchData) {
346 auto a = [](Comms* comms) {
347 // Nothing to do here.
348 };
349 auto b = [](Comms* comms) {
350 // Send too much data.
351 ASSERT_THAT(comms->SendBytes(nullptr, comms->GetMaxMsgSize() + 1),
352 IsFalse());
353 };
354 HandleCommunication(a, b);
355 }
356
TEST(CommsTest,TestSendRecvBytes)357 TEST(CommsTest, TestSendRecvBytes) {
358 auto a = [](Comms* comms) {
359 std::vector<uint8_t> buffer;
360 ASSERT_THAT(comms->RecvBytes(&buffer), IsTrue());
361 ASSERT_THAT(comms->SendBytes(buffer), IsTrue());
362 };
363 auto b = [](Comms* comms) {
364 const std::vector<uint8_t> request = {0, 1, 2, 3, 7};
365 ASSERT_THAT(comms->SendBytes(request), IsTrue());
366
367 std::vector<uint8_t> response;
368 ASSERT_THAT(comms->RecvBytes(&response), IsTrue());
369 EXPECT_THAT(request, Eq(response));
370 };
371 HandleCommunication(a, b);
372 }
373
374 } // namespace sandbox2
375