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 #include "host/commands/process_sandboxer/policies.h"
17
18 #include <linux/bpf_common.h>
19 #include <linux/filter.h>
20 #include <linux/prctl.h>
21 #include <sys/mman.h>
22 #include <sys/socket.h>
23 #include <sys/stat.h>
24 #include <syscall.h>
25 #include <unistd.h>
26
27 #include <cstdint>
28 #include <string>
29 #include <vector>
30
31 #include <absl/strings/str_cat.h>
32 #include <absl/strings/str_replace.h>
33 #include <sandboxed_api/sandbox2/policybuilder.h>
34 #include <sandboxed_api/sandbox2/util/bpf_helper.h>
35 #include <sandboxed_api/util/path.h>
36
37 namespace cuttlefish::process_sandboxer {
38
39 using sapi::file::JoinPath;
40
RunCvdPolicy(const HostInfo & host)41 sandbox2::PolicyBuilder RunCvdPolicy(const HostInfo& host) {
42 std::string sandboxer_proxy = host.HostToolExe("sandboxer_proxy");
43 return BaselinePolicy(host, host.HostToolExe("run_cvd"))
44 .AddDirectory(host.runtime_dir, /* is_ro= */ false)
45 .AddDirectory(
46 JoinPath(host.host_artifacts_path, "etc", "default_input_devices"))
47 .AddFile(host.cuttlefish_config_path)
48 .AddFile("/dev/null", /* is_ro= */ false)
49 .AddFileAt(sandboxer_proxy, host.HostToolExe("adb_connector"))
50 .AddFileAt(sandboxer_proxy, host.HostToolExe("casimir_control_server"))
51 .AddFileAt(sandboxer_proxy, host.HostToolExe("cf_vhost_user_input"))
52 .AddFileAt(sandboxer_proxy, host.HostToolExe("control_env_proxy_server"))
53 .AddFileAt(sandboxer_proxy, host.HostToolExe("crosvm"))
54 .AddFileAt(sandboxer_proxy, host.HostToolExe("echo_server"))
55 .AddFileAt(sandboxer_proxy, host.HostToolExe("gnss_grpc_proxy"))
56 .AddFileAt(sandboxer_proxy, host.HostToolExe("kernel_log_monitor"))
57 .AddFileAt(sandboxer_proxy, host.HostToolExe("log_tee"))
58 .AddFileAt(sandboxer_proxy, host.HostToolExe("logcat_receiver"))
59 .AddFileAt(sandboxer_proxy, host.HostToolExe("metrics"))
60 .AddFileAt(sandboxer_proxy, host.HostToolExe("modem_simulator"))
61 .AddFileAt(sandboxer_proxy, host.HostToolExe("netsimd"))
62 .AddFileAt(sandboxer_proxy, host.HostToolExe("openwrt_control_server"))
63 .AddFileAt(sandboxer_proxy, host.HostToolExe("operator_proxy"))
64 .AddFileAt(sandboxer_proxy, host.HostToolExe("process_restarter"))
65 .AddFileAt(sandboxer_proxy, host.HostToolExe("screen_recording_server"))
66 .AddFileAt(sandboxer_proxy, host.HostToolExe("secure_env"))
67 .AddFileAt(sandboxer_proxy, host.HostToolExe("socket_vsock_proxy"))
68 .AddFileAt(sandboxer_proxy, host.HostToolExe("tcp_connector"))
69 .AddFileAt(sandboxer_proxy, host.HostToolExe("tombstone_receiver"))
70 .AddFileAt(sandboxer_proxy, host.HostToolExe("webRTC"))
71 .AddFileAt(sandboxer_proxy, host.HostToolExe("webrtc_operator"))
72 .AddFileAt(sandboxer_proxy, host.HostToolExe("wmediumd"))
73 .AddFileAt(sandboxer_proxy, host.HostToolExe("wmediumd_gen_config"))
74 .AddDirectory(host.environments_dir)
75 .AddDirectory(host.EnvironmentsUdsDir(), /* is_ro= */ false)
76 .AddDirectory(host.InstanceUdsDir(), /* is_ro= */ false)
77 .AddDirectory(host.VsockDeviceDir(), /* is_ro= */ false)
78 // The UID inside the sandbox2 namespaces is always 1000.
79 .AddDirectoryAt(host.EnvironmentsUdsDir(),
80 absl::StrReplaceAll(
81 host.EnvironmentsUdsDir(),
82 {{absl::StrCat("cf_env_", getuid()), "cf_env_1000"}}),
83 false)
84 .AddDirectoryAt(host.InstanceUdsDir(),
85 absl::StrReplaceAll(
86 host.InstanceUdsDir(),
87 {{absl::StrCat("cf_avd_", getuid()), "cf_avd_1000"}}),
88 false)
89 .AddPolicyOnSyscall(__NR_madvise,
90 {ARG_32(2), JEQ32(MADV_DONTNEED, ALLOW)})
91 .AddPolicyOnSyscall(
92 __NR_mknodat,
93 [](bpf_labels& labels) -> std::vector<sock_filter> {
94 return {
95 ARG_32(2),
96 // a <- a & S_IFMT // Mask to only the file type bits
97 BPF_STMT(BPF_ALU + BPF_AND + BPF_K,
98 static_cast<uint32_t>(S_IFMT)),
99 // Only allow `mkfifo`
100 JNE32(S_IFIFO, JUMP(&labels, cf_mknodat_end)),
101 ARG_32(3),
102 JEQ32(0, ALLOW),
103 LABEL(&labels, cf_mknodat_end),
104 };
105 })
106 .AddPolicyOnSyscall(__NR_prctl,
107 {ARG_32(0), JEQ32(PR_SET_PDEATHSIG, ALLOW),
108 JEQ32(PR_SET_CHILD_SUBREAPER, ALLOW)})
109 .AddPolicyOnSyscall(
110 __NR_setsockopt,
111 [](bpf_labels& labels) -> std::vector<sock_filter> {
112 return {
113 ARG_32(1),
114 JNE32(SOL_SOCKET, JUMP(&labels, cf_setsockopt_end)),
115 ARG_32(2),
116 JEQ32(SO_REUSEADDR, ALLOW),
117 JEQ32(SO_RCVTIMEO, ALLOW),
118 LABEL(&labels, cf_setsockopt_end),
119 };
120 })
121 .AddPolicyOnSyscall(__NR_socket, {ARG_32(0), JEQ32(AF_UNIX, ALLOW),
122 JEQ32(AF_VSOCK, ALLOW)})
123 .AllowChmod()
124 .AllowDup()
125 .AllowEventFd()
126 .AllowFork() // Multithreading, sandboxer_proxy, process monitor
127 .AllowGetIDs()
128 .AllowInotifyInit()
129 .AllowMkdir()
130 .AllowPipe()
131 .AllowSafeFcntl()
132 .AllowSelect()
133 .AllowSyscall(__NR_accept)
134 .AllowSyscall(__NR_bind)
135 .AllowSyscall(__NR_connect)
136 .AllowSyscall(__NR_execve) // sandboxer_proxy
137 .AllowSyscall(__NR_getsid)
138 .AllowSyscall(__NR_inotify_add_watch)
139 .AllowSyscall(__NR_inotify_rm_watch)
140 .AllowSyscall(__NR_listen)
141 .AllowSyscall(__NR_msgget) // Metrics SysV RPC
142 .AllowSyscall(__NR_msgsnd) // Metrics SysV RPC
143 .AllowSyscall(__NR_recvmsg)
144 .AllowSyscall(__NR_sendmsg)
145 .AllowSyscall(__NR_setpgid)
146 .AllowSyscall(__NR_shutdown)
147 .AllowSyscall(__NR_socketpair)
148 .AllowSyscall(__NR_waitid) // Not covered by `AllowWait()`
149 .AllowTCGETS()
150 .AllowUnlink()
151 .AllowWait();
152 }
153
154 } // namespace cuttlefish::process_sandboxer
155