• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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