1 // Copyright 2013 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_BROWSER_NACL_BROWSER_H_ 6 #define COMPONENTS_NACL_BROWSER_NACL_BROWSER_H_ 7 8 #include <deque> 9 10 #include "base/bind.h" 11 #include "base/containers/mru_cache.h" 12 #include "base/files/file_util_proxy.h" 13 #include "base/memory/singleton.h" 14 #include "base/memory/weak_ptr.h" 15 #include "base/platform_file.h" 16 #include "base/time/time.h" 17 #include "components/nacl/browser/nacl_browser_delegate.h" 18 #include "components/nacl/browser/nacl_validation_cache.h" 19 20 class URLPattern; 21 class GURL; 22 23 namespace nacl { 24 25 // Open an immutable executable file that can be mmapped. 26 // This function should only be called on a thread that can perform file IO. 27 base::PlatformFile OpenNaClExecutableImpl(const base::FilePath& file_path); 28 29 // Represents shared state for all NaClProcessHost objects in the browser. 30 class NaClBrowser { 31 public: 32 static NaClBrowser* GetInstance(); 33 34 // Will it be possible to launch a NaCl process, eventually? 35 bool IsOk() const; 36 37 // Are we ready to launch a NaCl process now? Implies IsOk(). 38 bool IsReady() const; 39 40 // Attempt to asynchronously acquire all resources needed to start a process. 41 // This method is idempotent - it is safe to call multiple times. 42 void EnsureAllResourcesAvailable(); 43 44 // Enqueues reply() in the message loop when all the resources needed to start 45 // a process have been acquired. 46 void WaitForResources(const base::Closure& reply); 47 48 // Asynchronously attempt to get the IRT open. 49 // This is entailed by EnsureInitialized. This method is exposed as part of 50 // the public interface, however, so the IRT can be explicitly opened as 51 // early as possible to prevent autoupdate issues. 52 void EnsureIrtAvailable(); 53 54 // Path to IRT. Available even before IRT is loaded. 55 const base::FilePath& GetIrtFilePath(); 56 57 // IRT file handle, only available when IsReady(). 58 base::PlatformFile IrtFile() const; 59 60 // Methods for testing GDB debug stub in browser. If test adds debug stub 61 // port listener, Chrome will allocate a currently-unused TCP port number for 62 // debug stub server instead of a fixed one. 63 64 // Notify listener that new debug stub TCP port is allocated. 65 void FireGdbDebugStubPortOpened(int port); 66 bool HasGdbDebugStubPortListener(); 67 void SetGdbDebugStubPortListener(base::Callback<void(int)> listener); 68 void ClearGdbDebugStubPortListener(); 69 70 bool ValidationCacheIsEnabled() const { 71 return validation_cache_is_enabled_; 72 } 73 74 const std::string& GetValidationCacheKey() const { 75 return validation_cache_.GetValidationCacheKey(); 76 } 77 78 // The NaCl singleton keeps information about NaCl executable files opened via 79 // PPAPI. This allows the NaCl process to get trusted information about the 80 // file directly from the browser process. In theory, a compromised renderer 81 // could provide a writable file handle or lie about the file's path. If we 82 // trusted the handle was read only but it was not, an mmapped file could be 83 // modified after validation, allowing an escape from the NaCl sandbox. 84 // Similarly, if we trusted the file path corresponded to the file handle but 85 // it did not, the validation cache could be tricked into bypassing validation 86 // for bad code. 87 // Instead of allowing these attacks, the NaCl process only trusts information 88 // it gets directly from the browser process. Because the information is 89 // stored in a cache of bounded size, it is not guaranteed the browser process 90 // will be able to provide the requested information. In these cases, the 91 // NaCl process must make conservative assumptions about the origin of the 92 // file. 93 // In theory, a compromised renderer could guess file tokens in an attempt to 94 // read files it normally doesn't have access to. This would not compromise 95 // the NaCl sandbox, however, and only has a 1 in ~2**120 chance of success 96 // per guess. 97 // TODO(ncbray): move the cache onto NaClProcessHost so that we don't need to 98 // rely on tokens being unguessable by another process. 99 void PutFilePath(const base::FilePath& path, uint64* file_token_lo, 100 uint64* file_token_hi); 101 bool GetFilePath(uint64 file_token_lo, uint64 file_token_hi, 102 base::FilePath* path); 103 104 bool QueryKnownToValidate(const std::string& signature, bool off_the_record); 105 void SetKnownToValidate(const std::string& signature, bool off_the_record); 106 void ClearValidationCache(const base::Closure& callback); 107 #if defined(OS_WIN) 108 // Get path to NaCl loader on the filesystem if possible. 109 // |exe_path| does not change if the method fails. 110 bool GetNaCl64ExePath(base::FilePath* exe_path); 111 #endif 112 113 void EarlyStartup(); 114 static void SetDelegate(NaClBrowserDelegate* delegate); 115 static NaClBrowserDelegate* GetDelegate(); 116 117 // Support for NaCl crash throttling. 118 // Each time a NaCl module crashes, the browser is notified. 119 void OnProcessCrashed(); 120 // If "too many" crashes occur within a given time period, NaCl is throttled 121 // until the rate again drops below the threshold. 122 bool IsThrottled(); 123 124 private: 125 friend struct DefaultSingletonTraits<NaClBrowser>; 126 127 enum NaClResourceState { 128 NaClResourceUninitialized, 129 NaClResourceRequested, 130 NaClResourceReady 131 }; 132 133 NaClBrowser(); 134 ~NaClBrowser(); 135 136 void InitIrtFilePath(); 137 138 void OpenIrtLibraryFile(); 139 140 void OnIrtOpened(base::PlatformFileError error_code, 141 base::PassPlatformFile file, bool created); 142 143 void InitValidationCacheFilePath(); 144 void EnsureValidationCacheAvailable(); 145 void OnValidationCacheLoaded(const std::string* data); 146 void RunWithoutValidationCache(); 147 148 // Dispatch waiting tasks if we are ready, or if we know we'll never be ready. 149 void CheckWaiting(); 150 151 // Indicate that it is impossible to launch a NaCl process. 152 void MarkAsFailed(); 153 154 void MarkValidationCacheAsModified(); 155 void PersistValidationCache(); 156 157 // Singletons get destroyed at shutdown. 158 base::WeakPtrFactory<NaClBrowser> weak_factory_; 159 160 base::PlatformFile irt_platform_file_; 161 base::FilePath irt_filepath_; 162 NaClResourceState irt_state_; 163 NaClValidationCache validation_cache_; 164 NaClValidationCache off_the_record_validation_cache_; 165 base::FilePath validation_cache_file_path_; 166 bool validation_cache_is_enabled_; 167 bool validation_cache_is_modified_; 168 NaClResourceState validation_cache_state_; 169 base::Callback<void(int)> debug_stub_port_listener_; 170 171 typedef base::HashingMRUCache<std::string, base::FilePath> PathCacheType; 172 PathCacheType path_cache_; 173 174 bool ok_; 175 176 // A list of pending tasks to start NaCl processes. 177 std::vector<base::Closure> waiting_; 178 179 scoped_ptr<NaClBrowserDelegate> browser_delegate_; 180 181 std::deque<base::Time> crash_times_; 182 183 DISALLOW_COPY_AND_ASSIGN(NaClBrowser); 184 }; 185 186 } // namespace nacl 187 188 #endif // COMPONENTS_NACL_BROWSER_NACL_BROWSER_H_ 189