1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "perfetto/ext/base/unix_socket.h"
18
19 #include <signal.h>
20 #include <sys/types.h>
21 #include <list>
22 #include <thread>
23
24 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
25 #include <sys/mman.h>
26 #include <sys/socket.h>
27 #include <sys/un.h>
28 #endif
29
30 #include "perfetto/base/build_config.h"
31 #include "perfetto/base/logging.h"
32 #include "perfetto/ext/base/file_utils.h"
33 #include "perfetto/ext/base/periodic_task.h"
34 #include "perfetto/ext/base/pipe.h"
35 #include "perfetto/ext/base/string_utils.h"
36 #include "perfetto/ext/base/temp_file.h"
37 #include "perfetto/ext/base/utils.h"
38 #include "src/base/test/test_task_runner.h"
39 #include "src/ipc/test/test_socket.h"
40 #include "test/gtest_and_gmock.h"
41
42 #if (PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
43 PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID))
44 #define SKIP_IF_VSOCK_LOOPBACK_NOT_SUPPORTED() \
45 do { \
46 if (!UnixSocketRaw::CreateMayFail(SockFamily::kVsock, SockType::kStream) \
47 .Bind("vsock://1:10000")) { \
48 GTEST_SKIP() << "vsock testing skipped: loopback address unsupported.\n" \
49 << "Please run sudo modprobe vsock-loopback"; \
50 } \
51 } while (0)
52 #endif
53
54 namespace perfetto {
55 namespace base {
56 namespace {
57
58 using ::testing::_;
59 using ::testing::AtLeast;
60 using ::testing::Invoke;
61 using ::testing::InvokeWithoutArgs;
62 using ::testing::Mock;
63
64 ipc::TestSocket kTestSocket{"unix_socket_unittest"};
65
66 class MockEventListener : public UnixSocket::EventListener {
67 public:
68 MOCK_METHOD(void, OnNewIncomingConnection, (UnixSocket*, UnixSocket*));
69 MOCK_METHOD(void, OnConnect, (UnixSocket*, bool), (override));
70 MOCK_METHOD(void, OnDisconnect, (UnixSocket*), (override));
71 MOCK_METHOD(void, OnDataAvailable, (UnixSocket*), (override));
72
73 // GMock doesn't support mocking methods with non-copiable args.
OnNewIncomingConnection(UnixSocket * self,std::unique_ptr<UnixSocket> new_connection)74 void OnNewIncomingConnection(
75 UnixSocket* self,
76 std::unique_ptr<UnixSocket> new_connection) override {
77 incoming_connections_.emplace_back(std::move(new_connection));
78 OnNewIncomingConnection(self, incoming_connections_.back().get());
79 }
80
GetIncomingConnection()81 std::unique_ptr<UnixSocket> GetIncomingConnection() {
82 if (incoming_connections_.empty())
83 return nullptr;
84 std::unique_ptr<UnixSocket> sock = std::move(incoming_connections_.front());
85 incoming_connections_.pop_front();
86 return sock;
87 }
88
89 private:
90 std::list<std::unique_ptr<UnixSocket>> incoming_connections_;
91 };
92
93 class UnixSocketTest : public ::testing::Test {
94 protected:
SetUp()95 void SetUp() override { kTestSocket.Destroy(); }
TearDown()96 void TearDown() override { kTestSocket.Destroy(); }
97
98 TestTaskRunner task_runner_;
99 MockEventListener event_listener_;
100 };
101
TEST_F(UnixSocketTest,ConnectionFailureIfUnreachable)102 TEST_F(UnixSocketTest, ConnectionFailureIfUnreachable) {
103 auto cli =
104 UnixSocket::Connect(kTestSocket.name(), &event_listener_, &task_runner_,
105 kTestSocket.family(), SockType::kStream);
106 ASSERT_FALSE(cli->is_connected());
107 auto checkpoint = task_runner_.CreateCheckpoint("failure");
108 EXPECT_CALL(event_listener_, OnConnect(cli.get(), false))
109 .WillOnce(InvokeWithoutArgs(checkpoint));
110 task_runner_.RunUntilCheckpoint("failure");
111 }
112
113 // Both server and client should see an OnDisconnect() if the server drops
114 // incoming connections immediately as they are created.
TEST_F(UnixSocketTest,ConnectionImmediatelyDroppedByServer)115 TEST_F(UnixSocketTest, ConnectionImmediatelyDroppedByServer) {
116 auto srv =
117 UnixSocket::Listen(kTestSocket.name(), &event_listener_, &task_runner_,
118 kTestSocket.family(), SockType::kStream);
119 ASSERT_TRUE(srv->is_listening());
120
121 // The server will immediately shutdown the connection upon
122 // OnNewIncomingConnection().
123 auto srv_did_shutdown = task_runner_.CreateCheckpoint("srv_did_shutdown");
124 EXPECT_CALL(event_listener_, OnNewIncomingConnection(srv.get(), _))
125 .WillOnce(
126 Invoke([this, srv_did_shutdown](UnixSocket*, UnixSocket* new_conn) {
127 EXPECT_CALL(event_listener_, OnDisconnect(new_conn));
128 new_conn->Shutdown(true);
129 srv_did_shutdown();
130 }));
131
132 auto checkpoint = task_runner_.CreateCheckpoint("cli_connected");
133 auto cli =
134 UnixSocket::Connect(kTestSocket.name(), &event_listener_, &task_runner_,
135 kTestSocket.family(), SockType::kStream);
136 EXPECT_CALL(event_listener_, OnConnect(cli.get(), true))
137 .WillOnce(InvokeWithoutArgs(checkpoint));
138 task_runner_.RunUntilCheckpoint("cli_connected");
139 task_runner_.RunUntilCheckpoint("srv_did_shutdown");
140
141 // Trying to send something will trigger the disconnection notification.
142 auto cli_disconnected = task_runner_.CreateCheckpoint("cli_disconnected");
143 EXPECT_CALL(event_listener_, OnDisconnect(cli.get()))
144 .WillOnce(InvokeWithoutArgs(cli_disconnected));
145
146 // On Windows the first send immediately after the disconnection succeeds, the
147 // kernel will detect the disconnection only later.
148 cli->SendStr(".");
149 EXPECT_FALSE(cli->SendStr("should_fail_both_on_win_and_unix"));
150 task_runner_.RunUntilCheckpoint("cli_disconnected");
151 }
152
TEST_F(UnixSocketTest,ClientAndServerExchangeData)153 TEST_F(UnixSocketTest, ClientAndServerExchangeData) {
154 auto srv =
155 UnixSocket::Listen(kTestSocket.name(), &event_listener_, &task_runner_,
156 kTestSocket.family(), SockType::kStream);
157 ASSERT_TRUE(srv->is_listening());
158
159 auto cli =
160 UnixSocket::Connect(kTestSocket.name(), &event_listener_, &task_runner_,
161 kTestSocket.family(), SockType::kStream);
162 auto cli_connected = task_runner_.CreateCheckpoint("cli_connected");
163 EXPECT_CALL(event_listener_, OnConnect(cli.get(), true))
164 .WillOnce(InvokeWithoutArgs(cli_connected));
165 auto srv_conn_seen = task_runner_.CreateCheckpoint("srv_conn_seen");
166 auto srv_disconnected = task_runner_.CreateCheckpoint("srv_disconnected");
167 EXPECT_CALL(event_listener_, OnNewIncomingConnection(srv.get(), _))
168 .WillOnce(Invoke([this, srv_conn_seen, srv_disconnected](
169 UnixSocket*, UnixSocket* srv_conn) {
170 EXPECT_CALL(event_listener_, OnDisconnect(srv_conn))
171 .WillOnce(InvokeWithoutArgs(srv_disconnected));
172 srv_conn_seen();
173 }));
174 task_runner_.RunUntilCheckpoint("srv_conn_seen");
175 task_runner_.RunUntilCheckpoint("cli_connected");
176
177 auto srv_conn = event_listener_.GetIncomingConnection();
178 ASSERT_TRUE(srv_conn);
179 ASSERT_TRUE(cli->is_connected());
180
181 auto cli_did_recv = task_runner_.CreateCheckpoint("cli_did_recv");
182 EXPECT_CALL(event_listener_, OnDataAvailable(cli.get()))
183 .WillOnce(Invoke([cli_did_recv](UnixSocket* s) {
184 ASSERT_EQ("srv>cli", s->ReceiveString());
185 cli_did_recv();
186 }));
187
188 auto srv_did_recv = task_runner_.CreateCheckpoint("srv_did_recv");
189 EXPECT_CALL(event_listener_, OnDataAvailable(srv_conn.get()))
190 .WillOnce(Invoke([srv_did_recv](UnixSocket* s) {
191 ASSERT_EQ("cli>srv", s->ReceiveString());
192 srv_did_recv();
193 }));
194 ASSERT_TRUE(cli->SendStr("cli>srv"));
195 ASSERT_TRUE(srv_conn->SendStr("srv>cli"));
196 task_runner_.RunUntilCheckpoint("cli_did_recv");
197 task_runner_.RunUntilCheckpoint("srv_did_recv");
198
199 // Check that Send/Receive() fails gracefully once the socket is closed.
200 auto cli_disconnected = task_runner_.CreateCheckpoint("cli_disconnected");
201 EXPECT_CALL(event_listener_, OnDisconnect(cli.get()))
202 .WillOnce(InvokeWithoutArgs(cli_disconnected));
203 cli->Shutdown(true);
204 char msg[4];
205 ASSERT_EQ(0u, cli->Receive(&msg, sizeof(msg)));
206 ASSERT_EQ("", cli->ReceiveString());
207 ASSERT_EQ(0u, srv_conn->Receive(&msg, sizeof(msg)));
208 ASSERT_EQ("", srv_conn->ReceiveString());
209 ASSERT_FALSE(cli->SendStr("foo"));
210 ASSERT_FALSE(srv_conn->SendStr("bar"));
211 srv->Shutdown(true);
212 task_runner_.RunUntilCheckpoint("cli_disconnected");
213 task_runner_.RunUntilCheckpoint("srv_disconnected");
214 }
215
TEST_F(UnixSocketTest,ListenWithPassedSocketHandle)216 TEST_F(UnixSocketTest, ListenWithPassedSocketHandle) {
217 auto sock_raw =
218 UnixSocketRaw::CreateMayFail(kTestSocket.family(), SockType::kStream);
219 ASSERT_TRUE(sock_raw.Bind(kTestSocket.name()));
220 auto fd = sock_raw.ReleaseFd();
221 auto srv = UnixSocket::Listen(std::move(fd), &event_listener_, &task_runner_,
222 kTestSocket.family(), SockType::kStream);
223 ASSERT_TRUE(srv->is_listening());
224
225 auto cli_connected = task_runner_.CreateCheckpoint("cli_connected");
226 auto cli =
227 UnixSocket::Connect(kTestSocket.name(), &event_listener_, &task_runner_,
228 kTestSocket.family(), SockType::kStream);
229 EXPECT_CALL(event_listener_, OnConnect(cli.get(), true))
230 .WillOnce(InvokeWithoutArgs(cli_connected));
231 auto srv_connected = task_runner_.CreateCheckpoint("srv_connected");
232 auto srv_disconnected = task_runner_.CreateCheckpoint("srv_disconnected");
233 EXPECT_CALL(event_listener_, OnNewIncomingConnection(srv.get(), _))
234 .WillOnce(Invoke([this, srv_connected, srv_disconnected](
235 UnixSocket*, UnixSocket* srv_conn) {
236 // An empty OnDataAvailable might be raised to signal the EOF state.
237 EXPECT_CALL(event_listener_, OnDataAvailable(srv_conn))
238 .WillRepeatedly(
239 InvokeWithoutArgs([srv_conn] { srv_conn->ReceiveString(); }));
240 EXPECT_CALL(event_listener_, OnDisconnect(srv_conn))
241 .WillOnce(InvokeWithoutArgs(srv_disconnected));
242 srv_connected();
243 }));
244 task_runner_.RunUntilCheckpoint("srv_connected");
245 task_runner_.RunUntilCheckpoint("cli_connected");
246 ASSERT_TRUE(cli->is_connected());
247 cli.reset();
248 task_runner_.RunUntilCheckpoint("srv_disconnected");
249 }
250
251 // Mostly a stress tests. Connects kNumClients clients to the same server and
252 // tests that all can exchange data and can see the expected sequence of events.
TEST_F(UnixSocketTest,SeveralClients)253 TEST_F(UnixSocketTest, SeveralClients) {
254 auto srv =
255 UnixSocket::Listen(kTestSocket.name(), &event_listener_, &task_runner_,
256 kTestSocket.family(), SockType::kStream);
257 ASSERT_TRUE(srv->is_listening());
258 constexpr size_t kNumClients = 32;
259 std::unique_ptr<UnixSocket> cli[kNumClients];
260
261 EXPECT_CALL(event_listener_, OnNewIncomingConnection(srv.get(), _))
262 .Times(kNumClients)
263 .WillRepeatedly(Invoke([this](UnixSocket*, UnixSocket* s) {
264 EXPECT_CALL(event_listener_, OnDataAvailable(s))
265 .WillOnce(Invoke([](UnixSocket* t) {
266 ASSERT_EQ("PING", t->ReceiveString());
267 ASSERT_TRUE(t->SendStr("PONG"));
268 }));
269 }));
270
271 for (size_t i = 0; i < kNumClients; i++) {
272 cli[i] =
273 UnixSocket::Connect(kTestSocket.name(), &event_listener_, &task_runner_,
274 kTestSocket.family(), SockType::kStream);
275 EXPECT_CALL(event_listener_, OnConnect(cli[i].get(), true))
276 .WillOnce(Invoke([](UnixSocket* s, bool success) {
277 ASSERT_TRUE(success);
278 ASSERT_TRUE(s->SendStr("PING"));
279 }));
280
281 auto checkpoint = task_runner_.CreateCheckpoint(std::to_string(i));
282 EXPECT_CALL(event_listener_, OnDataAvailable(cli[i].get()))
283 .WillOnce(Invoke([checkpoint](UnixSocket* s) {
284 ASSERT_EQ("PONG", s->ReceiveString());
285 checkpoint();
286 }));
287 }
288
289 for (size_t i = 0; i < kNumClients; i++) {
290 task_runner_.RunUntilCheckpoint(std::to_string(i));
291 ASSERT_TRUE(Mock::VerifyAndClearExpectations(cli[i].get()));
292 }
293 }
294
TEST_F(UnixSocketTest,BlockingSend)295 TEST_F(UnixSocketTest, BlockingSend) {
296 auto srv =
297 UnixSocket::Listen(kTestSocket.name(), &event_listener_, &task_runner_,
298 kTestSocket.family(), SockType::kStream);
299 ASSERT_TRUE(srv->is_listening());
300
301 auto all_frames_done = task_runner_.CreateCheckpoint("all_frames_done");
302 size_t total_bytes_received = 0;
303 static constexpr size_t kTotalBytes = 1024 * 1024 * 4;
304 EXPECT_CALL(event_listener_, OnNewIncomingConnection(srv.get(), _))
305 .WillOnce(Invoke([this, &total_bytes_received, all_frames_done](
306 UnixSocket*, UnixSocket* srv_conn) {
307 EXPECT_CALL(event_listener_, OnDataAvailable(srv_conn))
308 .WillRepeatedly(
309 Invoke([&total_bytes_received, all_frames_done](UnixSocket* s) {
310 char buf[1024];
311 size_t res = s->Receive(buf, sizeof(buf));
312 total_bytes_received += res;
313 if (total_bytes_received == kTotalBytes)
314 all_frames_done();
315 }));
316 }));
317
318 // Override default timeout as this test can take time on the emulator.
319 static constexpr int kTimeoutMs = 60000 * 3;
320
321 // Perform the blocking send form another thread.
322 std::thread tx_thread([] {
323 TestTaskRunner tx_task_runner;
324 MockEventListener tx_events;
325 auto cli =
326 UnixSocket::Connect(kTestSocket.name(), &tx_events, &tx_task_runner,
327 kTestSocket.family(), SockType::kStream);
328
329 auto cli_connected = tx_task_runner.CreateCheckpoint("cli_connected");
330 EXPECT_CALL(tx_events, OnConnect(cli.get(), true))
331 .WillOnce(InvokeWithoutArgs(cli_connected));
332 tx_task_runner.RunUntilCheckpoint("cli_connected");
333
334 auto all_sent = tx_task_runner.CreateCheckpoint("all_sent");
335 std::string buf(1024 * 32, '\0');
336 tx_task_runner.PostTask([&cli, &buf, all_sent] {
337 for (size_t i = 0; i < kTotalBytes / buf.size(); i++)
338 cli->Send(buf.data(), buf.size());
339 all_sent();
340 });
341 tx_task_runner.RunUntilCheckpoint("all_sent", kTimeoutMs);
342 });
343
344 task_runner_.RunUntilCheckpoint("all_frames_done", kTimeoutMs);
345 tx_thread.join();
346 }
347
348 // Regression test for b/76155349 . If the receiver end disconnects while the
349 // sender is in the middle of a large send(), the socket should gracefully give
350 // up (i.e. Shutdown()) but not crash.
TEST_F(UnixSocketTest,ReceiverDisconnectsDuringSend)351 TEST_F(UnixSocketTest, ReceiverDisconnectsDuringSend) {
352 auto srv =
353 UnixSocket::Listen(kTestSocket.name(), &event_listener_, &task_runner_,
354 kTestSocket.family(), SockType::kStream);
355 ASSERT_TRUE(srv->is_listening());
356 static constexpr int kTimeoutMs = 30000;
357
358 auto receive_done = task_runner_.CreateCheckpoint("receive_done");
359 EXPECT_CALL(event_listener_, OnNewIncomingConnection(srv.get(), _))
360 .WillOnce(Invoke([this, receive_done](UnixSocket*, UnixSocket* srv_conn) {
361 EXPECT_CALL(event_listener_, OnDataAvailable(srv_conn))
362 .WillOnce(Invoke([receive_done](UnixSocket* s) {
363 char buf[1024];
364 size_t res = s->Receive(buf, sizeof(buf));
365 ASSERT_EQ(1024u, res);
366 s->Shutdown(false /*notify*/);
367 receive_done();
368 }));
369 }));
370
371 // Perform the blocking send form another thread.
372 std::thread tx_thread([] {
373 TestTaskRunner tx_task_runner;
374 MockEventListener tx_events;
375 auto cli =
376 UnixSocket::Connect(kTestSocket.name(), &tx_events, &tx_task_runner,
377 kTestSocket.family(), SockType::kStream);
378
379 auto cli_connected = tx_task_runner.CreateCheckpoint("cli_connected");
380 EXPECT_CALL(tx_events, OnConnect(cli.get(), true))
381 .WillOnce(InvokeWithoutArgs(cli_connected));
382 tx_task_runner.RunUntilCheckpoint("cli_connected");
383
384 auto send_done = tx_task_runner.CreateCheckpoint("send_done");
385 static constexpr size_t kBufSize = 32 * 1024 * 1024;
386 std::unique_ptr<char[]> buf(new char[kBufSize]());
387 tx_task_runner.PostTask([&cli, &buf, send_done] {
388 cli->Send(buf.get(), kBufSize);
389 send_done();
390 });
391
392 tx_task_runner.RunUntilCheckpoint("send_done", kTimeoutMs);
393 });
394 task_runner_.RunUntilCheckpoint("receive_done", kTimeoutMs);
395 tx_thread.join();
396 }
397
TEST_F(UnixSocketTest,ReleaseSocket)398 TEST_F(UnixSocketTest, ReleaseSocket) {
399 auto srv =
400 UnixSocket::Listen(kTestSocket.name(), &event_listener_, &task_runner_,
401 kTestSocket.family(), SockType::kStream);
402 ASSERT_TRUE(srv->is_listening());
403 auto srv_connected = task_runner_.CreateCheckpoint("srv_connected");
404 UnixSocket* peer = nullptr;
405 EXPECT_CALL(event_listener_, OnNewIncomingConnection(srv.get(), _))
406 .WillOnce(
407 Invoke([srv_connected, &peer](UnixSocket*, UnixSocket* new_conn) {
408 peer = new_conn;
409 srv_connected();
410 }));
411
412 auto cli =
413 UnixSocket::Connect(kTestSocket.name(), &event_listener_, &task_runner_,
414 kTestSocket.family(), SockType::kStream);
415 auto cli_connected = task_runner_.CreateCheckpoint("cli_connected");
416 EXPECT_CALL(event_listener_, OnConnect(cli.get(), true))
417 .WillOnce(InvokeWithoutArgs(cli_connected));
418 task_runner_.RunUntilCheckpoint("srv_connected");
419 task_runner_.RunUntilCheckpoint("cli_connected");
420 srv->Shutdown(true);
421
422 cli->SendStr("test");
423
424 ASSERT_NE(peer, nullptr);
425 auto raw_sock = peer->ReleaseSocket();
426
427 EXPECT_CALL(event_listener_, OnDataAvailable(_)).Times(0);
428 task_runner_.RunUntilIdle();
429
430 char buf[5];
431 ASSERT_TRUE(raw_sock);
432 ASSERT_EQ(raw_sock.Receive(buf, sizeof(buf)), 4);
433 buf[sizeof(buf) - 1] = '\0';
434 ASSERT_STREQ(buf, "test");
435 }
436
437 // Tests that the return value of GetSockAddr() returns a well formatted address
438 // that can be passed to UnixSocket::Connect().
TEST_F(UnixSocketTest,GetSockAddrTcp4)439 TEST_F(UnixSocketTest, GetSockAddrTcp4) {
440 auto srv = UnixSocket::Listen("127.0.0.1:0", &event_listener_, &task_runner_,
441 SockFamily::kInet, SockType::kStream);
442 ASSERT_TRUE(srv->is_listening());
443
444 auto cli =
445 UnixSocket::Connect(srv->GetSockAddr(), &event_listener_, &task_runner_,
446 SockFamily::kInet, SockType::kStream);
447 EXPECT_CALL(event_listener_, OnConnect(cli.get(), true))
448 .WillOnce(InvokeWithoutArgs(task_runner_.CreateCheckpoint("connected")));
449 task_runner_.RunUntilCheckpoint("connected");
450 }
451
TEST_F(UnixSocketTest,GetSockAddrTcp6)452 TEST_F(UnixSocketTest, GetSockAddrTcp6) {
453 auto srv = UnixSocket::Listen("[::1]:0", &event_listener_, &task_runner_,
454 SockFamily::kInet6, SockType::kStream);
455 if (!srv)
456 GTEST_SKIP() << "This test requires IPv6 support in the OS. Skipping";
457
458 ASSERT_TRUE(srv->is_listening());
459 auto cli =
460 UnixSocket::Connect(srv->GetSockAddr(), &event_listener_, &task_runner_,
461 SockFamily::kInet6, SockType::kStream);
462
463 EXPECT_CALL(event_listener_, OnConnect(cli.get(), true))
464 .WillOnce(InvokeWithoutArgs(task_runner_.CreateCheckpoint("connected")));
465 task_runner_.RunUntilCheckpoint("connected");
466 }
467
468 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
469 PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
470 PERFETTO_BUILDFLAG(PERFETTO_OS_MAC)
TEST_F(UnixSocketTest,GetSockAddrUnixLinked)471 TEST_F(UnixSocketTest, GetSockAddrUnixLinked) {
472 TempDir tmp_dir = TempDir::Create();
473 std::string sock_path = tmp_dir.path() + "/test.sock";
474 auto srv = UnixSocket::Listen(sock_path, &event_listener_, &task_runner_,
475 SockFamily::kUnix, SockType::kStream);
476 ASSERT_TRUE(srv->is_listening());
477 EXPECT_EQ(sock_path, srv->GetSockAddr());
478 auto cli =
479 UnixSocket::Connect(srv->GetSockAddr(), &event_listener_, &task_runner_,
480 SockFamily::kUnix, SockType::kStream);
481 EXPECT_CALL(event_listener_, OnConnect(cli.get(), true))
482 .WillOnce(InvokeWithoutArgs(task_runner_.CreateCheckpoint("connected")));
483 task_runner_.RunUntilCheckpoint("connected");
484 cli.reset();
485 srv.reset();
486 remove(sock_path.c_str());
487 }
488 #endif
489
490 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
491 PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
TEST_F(UnixSocketTest,GetSockAddrUnixAbstract)492 TEST_F(UnixSocketTest, GetSockAddrUnixAbstract) {
493 StackString<128> sock_name("@perfetto_sock_%d_%d", getpid(), rand() % 100000);
494
495 auto srv =
496 UnixSocket::Listen(sock_name.ToStdString(), &event_listener_,
497 &task_runner_, SockFamily::kUnix, SockType::kStream);
498 ASSERT_TRUE(srv->is_listening());
499 EXPECT_EQ(sock_name.ToStdString(), srv->GetSockAddr());
500 auto cli =
501 UnixSocket::Connect(srv->GetSockAddr(), &event_listener_, &task_runner_,
502 SockFamily::kUnix, SockType::kStream);
503 EXPECT_CALL(event_listener_, OnConnect(cli.get(), true))
504 .WillOnce(InvokeWithoutArgs(task_runner_.CreateCheckpoint("connected")));
505 task_runner_.RunUntilCheckpoint("connected");
506 }
507 #endif
508
509 #if (PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
510 PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID))
TEST_F(UnixSocketTest,GetSockAddrVsock)511 TEST_F(UnixSocketTest, GetSockAddrVsock) {
512 SKIP_IF_VSOCK_LOOPBACK_NOT_SUPPORTED();
513
514 auto srv = UnixSocket::Listen("vsock://1:-1", &event_listener_, &task_runner_,
515 SockFamily::kVsock, SockType::kStream);
516 ASSERT_TRUE(srv->is_listening());
517 auto cli =
518 UnixSocket::Connect(srv->GetSockAddr(), &event_listener_, &task_runner_,
519 SockFamily::kVsock, SockType::kStream);
520
521 EXPECT_CALL(event_listener_, OnConnect(cli.get(), true))
522 .WillOnce(InvokeWithoutArgs(task_runner_.CreateCheckpoint("connected")));
523 task_runner_.RunUntilCheckpoint("connected");
524 }
525 #endif
526
TEST_F(UnixSocketTest,TcpStream)527 TEST_F(UnixSocketTest, TcpStream) {
528 // Listen on a random port.
529 std::unique_ptr<UnixSocket> srv =
530 UnixSocket::Listen("127.0.0.1:0", &event_listener_, &task_runner_,
531 SockFamily::kInet, SockType::kStream);
532 ASSERT_TRUE(srv->is_listening());
533 std::string host_and_port = srv->GetSockAddr();
534 constexpr size_t kNumClients = 3;
535 std::unique_ptr<UnixSocket> cli[kNumClients];
536 EXPECT_CALL(event_listener_, OnNewIncomingConnection(srv.get(), _))
537 .Times(kNumClients)
538 .WillRepeatedly(Invoke([&](UnixSocket*, UnixSocket* s) {
539 // OnDisconnect() might spuriously happen depending on the dtor order.
540 EXPECT_CALL(event_listener_, OnDisconnect(s)).Times(AtLeast(0));
541 EXPECT_CALL(event_listener_, OnDataAvailable(s))
542 .WillRepeatedly(Invoke([](UnixSocket* cli_sock) {
543 cli_sock->ReceiveString(); // Read connection EOF;
544 }));
545 ASSERT_TRUE(s->SendStr("welcome"));
546 }));
547
548 for (size_t i = 0; i < kNumClients; i++) {
549 cli[i] = UnixSocket::Connect(host_and_port, &event_listener_, &task_runner_,
550 SockFamily::kInet, SockType::kStream);
551 auto checkpoint = task_runner_.CreateCheckpoint(std::to_string(i));
552 EXPECT_CALL(event_listener_, OnDisconnect(cli[i].get())).Times(AtLeast(0));
553 EXPECT_CALL(event_listener_, OnConnect(cli[i].get(), true));
554 EXPECT_CALL(event_listener_, OnDataAvailable(cli[i].get()))
555 .WillRepeatedly(Invoke([checkpoint](UnixSocket* s) {
556 auto str = s->ReceiveString();
557 if (str == "")
558 return; // Connection EOF.
559 ASSERT_EQ("welcome", str);
560 checkpoint();
561 }));
562 }
563
564 for (size_t i = 0; i < kNumClients; i++) {
565 task_runner_.RunUntilCheckpoint(std::to_string(i));
566 ASSERT_TRUE(Mock::VerifyAndClearExpectations(cli[i].get()));
567 }
568 }
569
570 // ---------------------------------
571 // Posix-only tests below this point
572 // ---------------------------------
573
574 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
575
576 // Tests the SockPeerCredMode::kIgnore logic.
TEST_F(UnixSocketTest,IgnorePeerCredentials)577 TEST_F(UnixSocketTest, IgnorePeerCredentials) {
578 auto srv =
579 UnixSocket::Listen(kTestSocket.name(), &event_listener_, &task_runner_,
580 kTestSocket.family(), SockType::kStream);
581 ASSERT_TRUE(srv->is_listening());
582 auto cli1_connected = task_runner_.CreateCheckpoint("cli1_connected");
583 auto cli1 = UnixSocket::Connect(kTestSocket.name(), &event_listener_,
584 &task_runner_, kTestSocket.family(),
585 SockType::kStream, SockPeerCredMode::kIgnore);
586 EXPECT_CALL(event_listener_, OnConnect(cli1.get(), true))
587 .WillOnce(InvokeWithoutArgs(cli1_connected));
588
589 auto cli2_connected = task_runner_.CreateCheckpoint("cli2_connected");
590 auto cli2 = UnixSocket::Connect(
591 kTestSocket.name(), &event_listener_, &task_runner_, kTestSocket.family(),
592 SockType::kStream, SockPeerCredMode::kReadOnConnect);
593 EXPECT_CALL(event_listener_, OnConnect(cli2.get(), true))
594 .WillOnce(InvokeWithoutArgs(cli2_connected));
595
596 task_runner_.RunUntilCheckpoint("cli1_connected");
597 task_runner_.RunUntilCheckpoint("cli2_connected");
598
599 ASSERT_EQ(cli1->peer_uid_posix(/*skip_check_for_testing=*/true), kInvalidUid);
600 ASSERT_EQ(cli2->peer_uid_posix(), geteuid());
601 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
602 PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
603 ASSERT_EQ(cli1->peer_pid_linux(/*skip_check_for_testing=*/true), kInvalidPid);
604 ASSERT_EQ(cli2->peer_pid_linux(), getpid());
605 #endif
606 }
607
608 // Checks that the peer_uid() is retained after the client disconnects. The IPC
609 // layer needs to rely on this to validate messages received immediately before
610 // a client disconnects.
TEST_F(UnixSocketTest,PeerCredentialsRetainedAfterDisconnect)611 TEST_F(UnixSocketTest, PeerCredentialsRetainedAfterDisconnect) {
612 auto srv =
613 UnixSocket::Listen(kTestSocket.name(), &event_listener_, &task_runner_,
614 kTestSocket.family(), SockType::kStream);
615 ASSERT_TRUE(srv->is_listening());
616 UnixSocket* srv_client_conn = nullptr;
617 auto srv_connected = task_runner_.CreateCheckpoint("srv_connected");
618 EXPECT_CALL(event_listener_, OnNewIncomingConnection(srv.get(), _))
619 .WillOnce(Invoke([&srv_client_conn, srv_connected](UnixSocket*,
620 UnixSocket* srv_conn) {
621 srv_client_conn = srv_conn;
622 EXPECT_EQ(geteuid(), static_cast<uint32_t>(srv_conn->peer_uid_posix()));
623 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
624 PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
625 EXPECT_EQ(getpid(), static_cast<pid_t>(srv_conn->peer_pid_linux()));
626 #endif
627 srv_connected();
628 }));
629 auto cli_connected = task_runner_.CreateCheckpoint("cli_connected");
630 auto cli =
631 UnixSocket::Connect(kTestSocket.name(), &event_listener_, &task_runner_,
632 kTestSocket.family(), SockType::kStream);
633 EXPECT_CALL(event_listener_, OnConnect(cli.get(), true))
634 .WillOnce(InvokeWithoutArgs(cli_connected));
635
636 task_runner_.RunUntilCheckpoint("cli_connected");
637 task_runner_.RunUntilCheckpoint("srv_connected");
638 ASSERT_NE(nullptr, srv_client_conn);
639 ASSERT_TRUE(srv_client_conn->is_connected());
640
641 auto cli_disconnected = task_runner_.CreateCheckpoint("cli_disconnected");
642 EXPECT_CALL(event_listener_, OnDisconnect(srv_client_conn))
643 .WillOnce(InvokeWithoutArgs(cli_disconnected));
644
645 // TODO(primiano): when the a peer disconnects, the other end receives a
646 // spurious OnDataAvailable() that needs to be acked with a Receive() to read
647 // the EOF. See b/69536434.
648 EXPECT_CALL(event_listener_, OnDataAvailable(srv_client_conn))
649 .WillOnce(Invoke([](UnixSocket* sock) { sock->ReceiveString(); }));
650
651 cli.reset();
652 task_runner_.RunUntilCheckpoint("cli_disconnected");
653 ASSERT_FALSE(srv_client_conn->is_connected());
654 EXPECT_EQ(geteuid(),
655 static_cast<uint32_t>(srv_client_conn->peer_uid_posix()));
656 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
657 PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
658 EXPECT_EQ(getpid(), static_cast<pid_t>(srv_client_conn->peer_pid_linux()));
659 #endif
660 }
661
TEST_F(UnixSocketTest,ClientAndServerExchangeFDs)662 TEST_F(UnixSocketTest, ClientAndServerExchangeFDs) {
663 static constexpr char cli_str[] = "cli>srv";
664 static constexpr char srv_str[] = "srv>cli";
665 auto srv =
666 UnixSocket::Listen(kTestSocket.name(), &event_listener_, &task_runner_,
667 kTestSocket.family(), SockType::kStream);
668 ASSERT_TRUE(srv->is_listening());
669
670 auto cli =
671 UnixSocket::Connect(kTestSocket.name(), &event_listener_, &task_runner_,
672 kTestSocket.family(), SockType::kStream);
673 EXPECT_CALL(event_listener_, OnConnect(cli.get(), true));
674 auto cli_connected = task_runner_.CreateCheckpoint("cli_connected");
675 auto srv_disconnected = task_runner_.CreateCheckpoint("srv_disconnected");
676 EXPECT_CALL(event_listener_, OnNewIncomingConnection(srv.get(), _))
677 .WillOnce(Invoke([this, cli_connected, srv_disconnected](
678 UnixSocket*, UnixSocket* srv_conn) {
679 EXPECT_CALL(event_listener_, OnDisconnect(srv_conn))
680 .WillOnce(InvokeWithoutArgs(srv_disconnected));
681 cli_connected();
682 }));
683 task_runner_.RunUntilCheckpoint("cli_connected");
684
685 auto srv_conn = event_listener_.GetIncomingConnection();
686 ASSERT_TRUE(srv_conn);
687 ASSERT_TRUE(cli->is_connected());
688
689 ScopedFile null_fd(base::OpenFile("/dev/null", O_RDONLY));
690 ScopedFile zero_fd(base::OpenFile("/dev/zero", O_RDONLY));
691
692 auto cli_did_recv = task_runner_.CreateCheckpoint("cli_did_recv");
693 EXPECT_CALL(event_listener_, OnDataAvailable(cli.get()))
694 .WillRepeatedly(Invoke([cli_did_recv](UnixSocket* s) {
695 ScopedFile fd_buf[3];
696 char buf[sizeof(cli_str)];
697 if (!s->Receive(buf, sizeof(buf), fd_buf, ArraySize(fd_buf)))
698 return;
699 ASSERT_STREQ(srv_str, buf);
700 ASSERT_NE(*fd_buf[0], -1);
701 ASSERT_NE(*fd_buf[1], -1);
702 ASSERT_EQ(*fd_buf[2], -1);
703
704 char rd_buf[1];
705 // /dev/null
706 ASSERT_EQ(read(*fd_buf[0], rd_buf, sizeof(rd_buf)), 0);
707 // /dev/zero
708 ASSERT_EQ(read(*fd_buf[1], rd_buf, sizeof(rd_buf)), 1);
709 cli_did_recv();
710 }));
711
712 auto srv_did_recv = task_runner_.CreateCheckpoint("srv_did_recv");
713 EXPECT_CALL(event_listener_, OnDataAvailable(srv_conn.get()))
714 .WillRepeatedly(Invoke([srv_did_recv](UnixSocket* s) {
715 ScopedFile fd_buf[3];
716 char buf[sizeof(srv_str)];
717 if (!s->Receive(buf, sizeof(buf), fd_buf, ArraySize(fd_buf)))
718 return;
719 ASSERT_STREQ(cli_str, buf);
720 ASSERT_NE(*fd_buf[0], -1);
721 ASSERT_NE(*fd_buf[1], -1);
722 ASSERT_EQ(*fd_buf[2], -1);
723
724 char rd_buf[1];
725 // /dev/null
726 ASSERT_EQ(read(*fd_buf[0], rd_buf, sizeof(rd_buf)), 0);
727 // /dev/zero
728 ASSERT_EQ(read(*fd_buf[1], rd_buf, sizeof(rd_buf)), 1);
729 srv_did_recv();
730 }));
731
732 int buf_fd[2] = {null_fd.get(), zero_fd.get()};
733
734 ASSERT_TRUE(
735 cli->Send(cli_str, sizeof(cli_str), buf_fd, base::ArraySize(buf_fd)));
736 ASSERT_TRUE(srv_conn->Send(srv_str, sizeof(srv_str), buf_fd,
737 base::ArraySize(buf_fd)));
738 task_runner_.RunUntilCheckpoint("srv_did_recv");
739 task_runner_.RunUntilCheckpoint("cli_did_recv");
740
741 auto cli_disconnected = task_runner_.CreateCheckpoint("cli_disconnected");
742 EXPECT_CALL(event_listener_, OnDisconnect(cli.get()))
743 .WillOnce(InvokeWithoutArgs(cli_disconnected));
744 cli->Shutdown(true);
745 srv->Shutdown(true);
746 task_runner_.RunUntilCheckpoint("srv_disconnected");
747 task_runner_.RunUntilCheckpoint("cli_disconnected");
748 }
749
750 // Creates two processes. The server process creates a file and passes it over
751 // the socket to the client. Both processes mmap the file in shared mode and
752 // check that they see the same contents.
TEST_F(UnixSocketTest,SharedMemory)753 TEST_F(UnixSocketTest, SharedMemory) {
754 Pipe pipe = Pipe::Create();
755 pid_t pid = fork();
756 ASSERT_GE(pid, 0);
757 constexpr size_t kTmpSize = 4096;
758
759 if (pid == 0) {
760 // Child process.
761 TempFile scoped_tmp = TempFile::CreateUnlinked();
762 int tmp_fd = scoped_tmp.fd();
763 ASSERT_FALSE(ftruncate(tmp_fd, kTmpSize));
764 char* mem = reinterpret_cast<char*>(
765 mmap(nullptr, kTmpSize, PROT_READ | PROT_WRITE, MAP_SHARED, tmp_fd, 0));
766 ASSERT_NE(nullptr, mem);
767 memcpy(mem, "shm rocks", 10);
768
769 auto srv =
770 UnixSocket::Listen(kTestSocket.name(), &event_listener_, &task_runner_,
771 kTestSocket.family(), SockType::kStream);
772 ASSERT_TRUE(srv->is_listening());
773 // Signal the other process that it can connect.
774 ASSERT_EQ(1, base::WriteAll(*pipe.wr, ".", 1));
775 auto checkpoint = task_runner_.CreateCheckpoint("change_seen_by_server");
776 EXPECT_CALL(event_listener_, OnNewIncomingConnection(srv.get(), _))
777 .WillOnce(Invoke(
778 [this, tmp_fd, checkpoint, mem](UnixSocket*, UnixSocket* new_conn) {
779 ASSERT_EQ(geteuid(),
780 static_cast<uint32_t>(new_conn->peer_uid_posix()));
781 ASSERT_TRUE(new_conn->Send("txfd", 5, tmp_fd));
782 // Wait for the client to change this again.
783 EXPECT_CALL(event_listener_, OnDataAvailable(new_conn))
784 .WillOnce(Invoke([checkpoint, mem](UnixSocket* s) {
785 ASSERT_EQ("change notify", s->ReceiveString());
786 ASSERT_STREQ("rock more", mem);
787 checkpoint();
788 }));
789 }));
790 task_runner_.RunUntilCheckpoint("change_seen_by_server");
791 ASSERT_TRUE(Mock::VerifyAndClearExpectations(&event_listener_));
792 _exit(0);
793 } else {
794 char sync_cmd = '\0';
795 ASSERT_EQ(1, PERFETTO_EINTR(read(*pipe.rd, &sync_cmd, 1)));
796 ASSERT_EQ('.', sync_cmd);
797 auto cli =
798 UnixSocket::Connect(kTestSocket.name(), &event_listener_, &task_runner_,
799 kTestSocket.family(), SockType::kStream);
800 EXPECT_CALL(event_listener_, OnConnect(cli.get(), true));
801 auto checkpoint = task_runner_.CreateCheckpoint("change_seen_by_client");
802 EXPECT_CALL(event_listener_, OnDataAvailable(cli.get()))
803 .WillOnce(Invoke([checkpoint](UnixSocket* s) {
804 char msg[32];
805 ScopedFile fd;
806 ASSERT_EQ(5u, s->Receive(msg, sizeof(msg), &fd));
807 ASSERT_STREQ("txfd", msg);
808 ASSERT_TRUE(fd);
809 char* mem = reinterpret_cast<char*>(mmap(
810 nullptr, kTmpSize, PROT_READ | PROT_WRITE, MAP_SHARED, *fd, 0));
811 ASSERT_NE(nullptr, mem);
812 mem[9] = '\0'; // Just to get a clean error in case of test failure.
813 ASSERT_STREQ("shm rocks", mem);
814
815 // Now change the shared memory and ping the other process.
816 memcpy(mem, "rock more", 10);
817 ASSERT_TRUE(s->SendStr("change notify"));
818 checkpoint();
819 }));
820 task_runner_.RunUntilCheckpoint("change_seen_by_client");
821 int st = 0;
822 PERFETTO_EINTR(waitpid(pid, &st, 0));
823 ASSERT_FALSE(WIFSIGNALED(st)) << "Server died with signal " << WTERMSIG(st);
824 EXPECT_TRUE(WIFEXITED(st));
825 ASSERT_EQ(0, WEXITSTATUS(st));
826 }
827 }
828
TEST_F(UnixSocketTest,ShiftMsgHdrSendPartialFirst)829 TEST_F(UnixSocketTest, ShiftMsgHdrSendPartialFirst) {
830 // Send a part of the first iov, then send the rest.
831 struct iovec iov[2] = {};
832 char hello[] = "hello";
833 char world[] = "world";
834 iov[0].iov_base = &hello[0];
835 iov[0].iov_len = base::ArraySize(hello);
836
837 iov[1].iov_base = &world[0];
838 iov[1].iov_len = base::ArraySize(world);
839
840 struct msghdr hdr = {};
841 hdr.msg_iov = iov;
842 hdr.msg_iovlen = base::ArraySize(iov);
843
844 UnixSocketRaw::ShiftMsgHdrPosix(1, &hdr);
845 EXPECT_NE(hdr.msg_iov, nullptr);
846 EXPECT_EQ(hdr.msg_iov[0].iov_base, &hello[1]);
847 EXPECT_EQ(hdr.msg_iov[1].iov_base, &world[0]);
848 EXPECT_EQ(static_cast<int>(hdr.msg_iovlen), 2);
849 EXPECT_STREQ(reinterpret_cast<char*>(hdr.msg_iov[0].iov_base), "ello");
850 EXPECT_EQ(iov[0].iov_len, base::ArraySize(hello) - 1);
851
852 UnixSocketRaw::ShiftMsgHdrPosix(base::ArraySize(hello) - 1, &hdr);
853 EXPECT_EQ(hdr.msg_iov, &iov[1]);
854 EXPECT_EQ(static_cast<int>(hdr.msg_iovlen), 1);
855 EXPECT_STREQ(reinterpret_cast<char*>(hdr.msg_iov[0].iov_base), world);
856 EXPECT_EQ(hdr.msg_iov[0].iov_len, base::ArraySize(world));
857
858 UnixSocketRaw::ShiftMsgHdrPosix(base::ArraySize(world), &hdr);
859 EXPECT_EQ(hdr.msg_iov, nullptr);
860 EXPECT_EQ(static_cast<int>(hdr.msg_iovlen), 0);
861 }
862
TEST_F(UnixSocketTest,ShiftMsgHdrSendFirstAndPartial)863 TEST_F(UnixSocketTest, ShiftMsgHdrSendFirstAndPartial) {
864 // Send first iov and part of the second iov, then send the rest.
865 struct iovec iov[2] = {};
866 char hello[] = "hello";
867 char world[] = "world";
868 iov[0].iov_base = &hello[0];
869 iov[0].iov_len = base::ArraySize(hello);
870
871 iov[1].iov_base = &world[0];
872 iov[1].iov_len = base::ArraySize(world);
873
874 struct msghdr hdr = {};
875 hdr.msg_iov = iov;
876 hdr.msg_iovlen = base::ArraySize(iov);
877
878 UnixSocketRaw::ShiftMsgHdrPosix(base::ArraySize(hello) + 1, &hdr);
879 EXPECT_NE(hdr.msg_iov, nullptr);
880 EXPECT_EQ(static_cast<int>(hdr.msg_iovlen), 1);
881 EXPECT_STREQ(reinterpret_cast<char*>(hdr.msg_iov[0].iov_base), "orld");
882 EXPECT_EQ(hdr.msg_iov[0].iov_len, base::ArraySize(world) - 1);
883
884 UnixSocketRaw::ShiftMsgHdrPosix(base::ArraySize(world) - 1, &hdr);
885 EXPECT_EQ(hdr.msg_iov, nullptr);
886 EXPECT_EQ(static_cast<int>(hdr.msg_iovlen), 0);
887 }
888
TEST_F(UnixSocketTest,ShiftMsgHdrSendEverything)889 TEST_F(UnixSocketTest, ShiftMsgHdrSendEverything) {
890 // Send everything at once.
891 struct iovec iov[2] = {};
892 char hello[] = "hello";
893 char world[] = "world";
894 iov[0].iov_base = &hello[0];
895 iov[0].iov_len = base::ArraySize(hello);
896
897 iov[1].iov_base = &world[0];
898 iov[1].iov_len = base::ArraySize(world);
899
900 struct msghdr hdr = {};
901 hdr.msg_iov = iov;
902 hdr.msg_iovlen = base::ArraySize(iov);
903
904 UnixSocketRaw::ShiftMsgHdrPosix(
905 base::ArraySize(world) + base::ArraySize(hello), &hdr);
906 EXPECT_EQ(hdr.msg_iov, nullptr);
907 EXPECT_EQ(static_cast<int>(hdr.msg_iovlen), 0);
908 }
909
910 // For use in PartialSendMsgAll template argument. Cannot be a lambda.
RollbackSigaction(const struct sigaction * act)911 int RollbackSigaction(const struct sigaction* act) {
912 return sigaction(SIGWINCH, act, nullptr);
913 }
914
TEST_F(UnixSocketTest,PartialSendMsgAll)915 TEST_F(UnixSocketTest, PartialSendMsgAll) {
916 UnixSocketRaw send_sock;
917 UnixSocketRaw recv_sock;
918 std::tie(send_sock, recv_sock) =
919 UnixSocketRaw::CreatePairPosix(kTestSocket.family(), SockType::kStream);
920 ASSERT_TRUE(send_sock);
921 ASSERT_TRUE(recv_sock);
922
923 // Set bufsize to minimum.
924 int bufsize = 1024;
925 ASSERT_EQ(setsockopt(send_sock.fd(), SOL_SOCKET, SO_SNDBUF, &bufsize,
926 sizeof(bufsize)),
927 0);
928 ASSERT_EQ(setsockopt(recv_sock.fd(), SOL_SOCKET, SO_RCVBUF, &bufsize,
929 sizeof(bufsize)),
930 0);
931
932 // Send something larger than send + recv kernel buffers combined to make
933 // sendmsg block.
934 std::string send_buf(8192, '\0');
935 // Make MSAN happy.
936 for (size_t i = 0; i < send_buf.size(); ++i)
937 send_buf[i] = static_cast<char>(i % 256);
938 std::string recv_buf(send_buf.size(), '\0');
939
940 // Need to install signal handler to cause the interrupt to happen.
941 // man 3 pthread_kill:
942 // Signal dispositions are process-wide: if a signal handler is
943 // installed, the handler will be invoked in the thread thread, but if
944 // the disposition of the signal is "stop", "continue", or "terminate",
945 // this action will affect the whole process.
946 struct sigaction oldact;
947 struct sigaction newact = {};
948 newact.sa_handler = [](int) {};
949 ASSERT_EQ(sigaction(SIGWINCH, &newact, &oldact), 0);
950 base::ScopedResource<const struct sigaction*, RollbackSigaction, nullptr>
951 rollback(&oldact);
952
953 auto blocked_thread = pthread_self();
954 std::thread th([blocked_thread, &recv_sock, &recv_buf] {
955 ssize_t rd = PERFETTO_EINTR(read(recv_sock.fd(), &recv_buf[0], 1));
956 ASSERT_EQ(rd, 1);
957 // We are now sure the other thread is in sendmsg, interrupt send.
958 ASSERT_EQ(pthread_kill(blocked_thread, SIGWINCH), 0);
959 // Drain the socket to allow SendMsgAllPosix to succeed.
960 size_t offset = 1;
961 while (offset < recv_buf.size()) {
962 rd = PERFETTO_EINTR(
963 read(recv_sock.fd(), &recv_buf[offset], recv_buf.size() - offset));
964 ASSERT_GE(rd, 0);
965 offset += static_cast<size_t>(rd);
966 }
967 });
968
969 // Test sending the send_buf in several chunks as an iov to exercise the
970 // more complicated code-paths of SendMsgAllPosix.
971 struct msghdr hdr = {};
972 struct iovec iov[4];
973 ASSERT_EQ(send_buf.size() % base::ArraySize(iov), 0u)
974 << "Cannot split buffer into even pieces.";
975 const size_t kChunkSize = send_buf.size() / base::ArraySize(iov);
976 for (size_t i = 0; i < base::ArraySize(iov); ++i) {
977 iov[i].iov_base = &send_buf[i * kChunkSize];
978 iov[i].iov_len = kChunkSize;
979 }
980 hdr.msg_iov = iov;
981 hdr.msg_iovlen = base::ArraySize(iov);
982
983 ASSERT_EQ(send_sock.SendMsgAllPosix(&hdr),
984 static_cast<ssize_t>(send_buf.size()));
985 send_sock.Shutdown();
986 th.join();
987 // Make sure the re-entry logic was actually triggered.
988 ASSERT_EQ(hdr.msg_iov, nullptr);
989 ASSERT_EQ(memcmp(&send_buf[0], &recv_buf[0], send_buf.size()), 0);
990 }
991
992 // Regression test for b/193234818. SO_SNDTIMEO is unreliable on most systems.
993 // It doesn't guarantee that the whole send() call blocks for at most X, as the
994 // kernel rearms the timeout if the send buffers frees up and allows a partial
995 // send. This test reproduces the issue 100% on Mac. Unfortunately on Linux the
996 // repro seem to happen only when a suspend happens in the middle.
TEST_F(UnixSocketTest,BlockingSendTimeout)997 TEST_F(UnixSocketTest, BlockingSendTimeout) {
998 TestTaskRunner ttr;
999 UnixSocketRaw send_sock;
1000 UnixSocketRaw recv_sock;
1001 std::tie(send_sock, recv_sock) =
1002 UnixSocketRaw::CreatePairPosix(kTestSocket.family(), SockType::kStream);
1003
1004 auto blocking_send_done = ttr.CreateCheckpoint("blocking_send_done");
1005
1006 std::thread tx_thread([&] {
1007 // Fill the tx buffer in non-blocking mode.
1008 send_sock.SetBlocking(false);
1009 char buf[1024 * 16]{};
1010 while (send_sock.Send(buf, sizeof(buf)) > 0) {
1011 }
1012
1013 // Then do a blocking send. It should return a partial value within the tx
1014 // timeout.
1015 send_sock.SetBlocking(true);
1016 send_sock.SetTxTimeout(10);
1017 ASSERT_LT(send_sock.Send(buf, sizeof(buf)),
1018 static_cast<ssize_t>(sizeof(buf)));
1019 ttr.PostTask(blocking_send_done);
1020 });
1021
1022 // This task needs to be slow enough so that doesn't unblock the send, but
1023 // fast enough so that within a blocking cycle, the send re-attempts and
1024 // re-arms the timeout.
1025 PeriodicTask read_slowly_task(&ttr);
1026 PeriodicTask::Args args;
1027 args.period_ms = 1; // Read 1 byte every ms (1 KiB/s).
1028 args.task = [&] {
1029 char rxbuf[1]{};
1030 recv_sock.Receive(rxbuf, sizeof(rxbuf));
1031 };
1032 read_slowly_task.Start(args);
1033
1034 ttr.RunUntilCheckpoint("blocking_send_done");
1035 read_slowly_task.Reset();
1036 tx_thread.join();
1037 }
1038
1039 #if !PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
TEST_F(UnixSocketTest,SetsCloexec)1040 TEST_F(UnixSocketTest, SetsCloexec) {
1041 // CLOEXEC set when constructing sockets through helper:
1042 {
1043 auto raw = UnixSocketRaw::CreateMayFail(base::SockFamily::kUnix,
1044 SockType::kStream);
1045 int flags = fcntl(raw.fd(), F_GETFD, 0);
1046 EXPECT_TRUE(flags & FD_CLOEXEC);
1047 }
1048 // CLOEXEC set when creating a UnixSocketRaw out of an existing fd:
1049 {
1050 int fd = socket(AF_UNIX, SOCK_STREAM, 0);
1051 int flags = fcntl(fd, F_GETFD, 0);
1052 EXPECT_FALSE(flags & FD_CLOEXEC);
1053
1054 auto raw = UnixSocketRaw(ScopedSocketHandle(fd), base::SockFamily::kUnix,
1055 SockType::kStream);
1056 flags = fcntl(raw.fd(), F_GETFD, 0);
1057 EXPECT_TRUE(flags & FD_CLOEXEC);
1058 }
1059 }
1060 #endif // !OS_FUCHSIA
1061
1062 #endif // !OS_WIN
1063
1064 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
1065 PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) || \
1066 PERFETTO_BUILDFLAG(PERFETTO_OS_MAC)
1067
1068 // Regression test for b/239725760.
TEST_F(UnixSocketTest,Sockaddr_FilesystemLinked)1069 TEST_F(UnixSocketTest, Sockaddr_FilesystemLinked) {
1070 TempDir tmp_dir = TempDir::Create();
1071 std::string sock_path = tmp_dir.path() + "/test.sock";
1072 auto srv = UnixSocket::Listen(sock_path, &event_listener_, &task_runner_,
1073 SockFamily::kUnix, SockType::kStream);
1074 ASSERT_TRUE(srv && srv->is_listening());
1075 ASSERT_TRUE(FileExists(sock_path));
1076
1077 // Create a raw socket and manually connect to that (to avoid getting affected
1078 // by accidental future bugs in the logic that populates struct sockaddr_un).
1079 auto cli = UnixSocketRaw::CreateMayFail(SockFamily::kUnix, SockType::kStream);
1080 struct sockaddr_un addr {};
1081 addr.sun_family = AF_UNIX;
1082 StringCopy(addr.sun_path, sock_path.c_str(), sizeof(addr.sun_path));
1083 ASSERT_EQ(0, connect(cli.fd(), reinterpret_cast<struct sockaddr*>(&addr),
1084 sizeof(addr)));
1085 cli.Shutdown();
1086 remove(sock_path.c_str());
1087 }
1088 #endif // OS_LINUX || OS_ANDROID || OS_MAC
1089
1090 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
1091 PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
1092 // Regression test for b/239725760.
1093 // Abstract sockets are not supported on Mac OS.
TEST_F(UnixSocketTest,Sockaddr_AbstractUnix)1094 TEST_F(UnixSocketTest, Sockaddr_AbstractUnix) {
1095 StackString<128> sock_name("@perfetto_test_%d_%d", getpid(), rand() % 100000);
1096 auto srv =
1097 UnixSocket::Listen(sock_name.ToStdString(), &event_listener_,
1098 &task_runner_, SockFamily::kUnix, SockType::kStream);
1099 ASSERT_TRUE(srv && srv->is_listening());
1100
1101 auto cli = UnixSocketRaw::CreateMayFail(SockFamily::kUnix, SockType::kStream);
1102 struct sockaddr_un addr {};
1103 addr.sun_family = AF_UNIX;
1104 StringCopy(addr.sun_path, sock_name.c_str(), sizeof(addr.sun_path));
1105 addr.sun_path[0] = '\0';
1106 auto addr_len = static_cast<socklen_t>(
1107 __builtin_offsetof(sockaddr_un, sun_path) + sock_name.len());
1108 ASSERT_EQ(0, connect(cli.fd(), reinterpret_cast<struct sockaddr*>(&addr),
1109 addr_len));
1110 }
1111
TEST_F(UnixSocketTest,VSockStream)1112 TEST_F(UnixSocketTest, VSockStream) {
1113 SKIP_IF_VSOCK_LOOPBACK_NOT_SUPPORTED();
1114
1115 // Set up the server. Use the loopback CID (1) and a random port number.
1116 auto srv = UnixSocket::Listen("vsock://1:-1", &event_listener_, &task_runner_,
1117 SockFamily::kVsock, SockType::kStream);
1118 ASSERT_TRUE(srv && srv->is_listening());
1119
1120 std::unique_ptr<UnixSocket> prod;
1121 EXPECT_CALL(event_listener_, OnNewIncomingConnection(srv.get(), _))
1122 .WillOnce(Invoke([&](UnixSocket*, UnixSocket* s) {
1123 // OnDisconnect() might spuriously happen depending on the dtor order.
1124 EXPECT_CALL(event_listener_, OnDisconnect(s)).Times(AtLeast(0));
1125 EXPECT_CALL(event_listener_, OnDataAvailable(s))
1126 .WillRepeatedly(Invoke([](UnixSocket* prod_sock) {
1127 prod_sock->ReceiveString(); // Read connection EOF;
1128 }));
1129 ASSERT_TRUE(s->SendStr("welcome"));
1130 }));
1131
1132 // Set up the client.
1133 prod =
1134 UnixSocket::Connect(srv->GetSockAddr(), &event_listener_, &task_runner_,
1135 SockFamily::kVsock, SockType::kStream);
1136 auto checkpoint = task_runner_.CreateCheckpoint("prod_connected");
1137 EXPECT_CALL(event_listener_, OnDisconnect(prod.get())).Times(AtLeast(0));
1138 EXPECT_CALL(event_listener_, OnConnect(prod.get(), true));
1139 EXPECT_CALL(event_listener_, OnDataAvailable(prod.get()))
1140 .WillRepeatedly(Invoke([checkpoint](UnixSocket* s) {
1141 auto str = s->ReceiveString();
1142 if (str.empty())
1143 return; // Connection EOF.
1144 ASSERT_EQ("welcome", str);
1145 checkpoint();
1146 }));
1147
1148 task_runner_.RunUntilCheckpoint("prod_connected");
1149 ASSERT_TRUE(Mock::VerifyAndClearExpectations(prod.get()));
1150 }
1151 #endif // OS_LINUX || OS_ANDROID
1152
TEST_F(UnixSocketTest,GetSockFamily)1153 TEST_F(UnixSocketTest, GetSockFamily) {
1154 ASSERT_EQ(GetSockFamily(""), SockFamily::kUnspec);
1155 ASSERT_EQ(GetSockFamily("/path/to/sock"), SockFamily::kUnix);
1156 ASSERT_EQ(GetSockFamily("local_dir_sock"), SockFamily::kUnix);
1157 ASSERT_EQ(GetSockFamily("@abstract"), SockFamily::kUnix);
1158 ASSERT_EQ(GetSockFamily("0.0.0.0:80"), SockFamily::kInet);
1159 ASSERT_EQ(GetSockFamily("127.0.0.1:80"), SockFamily::kInet);
1160 ASSERT_EQ(GetSockFamily("[effe::acca]:1234"), SockFamily::kInet6);
1161 ASSERT_EQ(GetSockFamily("[::1]:123456"), SockFamily::kInet6);
1162 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
1163 PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
1164 ASSERT_EQ(GetSockFamily("vsock://-1:10000"), SockFamily::kVsock);
1165 #endif
1166 }
1167
TEST_F(UnixSocketTest,ShmemSupported)1168 TEST_F(UnixSocketTest, ShmemSupported) {
1169 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
1170 ASSERT_EQ(SockShmemSupported(""), true);
1171 #else // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
1172 ASSERT_EQ(SockShmemSupported(""), false);
1173 ASSERT_EQ(SockShmemSupported("/path/to/sock"), true);
1174 ASSERT_EQ(SockShmemSupported("local_dir_sock"), true);
1175 ASSERT_EQ(SockShmemSupported("@abstract"), true);
1176 ASSERT_EQ(SockShmemSupported("0.0.0.0:80"), false);
1177 ASSERT_EQ(SockShmemSupported("127.0.0.1:80"), false);
1178 ASSERT_EQ(SockShmemSupported("[effe::acca]:1234"), false);
1179 ASSERT_EQ(SockShmemSupported("[::1]:123456"), false);
1180 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
1181 PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
1182 ASSERT_EQ(SockShmemSupported("vsock://-1:10000"), false);
1183 #endif
1184 #endif // !PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
1185 }
1186
1187 } // namespace
1188 } // namespace base
1189 } // namespace perfetto
1190