1 // Copyright 2014 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 COMPONENTS_NACL_LOADER_SANDBOX_LINUX_NACL_SANDBOX_LINUX_H_ 6 #define COMPONENTS_NACL_LOADER_SANDBOX_LINUX_NACL_SANDBOX_LINUX_H_ 7 8 #include "base/files/scoped_file.h" 9 #include "base/macros.h" 10 #include "base/memory/scoped_ptr.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 ~NaClSandbox(); 41 42 // This API will only work if the layer-1 sandbox is not sealed and the 43 // layer-2 sandbox is not engaged. 44 bool IsSingleThreaded(); 45 // Check whether the current process owns any directory file descriptors. This 46 // will ignore any directory file descriptor owned by this object (i.e. those 47 // that will be closed after SealLayerOneSandbox()) is called. 48 // This API will only work if the layer-1 sandbox is not sealed and the 49 // layer-2 sandbox is not engaged. 50 bool HasOpenDirectory(); 51 // Will attempt to initialize the layer-1 sandbox, depending on flags and the 52 // environment. It can only succeed if the current process is a child of the 53 // setuid sandbox. 54 void InitializeLayerOneSandbox(); 55 // Will attempt to initialize the layer-2 sandbox, depending on flags and the 56 // environment. |uses_nonsfi_mode| describes which seccomp-bpf policy is 57 // appropriate. 58 void InitializeLayerTwoSandbox(bool uses_nonsfi_mode); 59 // Seal the layer-1 sandbox, making it enforcing. 60 void SealLayerOneSandbox(); 61 // Check that the current sandboxing state matches the level of sandboxing 62 // expected for NaCl in the current configuration. Crash if it does not. 63 void CheckSandboxingStateWithPolicy(); 64 65 bool layer_one_enabled() { return layer_one_enabled_; } 66 bool layer_two_enabled() { return layer_two_enabled_; } 67 68 private: 69 void CheckForExpectedNumberOfOpenFds(); 70 71 bool layer_one_enabled_; 72 bool layer_one_sealed_; 73 bool layer_two_enabled_; 74 bool layer_two_is_nonsfi_; 75 // |proc_fd_| must be released before the layer-1 sandbox is considered 76 // enforcing. 77 base::ScopedFD proc_fd_; 78 scoped_ptr<sandbox::SetuidSandboxClient> setuid_sandbox_client_; 79 DISALLOW_COPY_AND_ASSIGN(NaClSandbox); 80 }; 81 82 } // namespace nacl 83 84 #endif // COMPONENTS_NACL_LOADER_SANDBOX_LINUX_NACL_SANDBOX_LINUX_H_ 85