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