1 /*
2 * Copyright (C) 2024 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 "host/libs/vm_manager/vhost_user.h"
18
19 #include <sys/socket.h>
20 #include <sys/stat.h>
21 #include <sys/types.h>
22 #include <sys/un.h>
23 #include <sys/wait.h>
24 #include <unistd.h>
25
26 #include <cstdlib>
27 #include <string>
28 #include <utility>
29
30 #include <android-base/logging.h>
31 #include <android-base/strings.h>
32 #include <vulkan/vulkan.h>
33
34 #include "common/libs/utils/files.h"
35 #include "common/libs/utils/result.h"
36 #include "common/libs/utils/subprocess.h"
37 #include "host/libs/config/cuttlefish_config.h"
38 #include "host/libs/vm_manager/crosvm_builder.h"
39
40 namespace cuttlefish {
41 namespace vm_manager {
42
43 // TODO(schuffelen): Deduplicate with BuildVhostUserGpu
VhostUserBlockDevice(const CuttlefishConfig & config,int num,std::string_view disk_path)44 Result<VhostUserDeviceCommands> VhostUserBlockDevice(
45 const CuttlefishConfig& config, int num, std::string_view disk_path) {
46 const auto& instance = config.ForDefaultInstance();
47
48 CF_EXPECT(instance.vhost_user_block(), "Feature is not enabled");
49
50 auto block_device_socket_path = instance.PerInstanceInternalUdsPath(
51 fmt::format("vhost-user-block-{}-socket", num));
52 auto block_device_logs_path = instance.PerInstanceInternalPath(
53 fmt::format("crosvm_vhost_user_block_{}.fifo", num));
54 auto block_device_logs =
55 CF_EXPECT(SharedFD::Fifo(block_device_logs_path, 0666));
56
57 Command block_device_logs_cmd(HostBinaryPath("log_tee"));
58 block_device_logs_cmd.AddParameter("--process_name=crosvm_block_", num);
59 block_device_logs_cmd.AddParameter("--log_fd_in=", block_device_logs);
60 block_device_logs_cmd.SetStopper(KillSubprocessFallback([](Subprocess* proc) {
61 // Ask nicely so that log_tee gets a chance to process all the logs.
62 // TODO: b/335934714 - Make sure the process actually exits
63 bool res = kill(proc->pid(), SIGINT) == 0;
64 return res ? StopperResult::kStopSuccess : StopperResult::kStopFailure;
65 }));
66
67 const std::string crosvm_path = config.crosvm_binary();
68
69 CrosvmBuilder block_device_cmd;
70
71 // NOTE: The "main" crosvm process returns a kCrosvmVmResetExitCode when the
72 // guest exits but the "block" crosvm just exits cleanly with 0 after the
73 // "main" crosvm disconnects.
74 block_device_cmd.ApplyProcessRestarter(config.crosvm_binary(),
75 /*first_time_argument=*/"",
76 /*exit_code=*/0);
77
78 block_device_cmd.Cmd().AddParameter("devices");
79 block_device_cmd.Cmd().AddParameter("--block");
80 block_device_cmd.Cmd().AddParameter("vhost=", block_device_socket_path,
81 ",path=", disk_path);
82
83 if (instance.enable_sandbox()) {
84 const bool seccomp_exists = DirectoryExists(instance.seccomp_policy_dir());
85 const std::string& var_empty_dir = kCrosvmVarEmptyDir;
86 const bool var_empty_available = DirectoryExists(var_empty_dir);
87 CF_EXPECT(var_empty_available && seccomp_exists,
88 var_empty_dir << " is not an existing, empty directory."
89 << "seccomp-policy-dir, "
90 << instance.seccomp_policy_dir()
91 << " does not exist");
92 block_device_cmd.Cmd().AddParameter("--jail");
93 block_device_cmd.Cmd().AddParameter("seccomp-policy-dir=",
94 instance.seccomp_policy_dir());
95 } else {
96 block_device_cmd.Cmd().AddParameter("--disable-sandbox");
97 }
98
99 return (VhostUserDeviceCommands){
100 .device_cmd = std::move(block_device_cmd.Cmd()),
101 .device_logs_cmd = std::move(block_device_logs_cmd),
102 .socket_path = block_device_socket_path,
103 };
104 }
105
106 } // namespace vm_manager
107 } // namespace cuttlefish
108