• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (C) 2019 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 #include "host/commands/run_cvd/launch.h"
17 
18 #include <android-base/logging.h>
19 #include <utility>
20 
21 #include "common/libs/fs/shared_fd.h"
22 #include "common/libs/utils/files.h"
23 #include "common/libs/utils/subprocess.h"
24 #include "host/commands/run_cvd/process_monitor.h"
25 #include "host/commands/run_cvd/runner_defs.h"
26 #include "host/libs/config/cuttlefish_config.h"
27 #include "host/libs/config/known_paths.h"
28 
29 namespace cuttlefish {
30 
31 namespace {
32 
33 template <typename T>
single_element_emplace(T && element)34 std::vector<T> single_element_emplace(T&& element) {
35   std::vector<T> vec;
36   vec.emplace_back(std::move(element));
37   return vec;
38 }
39 
40 }  // namespace
41 
LaunchKernelLogMonitor(const CuttlefishConfig & config,unsigned int number_of_event_pipes)42 KernelLogMonitorData LaunchKernelLogMonitor(
43     const CuttlefishConfig& config, unsigned int number_of_event_pipes) {
44   auto instance = config.ForDefaultInstance();
45   auto log_name = instance.kernel_log_pipe_name();
46   if (mkfifo(log_name.c_str(), 0600) != 0) {
47     LOG(ERROR) << "Unable to create named pipe at " << log_name << ": "
48                << strerror(errno);
49     return {};
50   }
51 
52   SharedFD pipe;
53   // Open the pipe here (from the launcher) to ensure the pipe is not deleted
54   // due to the usage counters in the kernel reaching zero. If this is not done
55   // and the kernel_log_monitor crashes for some reason the VMM may get SIGPIPE.
56   pipe = SharedFD::Open(log_name.c_str(), O_RDWR);
57   Command command(KernelLogMonitorBinary());
58   command.AddParameter("-log_pipe_fd=", pipe);
59 
60   KernelLogMonitorData ret;
61 
62   if (number_of_event_pipes > 0) {
63     command.AddParameter("-subscriber_fds=");
64     for (unsigned int i = 0; i < number_of_event_pipes; ++i) {
65       SharedFD event_pipe_write_end, event_pipe_read_end;
66       if (!SharedFD::Pipe(&event_pipe_read_end, &event_pipe_write_end)) {
67         LOG(ERROR) << "Unable to create kernel log events pipe: " << strerror(errno);
68         std::exit(RunnerExitCodes::kPipeIOError);
69       }
70       if (i > 0) {
71         command.AppendToLastParameter(",");
72       }
73       command.AppendToLastParameter(event_pipe_write_end);
74       ret.pipes.push_back(event_pipe_read_end);
75     }
76   }
77 
78   ret.commands.emplace_back(std::move(command));
79 
80   return ret;
81 }
82 
LaunchRootCanal(const CuttlefishConfig & config)83 std::vector<Command> LaunchRootCanal(const CuttlefishConfig& config) {
84   if (!config.enable_host_bluetooth()) {
85     return {};
86   }
87 
88   auto instance = config.ForDefaultInstance();
89   Command command(RootCanalBinary());
90 
91   // Test port
92   command.AddParameter(instance.rootcanal_test_port());
93   // HCI server port
94   command.AddParameter(instance.rootcanal_hci_port());
95   // Link server port
96   command.AddParameter(instance.rootcanal_link_port());
97   // Bluetooth controller properties file
98   command.AddParameter("--controller_properties_file=",
99                        instance.rootcanal_config_file());
100   // Default commands file
101   command.AddParameter("--default_commands_file=",
102                        instance.rootcanal_default_commands_file());
103 
104   return single_element_emplace(std::move(command));
105 }
106 
LaunchLogcatReceiver(const CuttlefishConfig & config)107 std::vector<Command> LaunchLogcatReceiver(const CuttlefishConfig& config) {
108   auto instance = config.ForDefaultInstance();
109   auto log_name = instance.logcat_pipe_name();
110   if (mkfifo(log_name.c_str(), 0600) != 0) {
111     LOG(ERROR) << "Unable to create named pipe at " << log_name << ": "
112                << strerror(errno);
113     return {};
114   }
115 
116   SharedFD pipe;
117   // Open the pipe here (from the launcher) to ensure the pipe is not deleted
118   // due to the usage counters in the kernel reaching zero. If this is not done
119   // and the logcat_receiver crashes for some reason the VMM may get SIGPIPE.
120   pipe = SharedFD::Open(log_name.c_str(), O_RDWR);
121   Command command(LogcatReceiverBinary());
122   command.AddParameter("-log_pipe_fd=", pipe);
123 
124   return single_element_emplace(std::move(command));
125 }
126 
LaunchConfigServer(const CuttlefishConfig & config)127 std::vector<Command> LaunchConfigServer(const CuttlefishConfig& config) {
128   auto instance = config.ForDefaultInstance();
129   auto port = instance.config_server_port();
130   auto socket = SharedFD::VsockServer(port, SOCK_STREAM);
131   if (!socket->IsOpen()) {
132     LOG(ERROR) << "Unable to create configuration server socket: "
133                << socket->StrError();
134     std::exit(RunnerExitCodes::kConfigServerError);
135   }
136   Command cmd(ConfigServerBinary());
137   cmd.AddParameter("-server_fd=", socket);
138   return single_element_emplace(std::move(cmd));
139 }
140 
LaunchTombstoneReceiver(const CuttlefishConfig & config)141 std::vector<Command> LaunchTombstoneReceiver(const CuttlefishConfig& config) {
142   auto instance = config.ForDefaultInstance();
143 
144   std::string tombstoneDir = instance.PerInstancePath("tombstones");
145   if (!DirectoryExists(tombstoneDir.c_str())) {
146     LOG(DEBUG) << "Setting up " << tombstoneDir;
147     if (mkdir(tombstoneDir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) <
148         0) {
149       LOG(ERROR) << "Failed to create tombstone directory: " << tombstoneDir
150                  << ". Error: " << errno;
151       exit(RunnerExitCodes::kTombstoneDirCreationError);
152       return {};
153     }
154   }
155 
156   auto port = instance.tombstone_receiver_port();
157   auto socket = SharedFD::VsockServer(port, SOCK_STREAM);
158   if (!socket->IsOpen()) {
159     LOG(ERROR) << "Unable to create tombstone server socket: "
160                << socket->StrError();
161     std::exit(RunnerExitCodes::kTombstoneServerError);
162     return {};
163   }
164   Command cmd(TombstoneReceiverBinary());
165   cmd.AddParameter("-server_fd=", socket);
166   cmd.AddParameter("-tombstone_dir=", tombstoneDir);
167 
168   return single_element_emplace(std::move(cmd));
169 }
170 
LaunchMetrics()171 std::vector<Command> LaunchMetrics() {
172   return single_element_emplace(Command(MetricsBinary()));
173 }
174 
LaunchGnssGrpcProxyServerIfEnabled(const CuttlefishConfig & config)175 std::vector<Command> LaunchGnssGrpcProxyServerIfEnabled(
176     const CuttlefishConfig& config) {
177   if (!config.enable_gnss_grpc_proxy() || !FileExists(GnssGrpcProxyBinary())) {
178     return {};
179   }
180 
181   Command gnss_grpc_proxy_cmd(GnssGrpcProxyBinary());
182   auto instance = config.ForDefaultInstance();
183 
184   auto gnss_in_pipe_name = instance.gnss_in_pipe_name();
185   if (mkfifo(gnss_in_pipe_name.c_str(), 0600) != 0) {
186     auto error = errno;
187     LOG(ERROR) << "Failed to create gnss input fifo for crosvm: "
188                << strerror(error);
189     return {};
190   }
191 
192   auto gnss_out_pipe_name = instance.gnss_out_pipe_name();
193   if (mkfifo(gnss_out_pipe_name.c_str(), 0660) != 0) {
194     auto error = errno;
195     LOG(ERROR) << "Failed to create gnss output fifo for crosvm: "
196                << strerror(error);
197     return {};
198   }
199 
200   // These fds will only be read from or written to, but open them with
201   // read and write access to keep them open in case the subprocesses exit
202   SharedFD gnss_grpc_proxy_in_wr =
203       SharedFD::Open(gnss_in_pipe_name.c_str(), O_RDWR);
204   if (!gnss_grpc_proxy_in_wr->IsOpen()) {
205     LOG(ERROR) << "Failed to open gnss_grpc_proxy input fifo for writes: "
206                << gnss_grpc_proxy_in_wr->StrError();
207     return {};
208   }
209 
210   SharedFD gnss_grpc_proxy_out_rd =
211       SharedFD::Open(gnss_out_pipe_name.c_str(), O_RDWR);
212   if (!gnss_grpc_proxy_out_rd->IsOpen()) {
213     LOG(ERROR) << "Failed to open gnss_grpc_proxy output fifo for reads: "
214                << gnss_grpc_proxy_out_rd->StrError();
215     return {};
216   }
217 
218   const unsigned gnss_grpc_proxy_server_port =
219       instance.gnss_grpc_proxy_server_port();
220   gnss_grpc_proxy_cmd.AddParameter("--gnss_in_fd=", gnss_grpc_proxy_in_wr);
221   gnss_grpc_proxy_cmd.AddParameter("--gnss_out_fd=", gnss_grpc_proxy_out_rd);
222   gnss_grpc_proxy_cmd.AddParameter("--gnss_grpc_port=",
223                                    gnss_grpc_proxy_server_port);
224   if (!instance.gnss_file_path().empty()) {
225     // If path is provided, proxy will start as local mode.
226     gnss_grpc_proxy_cmd.AddParameter("--gnss_file_path=",
227                                      instance.gnss_file_path());
228   }
229   return single_element_emplace(std::move(gnss_grpc_proxy_cmd));
230 }
231 
LaunchBluetoothConnector(const CuttlefishConfig & config)232 std::vector<Command> LaunchBluetoothConnector(const CuttlefishConfig& config) {
233   auto instance = config.ForDefaultInstance();
234   std::vector<std::string> fifo_paths = {
235       instance.PerInstanceInternalPath("bt_fifo_vm.in"),
236       instance.PerInstanceInternalPath("bt_fifo_vm.out"),
237   };
238   std::vector<SharedFD> fifos;
239   for (const auto& path : fifo_paths) {
240     unlink(path.c_str());
241     if (mkfifo(path.c_str(), 0660) < 0) {
242       PLOG(ERROR) << "Could not create " << path;
243       return {};
244     }
245     auto fd = SharedFD::Open(path, O_RDWR);
246     if (!fd->IsOpen()) {
247       LOG(ERROR) << "Could not open " << path << ": " << fd->StrError();
248       return {};
249     }
250     fifos.push_back(fd);
251   }
252 
253   Command command(DefaultHostArtifactsPath("bin/bt_connector"));
254   command.AddParameter("-bt_out=", fifos[0]);
255   command.AddParameter("-bt_in=", fifos[1]);
256   command.AddParameter("-hci_port=", instance.rootcanal_hci_port());
257   command.AddParameter("-link_port=", instance.rootcanal_link_port());
258   command.AddParameter("-test_port=", instance.rootcanal_test_port());
259   return single_element_emplace(std::move(command));
260 }
261 
LaunchSecureEnvironment(const CuttlefishConfig & config)262 std::vector<Command> LaunchSecureEnvironment(const CuttlefishConfig& config) {
263   auto instance = config.ForDefaultInstance();
264   std::vector<std::string> fifo_paths = {
265     instance.PerInstanceInternalPath("keymaster_fifo_vm.in"),
266     instance.PerInstanceInternalPath("keymaster_fifo_vm.out"),
267     instance.PerInstanceInternalPath("gatekeeper_fifo_vm.in"),
268     instance.PerInstanceInternalPath("gatekeeper_fifo_vm.out"),
269   };
270   std::vector<SharedFD> fifos;
271   for (const auto& path : fifo_paths) {
272     unlink(path.c_str());
273     if (mkfifo(path.c_str(), 0600) < 0) {
274       PLOG(ERROR) << "Could not create " << path;
275       return {};
276     }
277     auto fd = SharedFD::Open(path, O_RDWR);
278     if (!fd->IsOpen()) {
279       LOG(ERROR) << "Could not open " << path << ": " << fd->StrError();
280       return {};
281     }
282     fifos.push_back(fd);
283   }
284 
285   Command command(HostBinaryPath("secure_env"));
286   command.AddParameter("-keymaster_fd_out=", fifos[0]);
287   command.AddParameter("-keymaster_fd_in=", fifos[1]);
288   command.AddParameter("-gatekeeper_fd_out=", fifos[2]);
289   command.AddParameter("-gatekeeper_fd_in=", fifos[3]);
290 
291   const auto& secure_hals = config.secure_hals();
292   bool secure_keymint = secure_hals.count(SecureHal::Keymint) > 0;
293   command.AddParameter("-keymint_impl=", secure_keymint ? "tpm" : "software");
294   bool secure_gatekeeper = secure_hals.count(SecureHal::Gatekeeper) > 0;
295   auto gatekeeper_impl = secure_gatekeeper ? "tpm" : "software";
296   command.AddParameter("-gatekeeper_impl=", gatekeeper_impl);
297 
298   return single_element_emplace(std::move(command));
299 }
300 
LaunchVehicleHalServerIfEnabled(const CuttlefishConfig & config)301 std::vector<Command> LaunchVehicleHalServerIfEnabled(
302     const CuttlefishConfig& config) {
303   if (!config.enable_vehicle_hal_grpc_server() ||
304     !FileExists(config.vehicle_hal_grpc_server_binary())) {
305     return {};
306   }
307 
308   Command grpc_server(config.vehicle_hal_grpc_server_binary());
309   auto instance = config.ForDefaultInstance();
310 
311   const unsigned vhal_server_cid = 2;
312   const unsigned vhal_server_port = instance.vehicle_hal_server_port();
313   const std::string vhal_server_power_state_file =
314       AbsolutePath(instance.PerInstancePath("power_state"));
315   const std::string vhal_server_power_state_socket =
316       AbsolutePath(instance.PerInstancePath("power_state_socket"));
317 
318   grpc_server.AddParameter("--server_cid=", vhal_server_cid);
319   grpc_server.AddParameter("--server_port=", vhal_server_port);
320   grpc_server.AddParameter("--power_state_file=", vhal_server_power_state_file);
321   grpc_server.AddParameter("--power_state_socket=", vhal_server_power_state_socket);
322   return single_element_emplace(std::move(grpc_server));
323 }
324 
LaunchConsoleForwarderIfEnabled(const CuttlefishConfig & config)325 std::vector<Command> LaunchConsoleForwarderIfEnabled(
326     const CuttlefishConfig& config) {
327   if (!config.console()) {
328     return {};
329   }
330 
331   Command console_forwarder_cmd(ConsoleForwarderBinary());
332   auto instance = config.ForDefaultInstance();
333 
334   auto console_in_pipe_name = instance.console_in_pipe_name();
335   if (mkfifo(console_in_pipe_name.c_str(), 0600) != 0) {
336     auto error = errno;
337     LOG(ERROR) << "Failed to create console input fifo for crosvm: "
338                << strerror(error);
339     return {};
340   }
341 
342   auto console_out_pipe_name = instance.console_out_pipe_name();
343   if (mkfifo(console_out_pipe_name.c_str(), 0660) != 0) {
344     auto error = errno;
345     LOG(ERROR) << "Failed to create console output fifo for crosvm: "
346                << strerror(error);
347     return {};
348   }
349 
350   // These fds will only be read from or written to, but open them with
351   // read and write access to keep them open in case the subprocesses exit
352   SharedFD console_forwarder_in_wr =
353       SharedFD::Open(console_in_pipe_name.c_str(), O_RDWR);
354   if (!console_forwarder_in_wr->IsOpen()) {
355     LOG(ERROR) << "Failed to open console_forwarder input fifo for writes: "
356                << console_forwarder_in_wr->StrError();
357     return {};
358   }
359 
360   SharedFD console_forwarder_out_rd =
361       SharedFD::Open(console_out_pipe_name.c_str(), O_RDWR);
362   if (!console_forwarder_out_rd->IsOpen()) {
363     LOG(ERROR) << "Failed to open console_forwarder output fifo for reads: "
364                << console_forwarder_out_rd->StrError();
365     return {};
366   }
367 
368   console_forwarder_cmd.AddParameter("--console_in_fd=", console_forwarder_in_wr);
369   console_forwarder_cmd.AddParameter("--console_out_fd=", console_forwarder_out_rd);
370   return single_element_emplace(std::move(console_forwarder_cmd));
371 }
372 
373 } // namespace cuttlefish
374