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 <limits.h> 18 #include <signal.h> 19 #include <stdio.h> 20 #include <stdlib.h> 21 #include <sys/types.h> 22 #include <sys/stat.h> 23 #include <sys/wait.h> 24 #include <fcntl.h> 25 #include <unistd.h> 26 27 #include <algorithm> 28 #include <functional> 29 #include <iostream> 30 #include <fstream> 31 #include <iomanip> 32 #include <memory> 33 #include <sstream> 34 #include <string> 35 #include <thread> 36 #include <vector> 37 38 #include <gflags/gflags.h> 39 #include <glog/logging.h> 40 #include <host/libs/vm_manager/crosvm_manager.h> 41 42 #include "common/libs/fs/shared_fd.h" 43 #include "common/libs/fs/shared_select.h" 44 #include "common/libs/strings/str_split.h" 45 #include "common/libs/utils/environment.h" 46 #include "common/libs/utils/files.h" 47 #include "common/libs/utils/subprocess.h" 48 #include "common/libs/utils/size_utils.h" 49 #include "common/vsoc/lib/vsoc_memory.h" 50 #include "common/vsoc/shm/screen_layout.h" 51 #include "host/commands/launch/boot_image_unpacker.h" 52 #include "host/commands/launch/data_image.h" 53 #include "host/commands/launch/flags.h" 54 #include "host/commands/launch/launch.h" 55 #include "host/commands/launch/launcher_defs.h" 56 #include "host/commands/launch/process_monitor.h" 57 #include "host/commands/launch/vsoc_shared_memory.h" 58 #include "host/libs/config/cuttlefish_config.h" 59 #include "host/commands/kernel_log_monitor/kernel_log_server.h" 60 #include "host/libs/vm_manager/vm_manager.h" 61 #include "host/libs/vm_manager/qemu_manager.h" 62 63 using vsoc::GetPerInstanceDefault; 64 using cvd::LauncherExitCodes; 65 66 namespace { 67 68 cvd::OnSocketReadyCb GetOnSubprocessExitCallback( 69 const vsoc::CuttlefishConfig& config) { 70 if (config.restart_subprocesses()) { 71 return cvd::ProcessMonitor::RestartOnExitCb; 72 } else { 73 return cvd::ProcessMonitor::DoNotMonitorCb; 74 } 75 } 76 77 // Maintains the state of the boot process, once a final state is reached 78 // (success or failure) it sends the appropriate exit code to the foreground 79 // launcher process 80 class CvdBootStateMachine { 81 public: 82 CvdBootStateMachine(cvd::SharedFD fg_launcher_pipe) 83 : fg_launcher_pipe_(fg_launcher_pipe), state_(kBootStarted) {} 84 85 // Returns true if the machine is left in a final state 86 bool OnBootEvtReceived(cvd::SharedFD boot_events_pipe) { 87 monitor::BootEvent evt; 88 auto bytes_read = boot_events_pipe->Read(&evt, sizeof(evt)); 89 if (bytes_read != sizeof(evt)) { 90 LOG(ERROR) << "Fail to read a complete event, read " << bytes_read 91 << " bytes only instead of the expected " << sizeof(evt); 92 state_ |= kGuestBootFailed; 93 } else if (evt == monitor::BootEvent::BootCompleted) { 94 LOG(INFO) << "Virtual device booted successfully"; 95 state_ |= kGuestBootCompleted; 96 } else if (evt == monitor::BootEvent::BootFailed) { 97 LOG(ERROR) << "Virtual device failed to boot"; 98 state_ |= kGuestBootFailed; 99 } // Ignore the other signals 100 101 return MaybeWriteToForegroundLauncher(); 102 } 103 104 bool OnE2eTestCompleted(int exit_code) { 105 if (exit_code != 0) { 106 LOG(ERROR) << "VSoC e2e test failed"; 107 state_ |= kE2eTestFailed; 108 } else { 109 LOG(INFO) << "VSoC e2e test passed"; 110 state_ |= kE2eTestPassed; 111 } 112 return MaybeWriteToForegroundLauncher(); 113 } 114 115 bool BootCompleted() const { 116 bool boot_completed = state_ & kGuestBootCompleted; 117 bool test_passed_or_disabled = 118 (state_ & kE2eTestPassed) || (state_ & kE2eTestDisabled); 119 bool something_failed = 120 state_ & ~(kGuestBootCompleted | kE2eTestPassed | kE2eTestDisabled); 121 return boot_completed && test_passed_or_disabled && !something_failed; 122 } 123 124 bool DisableE2eTests() { 125 state_ |= kE2eTestDisabled; 126 return MaybeWriteToForegroundLauncher(); 127 } 128 129 bool BootFailed() const { 130 return state_ & (kGuestBootFailed | kE2eTestFailed); 131 } 132 133 private: 134 void SendExitCode(cvd::LauncherExitCodes exit_code) { 135 fg_launcher_pipe_->Write(&exit_code, sizeof(exit_code)); 136 // The foreground process will exit after receiving the exit code, if we try 137 // to write again we'll get a SIGPIPE 138 fg_launcher_pipe_->Close(); 139 } 140 bool MaybeWriteToForegroundLauncher() { 141 if (fg_launcher_pipe_->IsOpen()) { 142 if (BootCompleted()) { 143 SendExitCode(cvd::LauncherExitCodes::kSuccess); 144 } else if (state_ & kGuestBootFailed) { 145 SendExitCode(cvd::LauncherExitCodes::kVirtualDeviceBootFailed); 146 } else if (state_ & kE2eTestFailed) { 147 SendExitCode(cvd::LauncherExitCodes::kE2eTestFailed); 148 } else { 149 // No final state was reached 150 return false; 151 } 152 } 153 // Either we sent the code before or just sent it, in any case the state is 154 // final 155 return true; 156 } 157 158 cvd::SharedFD fg_launcher_pipe_; 159 int state_; 160 static const int kBootStarted = 0; 161 static const int kGuestBootCompleted = 1 << 0; 162 static const int kGuestBootFailed = 1 << 1; 163 static const int kE2eTestPassed = 1 << 2; 164 static const int kE2eTestFailed = 1 << 3; 165 static const int kE2eTestDisabled = 1 << 4; 166 }; 167 168 // Abuse the process monitor to make it call us back when boot events are ready 169 void SetUpHandlingOfBootEvents( 170 cvd::ProcessMonitor* process_monitor, cvd::SharedFD boot_events_pipe, 171 std::shared_ptr<CvdBootStateMachine> state_machine) { 172 process_monitor->MonitorExistingSubprocess( 173 // A dummy command, so logs are desciptive 174 cvd::Command("boot_events_listener"), 175 // A dummy subprocess, with the boot events pipe as control socket 176 cvd::Subprocess(-1, boot_events_pipe), 177 [boot_events_pipe, state_machine](cvd::MonitorEntry*) { 178 auto sent_code = state_machine->OnBootEvtReceived(boot_events_pipe); 179 return !sent_code; 180 }); 181 } 182 183 void LaunchE2eTestIfEnabled(cvd::ProcessMonitor* process_monitor, 184 std::shared_ptr<CvdBootStateMachine> state_machine, 185 const vsoc::CuttlefishConfig& config) { 186 if (config.run_e2e_test()) { 187 process_monitor->StartSubprocess( 188 cvd::Command(config.e2e_test_binary()), 189 [state_machine](cvd::MonitorEntry* entry) { 190 auto test_result = entry->proc->Wait(); 191 state_machine->OnE2eTestCompleted(test_result); 192 return false; 193 }); 194 } else { 195 state_machine->DisableE2eTests(); 196 } 197 } 198 199 bool WriteCuttlefishEnvironment(const vsoc::CuttlefishConfig& config) { 200 auto env = cvd::SharedFD::Open(config.cuttlefish_env_path().c_str(), 201 O_CREAT | O_RDWR, 0755); 202 if (!env->IsOpen()) { 203 LOG(ERROR) << "Unable to create cuttlefish.env file"; 204 return false; 205 } 206 std::string config_env = "export CUTTLEFISH_PER_INSTANCE_PATH=\"" + 207 config.PerInstancePath(".") + "\"\n"; 208 config_env += "export ANDROID_SERIAL="; 209 if (AdbUsbEnabled(config)) { 210 config_env += config.serial_number(); 211 } else { 212 config_env += "127.0.0.1:" + std::to_string(GetHostPort()); 213 } 214 config_env += "\n"; 215 env->Write(config_env.c_str(), config_env.size()); 216 return true; 217 } 218 219 // Forks and returns the write end of a pipe to the child process. The parent 220 // process waits for boot events to come through the pipe and exits accordingly. 221 cvd::SharedFD DaemonizeLauncher(const vsoc::CuttlefishConfig& config) { 222 cvd::SharedFD read_end, write_end; 223 if (!cvd::SharedFD::Pipe(&read_end, &write_end)) { 224 LOG(ERROR) << "Unable to create pipe"; 225 return cvd::SharedFD(); // a closed FD 226 } 227 auto pid = fork(); 228 if (pid) { 229 // Explicitly close here, otherwise we may end up reading forever if the 230 // child process dies. 231 write_end->Close(); 232 LauncherExitCodes exit_code; 233 auto bytes_read = read_end->Read(&exit_code, sizeof(exit_code)); 234 if (bytes_read != sizeof(exit_code)) { 235 LOG(ERROR) << "Failed to read a complete exit code, read " << bytes_read 236 << " bytes only instead of the expected " << sizeof(exit_code); 237 exit_code = LauncherExitCodes::kPipeIOError; 238 } else if (exit_code == LauncherExitCodes::kSuccess) { 239 LOG(INFO) << "Virtual device booted successfully"; 240 } else if (exit_code == LauncherExitCodes::kVirtualDeviceBootFailed) { 241 LOG(ERROR) << "Virtual device failed to boot"; 242 } else if (exit_code == LauncherExitCodes::kE2eTestFailed) { 243 LOG(ERROR) << "Host VSoC region end to end test failed"; 244 } else { 245 LOG(ERROR) << "Unexpected exit code: " << exit_code; 246 } 247 std::exit(exit_code); 248 } else { 249 // The child returns the write end of the pipe 250 if (daemon(/*nochdir*/ 1, /*noclose*/ 1) != 0) { 251 LOG(ERROR) << "Failed to daemonize child process: " << strerror(errno); 252 std::exit(LauncherExitCodes::kDaemonizationError); 253 } 254 // Redirect standard I/O 255 auto log_path = config.launcher_log_path(); 256 auto log = 257 cvd::SharedFD::Open(log_path.c_str(), O_CREAT | O_WRONLY | O_TRUNC, 258 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); 259 if (!log->IsOpen()) { 260 LOG(ERROR) << "Failed to create launcher log file: " << log->StrError(); 261 std::exit(LauncherExitCodes::kDaemonizationError); 262 } 263 auto dev_null = cvd::SharedFD::Open("/dev/null", O_RDONLY); 264 if (!dev_null->IsOpen()) { 265 LOG(ERROR) << "Failed to open /dev/null: " << dev_null->StrError(); 266 std::exit(LauncherExitCodes::kDaemonizationError); 267 } 268 if (dev_null->UNMANAGED_Dup2(0) < 0) { 269 LOG(ERROR) << "Failed dup2 stdin: " << dev_null->StrError(); 270 std::exit(LauncherExitCodes::kDaemonizationError); 271 } 272 if (log->UNMANAGED_Dup2(1) < 0) { 273 LOG(ERROR) << "Failed dup2 stdout: " << log->StrError(); 274 std::exit(LauncherExitCodes::kDaemonizationError); 275 } 276 if (log->UNMANAGED_Dup2(2) < 0) { 277 LOG(ERROR) << "Failed dup2 seterr: " << log->StrError(); 278 std::exit(LauncherExitCodes::kDaemonizationError); 279 } 280 281 read_end->Close(); 282 return write_end; 283 } 284 } 285 286 // Stops the device. If this function is successful it returns on a child of the 287 // launcher (after it killed the laucher) and it should exit immediately 288 bool StopCvd(vm_manager::VmManager* vm_manager) { 289 vm_manager->Stop(); 290 auto pgid = getpgid(0); 291 auto child_pid = fork(); 292 if (child_pid > 0) { 293 // The parent just waits for the child to kill it. 294 int wstatus; 295 waitpid(child_pid, &wstatus, 0); 296 LOG(ERROR) << "The forked child exited before delivering signal with " 297 "status: " 298 << wstatus; 299 // If waitpid returns it means the child exited before the signal was 300 // delivered, notify the client of the error and continue serving 301 return false; 302 } else if (child_pid == 0) { 303 // The child makes sure it is in a different process group before 304 // killing everyone on its parent's 305 // This call should never fail (see SETPGID(2)) 306 if (setpgid(0, 0) != 0) { 307 LOG(ERROR) << "setpgid failed (" << strerror(errno) 308 << ") the launcher's child is about to kill itself"; 309 } 310 killpg(pgid, SIGKILL); 311 return true; 312 } else { 313 // The fork failed, the system is in pretty bad shape 314 LOG(FATAL) << "Unable to fork before on Stop: " << strerror(errno); 315 return false; 316 } 317 } 318 319 void ServerLoop(cvd::SharedFD server, 320 vm_manager::VmManager* vm_manager) { 321 while (true) { 322 // TODO: use select to handle simultaneous connections. 323 auto client = cvd::SharedFD::Accept(*server); 324 cvd::LauncherAction action; 325 while (client->IsOpen() && client->Read(&action, sizeof(action)) > 0) { 326 switch (action) { 327 case cvd::LauncherAction::kStop: 328 if (StopCvd(vm_manager)) { 329 auto response = cvd::LauncherResponse::kSuccess; 330 client->Write(&response, sizeof(response)); 331 std::exit(0); 332 } else { 333 auto response = cvd::LauncherResponse::kError; 334 client->Write(&response, sizeof(response)); 335 } 336 break; 337 default: 338 LOG(ERROR) << "Unrecognized launcher action: " 339 << static_cast<char>(action); 340 auto response = cvd::LauncherResponse::kError; 341 client->Write(&response, sizeof(response)); 342 } 343 } 344 } 345 } 346 } // namespace 347 348 int main(int argc, char** argv) { 349 ::android::base::InitLogging(argv, android::base::StderrLogger); 350 351 auto config = InitFilesystemAndCreateConfig(&argc, &argv); 352 353 auto vm_manager = vm_manager::VmManager::Get(config->vm_manager(), config); 354 355 // Check host configuration 356 std::vector<std::string> config_commands; 357 if (!vm_manager->ValidateHostConfiguration(&config_commands)) { 358 LOG(ERROR) << "Validation of user configuration failed"; 359 std::cout << "Execute the following to correctly configure:" << std::endl; 360 for (auto& command : config_commands) { 361 std::cout << " " << command << std::endl; 362 } 363 std::cout << "You may need to logout for the changes to take effect" 364 << std::endl; 365 return LauncherExitCodes::kInvalidHostConfiguration; 366 } 367 368 if (!WriteCuttlefishEnvironment(*config)) { 369 LOG(ERROR) << "Unable to write cuttlefish environment file"; 370 } 371 372 LOG(INFO) << "The following files contain useful debugging information:"; 373 if (config->run_as_daemon()) { 374 LOG(INFO) << " Launcher log: " << config->launcher_log_path(); 375 } 376 LOG(INFO) << " Android's logcat output: " << config->logcat_path(); 377 LOG(INFO) << " Kernel log: " << config->PerInstancePath("kernel.log"); 378 LOG(INFO) << " Instance configuration: " << GetConfigFilePath(*config); 379 LOG(INFO) << " Instance environment: " << config->cuttlefish_env_path(); 380 LOG(INFO) << "To access the console run: socat file:$(tty),raw,echo=0 " 381 << config->console_path(); 382 383 auto launcher_monitor_path = config->launcher_monitor_socket_path(); 384 auto launcher_monitor_socket = cvd::SharedFD::SocketLocalServer( 385 launcher_monitor_path.c_str(), false, SOCK_STREAM, 0666); 386 if (!launcher_monitor_socket->IsOpen()) { 387 LOG(ERROR) << "Error when opening launcher server: " 388 << launcher_monitor_socket->StrError(); 389 return cvd::LauncherExitCodes::kMonitorCreationFailed; 390 } 391 cvd::SharedFD foreground_launcher_pipe; 392 if (config->run_as_daemon()) { 393 foreground_launcher_pipe = DaemonizeLauncher(*config); 394 if (!foreground_launcher_pipe->IsOpen()) { 395 return LauncherExitCodes::kDaemonizationError; 396 } 397 } else { 398 // Make sure the launcher runs in its own process group even when running in 399 // foreground 400 if (getsid(0) != getpid()) { 401 int retval = setpgid(0, 0); 402 if (retval) { 403 LOG(ERROR) << "Failed to create new process group: " << strerror(errno); 404 std::exit(LauncherExitCodes::kProcessGroupError); 405 } 406 } 407 } 408 409 auto boot_state_machine = 410 std::make_shared<CvdBootStateMachine>(foreground_launcher_pipe); 411 412 // Monitor and restart host processes supporting the CVD 413 cvd::ProcessMonitor process_monitor; 414 415 cvd::SharedFD boot_events_pipe; 416 cvd::SharedFD adbd_events_pipe; 417 // Only subscribe to boot events if running as daemon 418 process_monitor.StartSubprocess( 419 GetKernelLogMonitorCommand(*config, &boot_events_pipe, &adbd_events_pipe), 420 GetOnSubprocessExitCallback(*config)); 421 422 SetUpHandlingOfBootEvents(&process_monitor, boot_events_pipe, 423 boot_state_machine); 424 425 LaunchLogcatReceiverIfEnabled(*config, &process_monitor); 426 427 LaunchUsbServerIfEnabled(*config, &process_monitor); 428 429 LaunchIvServerIfEnabled(&process_monitor, *config); 430 // Launch the e2e tests after the ivserver is ready 431 LaunchE2eTestIfEnabled(&process_monitor, boot_state_machine, *config); 432 433 // Start the guest VM 434 process_monitor.StartSubprocess(vm_manager->StartCommand(), 435 GetOnSubprocessExitCallback(*config)); 436 437 // Start other host processes 438 LaunchSocketForwardProxyIfEnabled(&process_monitor, *config); 439 LaunchSocketVsockProxyIfEnabled(&process_monitor, *config); 440 LaunchVNCServerIfEnabled(*config, &process_monitor, 441 GetOnSubprocessExitCallback(*config)); 442 LaunchStreamAudioIfEnabled(*config, &process_monitor, 443 GetOnSubprocessExitCallback(*config)); 444 LaunchAdbConnectorIfEnabled(&process_monitor, *config, adbd_events_pipe); 445 446 ServerLoop(launcher_monitor_socket, vm_manager); // Should not return 447 LOG(ERROR) << "The server loop returned, it should never happen!!"; 448 return cvd::LauncherExitCodes::kServerError; 449 } 450