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/commands/process_sandboxer/policies.h"
18
19 #include <stdlib.h>
20
21 #include <cerrno>
22 #include <memory>
23 #include <ostream>
24 #include <set>
25 #include <string>
26 #include <string_view>
27 #include <utility>
28
29 #include <absl/container/flat_hash_map.h>
30 #include <absl/log/log.h>
31 #include <absl/status/status.h>
32 #include <sandboxed_api/sandbox2/policy.h>
33 #include <sandboxed_api/sandbox2/policybuilder.h>
34 #include <sandboxed_api/util/fileops.h>
35 #include <sandboxed_api/util/path.h>
36
37 #include "host/commands/process_sandboxer/proxy_common.h"
38
39 namespace cuttlefish::process_sandboxer {
40
41 using sapi::file::JoinPath;
42 using sapi::file_util::fileops::CreateDirectoryRecursively;
43
EnsureOutputDirectoriesExist()44 absl::Status HostInfo::EnsureOutputDirectoriesExist() {
45 if (!CreateDirectoryRecursively(assembly_dir, 0700)) {
46 return absl::ErrnoToStatus(errno, "Failed to create " + assembly_dir);
47 }
48 if (!CreateDirectoryRecursively(environments_dir, 0700)) {
49 return absl::ErrnoToStatus(errno, "Failed to create " + environments_dir);
50 }
51 if (!CreateDirectoryRecursively(EnvironmentsUdsDir(), 0700)) {
52 return absl::ErrnoToStatus(errno,
53 "Failed to create " + EnvironmentsUdsDir());
54 }
55 if (!CreateDirectoryRecursively(InstanceUdsDir(), 0700)) {
56 return absl::ErrnoToStatus(errno, "Failed to create " + InstanceUdsDir());
57 }
58 if (!CreateDirectoryRecursively(log_dir, 0700)) {
59 return absl::ErrnoToStatus(errno, "Failed to create " + log_dir);
60 }
61 if (!CreateDirectoryRecursively(runtime_dir, 0700)) {
62 return absl::ErrnoToStatus(errno, "Failed to create " + runtime_dir);
63 }
64 if (!CreateDirectoryRecursively(VsockDeviceDir(), 0700)) {
65 return absl::ErrnoToStatus(errno, "Failed to create " + runtime_dir);
66 }
67 return absl::OkStatus();
68 }
69
EnvironmentsUdsDir() const70 std::string HostInfo::EnvironmentsUdsDir() const {
71 return JoinPath(tmp_dir, "cf_env_1000");
72 }
73
HostToolExe(std::string_view exe) const74 std::string HostInfo::HostToolExe(std::string_view exe) const {
75 return JoinPath(host_artifacts_path, "bin", exe);
76 }
77
InstanceUdsDir() const78 std::string HostInfo::InstanceUdsDir() const {
79 return JoinPath(tmp_dir, "cf_avd_1000/cvd-1");
80 }
81
VsockDeviceDir() const82 std::string HostInfo::VsockDeviceDir() const {
83 return JoinPath(tmp_dir, "vsock_3_1000");
84 }
85
operator <<(std::ostream & out,const HostInfo & host)86 std::ostream& operator<<(std::ostream& out, const HostInfo& host) {
87 out << "HostInfo {\n";
88 out << "\tassembly_dir: \"" << host.assembly_dir << "\"\n";
89 out << "\tcuttlefish_config_path: \"" << host.cuttlefish_config_path
90 << "\"\n";
91 out << "\tenvironments_dir: \"" << host.environments_dir << "\"\n";
92 out << "\tenvironments_uds_dir: " << host.EnvironmentsUdsDir() << "\"\n";
93 out << "\tguest_image_path: " << host.guest_image_path << "\t\n";
94 out << "\thost_artifacts_path: \"" << host.host_artifacts_path << "\"\n";
95 out << "\tinstance_uds_dir: " << host.InstanceUdsDir() << "\"\n";
96 out << "\tlog_dir: " << host.log_dir << "\"\n";
97 out << "\truntime_dir: " << host.runtime_dir << "\"\n";
98 out << "\ttmp_dir: \"" << host.tmp_dir << "\"\n";
99 out << "\tvsock_device_dir: \"" << host.VsockDeviceDir() << "\"\n";
100 return out << "}";
101 }
102
PolicyForExecutable(const HostInfo & host,std::string_view server_socket_outside_path,std::string_view executable)103 std::unique_ptr<sandbox2::Policy> PolicyForExecutable(
104 const HostInfo& host, std::string_view server_socket_outside_path,
105 std::string_view executable) {
106 using Builder = sandbox2::PolicyBuilder(const HostInfo&);
107 absl::flat_hash_map<std::string, Builder*> builders;
108
109 builders[host.HostToolExe("adb_connector")] = AdbConnectorPolicy;
110 builders[host.HostToolExe("assemble_cvd")] = AssembleCvdPolicy;
111 builders[host.HostToolExe("avbtool")] = AvbToolPolicy;
112 builders[host.HostToolExe("casimir")] = CasimirPolicy;
113 builders[host.HostToolExe("cf_vhost_user_input")] = CfVhostUserInput;
114 builders[host.HostToolExe("casimir_control_server")] =
115 CasimirControlServerPolicy;
116 builders[host.HostToolExe("control_env_proxy_server")] =
117 ControlEnvProxyServerPolicy;
118 builders[host.HostToolExe("cvd_internal_start")] = CvdInternalStartPolicy;
119 builders[host.HostToolExe("echo_server")] = EchoServerPolicy;
120 builders[host.HostToolExe("gnss_grpc_proxy")] = GnssGrpcProxyPolicy;
121 builders[host.HostToolExe("kernel_log_monitor")] = KernelLogMonitorPolicy;
122 builders[host.HostToolExe("log_tee")] = LogTeePolicy;
123 builders[host.HostToolExe("logcat_receiver")] = LogcatReceiverPolicy;
124 builders[host.HostToolExe("metrics")] = MetricsPolicy;
125 builders[host.HostToolExe("mkenvimage_slim")] = MkEnvImgSlimPolicy;
126 builders[host.HostToolExe("modem_simulator")] = ModemSimulatorPolicy;
127 builders[host.HostToolExe("netsimd")] = NetsimdPolicy;
128 builders[host.HostToolExe("newfs_msdos")] = NewFsMsDosPolicy;
129 builders[host.HostToolExe("openwrt_control_server")] =
130 OpenWrtControlServerPolicy;
131 builders[host.HostToolExe("operator_proxy")] = OperatorProxyPolicy;
132 builders[host.HostToolExe("process_restarter")] = ProcessRestarterPolicy;
133 builders[host.HostToolExe("run_cvd")] = RunCvdPolicy;
134 builders[host.HostToolExe("screen_recording_server")] =
135 ScreenRecordingServerPolicy;
136 builders[host.HostToolExe("secure_env")] = SecureEnvPolicy;
137 builders[host.HostToolExe("simg2img")] = Simg2ImgPolicy;
138 builders[host.HostToolExe("socket_vsock_proxy")] = SocketVsockProxyPolicy;
139 builders[host.HostToolExe("tcp_connector")] = TcpConnectorPolicy;
140 builders[host.HostToolExe("tombstone_receiver")] = TombstoneReceiverPolicy;
141 builders[host.HostToolExe("vhost_device_vsock")] = VhostDeviceVsockPolicy;
142 builders[host.HostToolExe("webRTC")] = WebRtcPolicy;
143 builders[host.HostToolExe("webrtc_operator")] = WebRtcOperatorPolicy;
144 builders[host.HostToolExe("wmediumd")] = WmediumdPolicy;
145 builders[host.HostToolExe("wmediumd_gen_config")] = WmediumdGenConfigPolicy;
146
147 std::set<std::string> no_policy_set = NoPolicy(host);
148 for (const auto& [exe, policy_builder] : builders) {
149 if (no_policy_set.count(exe)) {
150 LOG(FATAL) << "Overlap in policy map and no-policy set: '" << exe << "'";
151 }
152 }
153
154 if (auto it = builders.find(executable); it != builders.end()) {
155 // TODO(schuffelen): Only share this with executables known to launch others
156 auto r1 = (it->second)(host);
157 r1.AddFileAt(server_socket_outside_path, kManagerSocketPath, false);
158 auto r2 = r1.TryBuild();
159 if (!r2.ok()) {
160 LOG(INFO) << r2.status().ToString();
161 abort();
162 }
163 return std::move(*r2);
164 } else if (no_policy_set.count(std::string(executable))) {
165 return nullptr;
166 } else {
167 LOG(FATAL) << "Unknown executable '" << executable << "'";
168 }
169 }
170
171 } // namespace cuttlefish::process_sandboxer
172