• 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 <stdio.h>
18 #include <algorithm>
19 
20 #include "perfetto/ext/base/getopt.h"
21 #include "perfetto/ext/base/string_utils.h"
22 #include "perfetto/ext/base/unix_task_runner.h"
23 #include "perfetto/ext/base/utils.h"
24 #include "perfetto/ext/base/version.h"
25 #include "perfetto/ext/base/watchdog.h"
26 #include "perfetto/ext/traced/traced.h"
27 #include "perfetto/ext/tracing/ipc/default_socket.h"
28 #include "perfetto/ext/tracing/ipc/service_ipc_host.h"
29 #include "src/traced/service/builtin_producer.h"
30 
31 #if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
32     PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
33 #define PERFETTO_SET_SOCKET_PERMISSIONS
34 #include <fcntl.h>
35 #include <grp.h>
36 #include <sys/stat.h>
37 #include <sys/types.h>
38 #include <unistd.h>
39 #endif
40 
41 namespace perfetto {
42 namespace {
43 #if defined(PERFETTO_SET_SOCKET_PERMISSIONS)
SetSocketPermissions(const std::string & socket_name,const std::string & group_name,const std::string & mode_bits)44 void SetSocketPermissions(const std::string& socket_name,
45                           const std::string& group_name,
46                           const std::string& mode_bits) {
47   PERFETTO_CHECK(!socket_name.empty());
48   PERFETTO_CHECK(!group_name.empty());
49   struct group* socket_group = nullptr;
50   // Query the group ID of |group|.
51   do {
52     socket_group = getgrnam(group_name.c_str());
53   } while (socket_group == nullptr && errno == EINTR);
54   if (socket_group == nullptr) {
55     PERFETTO_FATAL("Failed to get group information of %s ",
56                    group_name.c_str());
57   }
58 
59   if (PERFETTO_EINTR(
60           chown(socket_name.c_str(), geteuid(), socket_group->gr_gid))) {
61     PERFETTO_FATAL("Failed to chown %s ", socket_name.c_str());
62   }
63 
64   // |mode| accepts values like "0660" as "rw-rw----" mode bits.
65   auto mode_value = base::StringToInt32(mode_bits, 8);
66   if (!(mode_bits.size() == 4 && mode_value.has_value())) {
67     PERFETTO_FATAL(
68         "The chmod option must be a 4-digit octal number, e.g. 0660");
69   }
70   if (PERFETTO_EINTR(chmod(socket_name.c_str(),
71                            static_cast<mode_t>(mode_value.value())))) {
72     PERFETTO_FATAL("Failed to chmod %s", socket_name.c_str());
73   }
74 }
75 #endif  // defined(PERFETTO_SET_SOCKET_PERMISSIONS)
76 
PrintUsage(const char * prog_name)77 void PrintUsage(const char* prog_name) {
78   PERFETTO_ELOG(R"(
79 Usage: %s [option] ...
80 Options and arguments
81     --background : Exits immediately and continues running in the background
82     --version : print the version number and exit.
83     --set-socket-permissions <permissions> : sets group ownership and permission
84         mode bits of the producer and consumer sockets.
85         <permissions> format: <prod_group>:<prod_mode>:<cons_group>:<cons_mode>,
86         where <prod_group> is the group name for chgrp the producer socket,
87         <prod_mode> is the mode bits (e.g. 0660) for chmod the produce socket,
88         <cons_group> is the group name for chgrp the consumer socket, and
89         <cons_mode> is the mode bits (e.g. 0660) for chmod the consumer socket.
90 Example: %s --set-socket-permissions traced-producer:0660:traced-consumer:0660
91     starts the service and sets the group ownership of the producer and consumer
92     sockets to "traced-producer" and "traced-consumer", respectively. Both
93     producer and consumer sockets are chmod with 0660  (rw-rw----) mode bits.
94 )",
95                 prog_name, prog_name);
96 }
97 }  // namespace
98 
ServiceMain(int argc,char ** argv)99 int PERFETTO_EXPORT_ENTRYPOINT ServiceMain(int argc, char** argv) {
100   enum LongOption {
101     OPT_VERSION = 1000,
102     OPT_SET_SOCKET_PERMISSIONS = 1001,
103     OPT_BACKGROUND,
104   };
105 
106   bool background = false;
107 
108   static const option long_options[] = {
109       {"background", no_argument, nullptr, OPT_BACKGROUND},
110       {"version", no_argument, nullptr, OPT_VERSION},
111       {"set-socket-permissions", required_argument, nullptr,
112        OPT_SET_SOCKET_PERMISSIONS},
113       {nullptr, 0, nullptr, 0}};
114 
115   std::string producer_socket_group, consumer_socket_group,
116       producer_socket_mode, consumer_socket_mode;
117 
118   for (;;) {
119     int option = getopt_long(argc, argv, "", long_options, nullptr);
120     if (option == -1)
121       break;
122     switch (option) {
123       case OPT_BACKGROUND:
124         background = true;
125         break;
126       case OPT_VERSION:
127         printf("%s\n", base::GetVersionString());
128         return 0;
129       case OPT_SET_SOCKET_PERMISSIONS: {
130         // Check that the socket permission argument is well formed.
131         auto parts = base::SplitString(std::string(optarg), ":");
132         PERFETTO_CHECK(parts.size() == 4);
133         PERFETTO_CHECK(
134             std::all_of(parts.cbegin(), parts.cend(),
135                         [](const std::string& part) { return !part.empty(); }));
136         producer_socket_group = parts[0];
137         producer_socket_mode = parts[1];
138         consumer_socket_group = parts[2];
139         consumer_socket_mode = parts[3];
140         break;
141       }
142       default:
143         PrintUsage(argv[0]);
144         return 1;
145     }
146   }
147 
148   if (background) {
149     base::Daemonize();
150   }
151 
152   base::UnixTaskRunner task_runner;
153   std::unique_ptr<ServiceIPCHost> svc;
154   svc = ServiceIPCHost::CreateInstance(&task_runner);
155 
156   // When built as part of the Android tree, the two socket are created and
157   // bound by init and their fd number is passed in two env variables.
158   // See libcutils' android_get_control_socket().
159   const char* env_prod = getenv("ANDROID_SOCKET_traced_producer");
160   const char* env_cons = getenv("ANDROID_SOCKET_traced_consumer");
161   PERFETTO_CHECK((!env_prod && !env_cons) || (env_prod && env_cons));
162   bool started;
163   if (env_prod) {
164 #if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
165     PERFETTO_CHECK(false);
166 #else
167     base::ScopedFile producer_fd(atoi(env_prod));
168     base::ScopedFile consumer_fd(atoi(env_cons));
169     started = svc->Start(std::move(producer_fd), std::move(consumer_fd));
170 #endif
171   } else {
172     remove(GetProducerSocket());
173     remove(GetConsumerSocket());
174     started = svc->Start(GetProducerSocket(), GetConsumerSocket());
175 
176     if (!producer_socket_group.empty()) {
177 #if defined(PERFETTO_SET_SOCKET_PERMISSIONS)
178       SetSocketPermissions(GetProducerSocket(), producer_socket_group,
179                            producer_socket_mode);
180       SetSocketPermissions(GetConsumerSocket(), consumer_socket_group,
181                            consumer_socket_mode);
182 #else
183       PERFETTO_ELOG(
184           "Setting socket permissions is not supported on this platform");
185       return 1;
186 #endif
187     }
188   }
189 
190   if (!started) {
191     PERFETTO_ELOG("Failed to start the traced service");
192     return 1;
193   }
194 
195   BuiltinProducer builtin_producer(&task_runner, /*lazy_stop_delay_ms=*/30000);
196   builtin_producer.ConnectInProcess(svc->service());
197 
198   // Set the CPU limit and start the watchdog running. The memory limit will
199   // be set inside the service code as it relies on the size of buffers.
200   // The CPU limit is the generic one defined in watchdog.h.
201   base::Watchdog* watchdog = base::Watchdog::GetInstance();
202   watchdog->SetCpuLimit(base::kWatchdogDefaultCpuLimit,
203                         base::kWatchdogDefaultCpuWindow);
204   watchdog->Start();
205 
206   PERFETTO_ILOG("Started traced, listening on %s %s", GetProducerSocket(),
207                 GetConsumerSocket());
208   task_runner.Run();
209   return 0;
210 }
211 
212 }  // namespace perfetto
213