1 // Copyright 2014 The Chromium Authors 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 COMPONENTS_NACL_LOADER_SANDBOX_LINUX_NACL_SANDBOX_LINUX_H_ 6 #define COMPONENTS_NACL_LOADER_SANDBOX_LINUX_NACL_SANDBOX_LINUX_H_ 7 8 #include <memory> 9 10 #include "base/files/scoped_file.h" 11 12 namespace sandbox { 13 class SetuidSandboxClient; 14 } 15 16 namespace nacl { 17 18 // NaClSandbox supports two independent layers of sandboxing. 19 // layer-1 uses a chroot. It requires both InitializeLayerOneSandbox() and 20 // SealLayerOneSandbox() to have been called to be enforcing. 21 // layer-2 uses seccomp-bpf. It requires the layer-1 sandbox to not yet be 22 // sealed when being engaged. 23 // For the layer-1 sandbox to work, the current process must be a child of 24 // the setuid sandbox. InitializeLayerOneSandbox() can only be called once 25 // per instance of the setuid sandbox. 26 // 27 // A typical use case of this class would be: 28 // 1. Load libraries and do some pre-initialization 29 // 2. InitializeLayerOneSandbox(); 30 // 3. Do some more initializations (it is ok to fork() here). 31 // 4. CHECK(!HasOpenDirectory)); 32 // (This check is not strictly necessary, as the only possibility for a 33 // new directory descriptor to exist after (2) has been called is via IPC)). 34 // 5. InitializeLayerTwoSandbox(); 35 // 6. SealLayerOneSandbox(); 36 // 7. CheckSandboxingStateWithPolicy(); 37 class NaClSandbox { 38 public: 39 NaClSandbox(); 40 41 NaClSandbox(const NaClSandbox&) = delete; 42 NaClSandbox& operator=(const NaClSandbox&) = delete; 43 44 ~NaClSandbox(); 45 46 // This API will only work if the layer-1 sandbox is not sealed and the 47 // layer-2 sandbox is not engaged. 48 bool IsSingleThreaded(); 49 // Check whether the current process owns any directory file descriptors. This 50 // will ignore any directory file descriptor owned by this object (i.e. those 51 // that will be closed after SealLayerOneSandbox()) is called. 52 // This API will only work if the layer-1 sandbox is not sealed and the 53 // layer-2 sandbox is not engaged. 54 bool HasOpenDirectory(); 55 // Will attempt to initialize the layer-1 sandbox, depending on flags and the 56 // environment. It can only succeed if the current process is a child of the 57 // setuid sandbox or was started by the namespace sandbox. 58 void InitializeLayerOneSandbox(); 59 // Will attempt to initialize the layer-2 sandbox, depending on flags and the 60 // environment. 61 // This layer will also add a limit to how much of the address space can be 62 // used. 63 void InitializeLayerTwoSandbox(); 64 // Seal the layer-1 sandbox, making it enforcing. 65 void SealLayerOneSandbox(); 66 // Check that the current sandboxing state matches the level of sandboxing 67 // expected for NaCl in the current configuration. Crash if it does not. 68 void CheckSandboxingStateWithPolicy(); 69 layer_one_enabled()70 bool layer_one_enabled() { return layer_one_enabled_; } layer_two_enabled()71 bool layer_two_enabled() { return layer_two_enabled_; } 72 73 private: 74 void CheckForExpectedNumberOfOpenFds(); 75 76 bool layer_one_enabled_; 77 bool layer_one_sealed_; 78 bool layer_two_enabled_; 79 // |proc_fd_| must be released before the layer-1 sandbox is considered 80 // enforcing. 81 base::ScopedFD proc_fd_; 82 std::unique_ptr<sandbox::SetuidSandboxClient> setuid_sandbox_client_; 83 }; 84 85 } // namespace nacl 86 87 #endif // COMPONENTS_NACL_LOADER_SANDBOX_LINUX_NACL_SANDBOX_LINUX_H_ 88