1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef SANDBOX_POLICY_LINUX_SANDBOX_LINUX_H_ 6 #define SANDBOX_POLICY_LINUX_SANDBOX_LINUX_H_ 7 8 #include <memory> 9 #include <string> 10 #include <vector> 11 12 #include "base/check_op.h" 13 #include "base/macros.h" 14 #include "base/posix/global_descriptors.h" 15 #include "sandbox/linux/syscall_broker/broker_command.h" 16 #include "sandbox/linux/syscall_broker/broker_file_permission.h" 17 #include "sandbox/policy/export.h" 18 #include "sandbox/policy/linux/sandbox_seccomp_bpf_linux.h" 19 #include "sandbox/policy/sandbox_type.h" 20 #include "sandbox/policy/sanitizer_buildflags.h" 21 22 #if BUILDFLAG(USING_SANITIZER) 23 #include <sanitizer/common_interface_defs.h> 24 #endif 25 26 namespace base { 27 template <typename T> 28 struct DefaultSingletonTraits; 29 class Thread; 30 } // namespace base 31 32 namespace sandbox { 33 namespace syscall_broker { 34 class BrokerProcess; 35 } // namespace syscall_broker 36 class SetuidSandboxClient; 37 } // namespace sandbox 38 39 namespace sandbox { 40 namespace policy { 41 42 // A singleton class to represent and change our sandboxing state for the 43 // three main Linux sandboxes. 44 // The sandboxing model allows using two layers of sandboxing. The first layer 45 // can be implemented either with unprivileged namespaces or with the setuid 46 // sandbox. This class provides a way to engage the namespace sandbox, but does 47 // not deal with the legacy setuid sandbox directly. 48 // The second layer is mainly based on seccomp-bpf and is engaged with 49 // InitializeSandbox(). InitializeSandbox() is also responsible for "sealing" 50 // the first layer of sandboxing. That is, InitializeSandbox must always be 51 // called to have any meaningful sandboxing at all. 52 class SANDBOX_POLICY_EXPORT SandboxLinux { 53 public: 54 // This is a list of sandbox IPC methods which the renderer may send to the 55 // sandbox host. See 56 // https://chromium.googlesource.com/chromium/src/+/master/docs/linux/sandbox_ipc.md 57 // This isn't the full list, values < 32 are reserved for methods called from 58 // Skia, and values < 64 are reserved for libc_interceptor.cc. 59 enum LinuxSandboxIPCMethods { 60 DEPRECATED_METHOD_GET_FALLBACK_FONT_FOR_CHAR = 64, 61 DEPRECATED_METHOD_GET_CHILD_WITH_INODE, 62 DEPRECATED_METHOD_GET_STYLE_FOR_STRIKE, 63 METHOD_MAKE_SHARED_MEMORY_SEGMENT, 64 DEPRECATED_METHOD_MATCH_WITH_FALLBACK, 65 }; 66 67 // These form a bitmask which describes the conditions of the Linux sandbox. 68 // Note: this doesn't strictly give you the current status, it states 69 // what will be enabled when the relevant processes are initialized. 70 enum Status { 71 // SUID sandbox active. 72 kSUID = 1 << 0, 73 74 // Sandbox is using a new PID namespace. 75 kPIDNS = 1 << 1, 76 77 // Sandbox is using a new network namespace. 78 kNetNS = 1 << 2, 79 80 // seccomp-bpf sandbox active. 81 kSeccompBPF = 1 << 3, 82 83 // The Yama LSM module is present and enforcing. 84 kYama = 1 << 4, 85 86 // seccomp-bpf sandbox is active and the kernel supports TSYNC. 87 kSeccompTSYNC = 1 << 5, 88 89 // User namespace sandbox active. 90 kUserNS = 1 << 6, 91 92 // A flag that denotes an invalid sandbox status. 93 kInvalid = 1 << 31, 94 }; 95 96 // SandboxLinux Options are a superset of SandboxSecompBPF Options. 97 struct Options : public SandboxSeccompBPF::Options { 98 // When running with a zygote, the namespace sandbox will have already 99 // been engaged prior to initializing SandboxLinux itself, and need not 100 // be done so again. Set to true to indicate that there isn't a zygote 101 // for this process and the step is to be performed here explicitly. 102 bool engage_namespace_sandbox = false; 103 104 // Allow starting the sandbox with multiple threads already running. This 105 // will enable TSYNC for seccomp-BPF, which syncs the seccomp-BPF policy 106 // across all running threads. 107 bool allow_threads_during_sandbox_init = false; 108 109 // Enables the CHECK for open directories. The open directory check is only 110 // useful for the chroot jail (from the semantic layer of the sandbox), and 111 // can safely be disabled if we are only enabling the seccomp-BPF layer. 112 bool check_for_open_directories = true; 113 }; 114 115 // Callers can provide this hook to run code right before the policy 116 // is passed to the BPF compiler and the sandbox is engaged. If 117 // pre_sandbox_hook() returns true, the sandbox will be engaged 118 // afterwards, otherwise the process is terminated. 119 using PreSandboxHook = base::OnceCallback<bool(Options)>; 120 121 // Get our singleton instance. 122 static SandboxLinux* GetInstance(); 123 124 // Do some initialization that can only be done before any of the sandboxes 125 // are enabled. If using the setuid sandbox, this should be called manually 126 // before the setuid sandbox is engaged. 127 // Security: When this runs, it is imperative that either InitializeSandbox() 128 // runs as well or that all file descriptors returned in 129 // GetFileDescriptorsToClose() get closed. 130 // Otherwise file descriptors that bypass the security of the setuid sandbox 131 // would be kept open. One must be particularly careful if a process performs 132 // a fork(). 133 void PreinitializeSandbox(); 134 135 // Check that the current process is the init process of a new PID 136 // namespace and then proceed to drop access to the file system by using 137 // a new unprivileged namespace. This is a layer-1 sandbox. 138 // In order for this sandbox to be effective, it must be "sealed" by calling 139 // InitializeSandbox(). 140 // Terminates the process in case the sandboxing operations cannot complete 141 // successfully. 142 void EngageNamespaceSandbox(bool from_zygote); 143 144 // Performs the same actions as EngageNamespaceSandbox, but is allowed to 145 // to fail. This is useful when sandboxed non-renderer processes could 146 // benefit from extra sandboxing but is not strictly required on systems that 147 // don't support unprivileged user namespaces. 148 // Zygote should use EngageNamespaceSandbox instead. 149 bool EngageNamespaceSandboxIfPossible(); 150 151 // Return a list of file descriptors to close if PreinitializeSandbox() ran 152 // but InitializeSandbox() won't. Avoid using. 153 // TODO(jln): get rid of this hack. 154 std::vector<int> GetFileDescriptorsToClose(); 155 156 // Seal an eventual layer-1 sandbox and initialize the layer-2 sandbox with 157 // an adequate policy depending on the process type and command line 158 // arguments. 159 // Currently the layer-2 sandbox is composed of seccomp-bpf and address space 160 // limitations. 161 // This function should only be called without any thread running. 162 bool InitializeSandbox(SandboxType sandbox_type, 163 PreSandboxHook hook, 164 const Options& options); 165 166 // Stop |thread| in a way that can be trusted by the sandbox. 167 void StopThread(base::Thread* thread); 168 169 // Returns the status of the renderer, worker and ppapi sandbox. Can only 170 // be queried after going through PreinitializeSandbox(). This is a bitmask 171 // and uses the constants defined in "enum Status" above. Since the 172 // status needs to be provided before the sandboxes are actually started, 173 // this returns what will actually happen once InitializeSandbox() 174 // is called from inside these processes. 175 int GetStatus(); 176 177 // Returns true if the current process is single-threaded or if the number 178 // of threads cannot be determined. 179 bool IsSingleThreaded() const; 180 181 // Returns true if we started Seccomp BPF. 182 bool seccomp_bpf_started() const; 183 184 // Simple accessor for our instance of the setuid sandbox. Will never return 185 // NULL. 186 // There is no StartSetuidSandbox(), the SetuidSandboxClient instance should 187 // be used directly. 188 SetuidSandboxClient* setuid_sandbox_client() const; 189 190 // Check the policy and eventually start the seccomp-bpf sandbox. Fine to be 191 // called with threads, as long as 192 // |options.allow_threads_during_sandbox_init| is true and the kernel 193 // supports seccomp's TSYNC feature. If TSYNC is not available we treat 194 // multiple threads as a fatal error. 195 bool StartSeccompBPF(SandboxType sandbox_type, 196 PreSandboxHook hook, 197 const Options& options); 198 199 // Limit the address space of the current process (and its children) to make 200 // some vulnerabilities harder to exploit. Writes the errno due to setrlimit 201 // (including 0 if no error) into |error|. 202 bool LimitAddressSpace(int* error); 203 204 // Returns a file descriptor to proc. The file descriptor is no longer valid 205 // after the sandbox has been sealed. proc_fd()206 int proc_fd() const { 207 DCHECK_NE(-1, proc_fd_); 208 return proc_fd_; 209 } 210 211 #if BUILDFLAG(USING_SANITIZER) sanitizer_args()212 __sanitizer_sandbox_arguments* sanitizer_args() const { 213 return sanitizer_args_.get(); 214 } 215 #endif 216 217 // A BrokerProcess is a helper that is started before the sandbox is engaged, 218 // typically from a pre-sandbox hook, that will serve requests to access 219 // files over an IPC channel. The client of this runs from a SIGSYS handler 220 // triggered by the seccomp-bpf sandbox. 221 // |client_sandbox_policy| is the policy being run by the client, and is 222 // used to derive the equivalent broker-side policy. 223 // |broker_side_hook| is an alternate pre-sandbox hook to be run before the 224 // broker itself gets sandboxed, to which the broker side policy and 225 // |options| are passed. 226 // Crashes the process if the broker can not be started since continuation 227 // is impossible (and presumably unsafe). 228 // This should never be destroyed, as after the sandbox is started it is 229 // vital to the process. 230 void StartBrokerProcess( 231 const syscall_broker::BrokerCommandSet& allowed_command_set, 232 std::vector<syscall_broker::BrokerFilePermission> permissions, 233 PreSandboxHook broker_side_hook, 234 const Options& options); 235 236 // Returns true if the broker should handle a particular syscall indicated by 237 // |sysno|. This will typically return true for system calls that take 238 // filepaths as arguments. 239 bool ShouldBrokerHandleSyscall(int sysno) const; 240 241 // Returns an expression that indicates the syscall in question should be 242 // handled transparently by the broker process. This is useful for file 243 // syscalls that take pathnames, so we can enforce pathname whitelisting. 244 // Only usable if StartBrokerProcess() was already called. 245 bpf_dsl::ResultExpr HandleViaBroker() const; 246 247 private: 248 friend struct base::DefaultSingletonTraits<SandboxLinux>; 249 250 SandboxLinux(); 251 ~SandboxLinux(); 252 253 // We must have been pre_initialized_ before using these. 254 bool seccomp_bpf_supported() const; 255 bool seccomp_bpf_with_tsync_supported() const; 256 257 // Returns true if it can be determined that the current process has open 258 // directories that are not managed by the SandboxLinux class. This would 259 // be a vulnerability as it would allow to bypass the setuid sandbox. 260 bool HasOpenDirectories() const; 261 262 // The last part of the initialization is to make sure any temporary "hole" 263 // in the sandbox is closed. For now, this consists of closing proc_fd_. 264 void SealSandbox(); 265 266 // GetStatus() makes promises as to how the sandbox will behave. This 267 // checks that no promises have been broken. 268 void CheckForBrokenPromises(SandboxType sandbox_type); 269 270 // Stop |thread| and make sure it does not appear in /proc/self/tasks/ 271 // anymore. 272 void StopThreadAndEnsureNotCounted(base::Thread* thread) const; 273 274 // Engages the namespace sandbox as described for EngageNamespaceSandbox. 275 // Returns false if it fails to transition to a new user namespace, but 276 // after transitioning to a new user namespace we don't allow this function 277 // to fail. 278 bool EngageNamespaceSandboxInternal(bool from_zygote); 279 280 // A file descriptor to /proc. It's dangerous to have it around as it could 281 // allow for sandbox bypasses. It needs to be closed before we consider 282 // ourselves sandboxed. 283 int proc_fd_; 284 285 bool seccomp_bpf_started_; 286 // The value returned by GetStatus(). Gets computed once and then cached. 287 int sandbox_status_flags_; 288 // Did PreinitializeSandbox() run? 289 bool pre_initialized_; 290 bool seccomp_bpf_supported_; // Accurate if pre_initialized_. 291 bool seccomp_bpf_with_tsync_supported_; // Accurate if pre_initialized_. 292 bool yama_is_enforcing_; // Accurate if pre_initialized_. 293 bool initialize_sandbox_ran_; // InitializeSandbox() was called. 294 std::unique_ptr<SetuidSandboxClient> setuid_sandbox_client_; 295 #if BUILDFLAG(USING_SANITIZER) 296 std::unique_ptr<__sanitizer_sandbox_arguments> sanitizer_args_; 297 #endif 298 syscall_broker::BrokerProcess* broker_process_; // Leaked as global. 299 300 DISALLOW_COPY_AND_ASSIGN(SandboxLinux); 301 }; 302 303 } // namespace policy 304 } // namespace sandbox 305 306 #endif // SANDBOX_POLICY_LINUX_SANDBOX_LINUX_H_ 307