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 CHROME_BROWSER_NACL_HOST_NACL_BROWSER_H_ 6 #define CHROME_BROWSER_NACL_HOST_NACL_BROWSER_H_ 7 8 #include "base/bind.h" 9 #include "base/containers/mru_cache.h" 10 #include "base/files/file_util_proxy.h" 11 #include "base/memory/singleton.h" 12 #include "base/memory/weak_ptr.h" 13 #include "base/platform_file.h" 14 #include "chrome/browser/nacl_host/nacl_validation_cache.h" 15 #include "components/nacl/common/nacl_browser_delegate.h" 16 17 class URLPattern; 18 class GURL; 19 20 namespace nacl { 21 22 // Open an immutable executable file that can be mmapped. 23 // This function should only be called on a thread that can perform file IO. 24 void OpenNaClExecutableImpl(const base::FilePath& file_path, 25 base::PlatformFile* file); 26 27 } 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 // Set match patterns which will be checked before enabling debug stub. 61 void SetDebugPatterns(std::string debug_patterns); 62 63 // Returns whether NaCl application with this manifest URL should be debugged. 64 bool URLMatchesDebugPatterns(GURL manifest_url); 65 66 // Methods for testing GDB debug stub in browser. If test adds debug stub 67 // port listener, Chrome will allocate a currently-unused TCP port number for 68 // debug stub server instead of a fixed one. 69 70 // Notify listener that new debug stub TCP port is allocated. 71 void FireGdbDebugStubPortOpened(int port); 72 bool HasGdbDebugStubPortListener(); 73 void SetGdbDebugStubPortListener(base::Callback<void(int)> listener); 74 void ClearGdbDebugStubPortListener(); 75 76 bool ValidationCacheIsEnabled() const { 77 return validation_cache_is_enabled_; 78 } 79 80 const std::string& GetValidationCacheKey() const { 81 return validation_cache_.GetValidationCacheKey(); 82 } 83 84 // The NaCl singleton keeps information about NaCl executable files opened via 85 // PPAPI. This allows the NaCl process to get trusted information about the 86 // file directly from the browser process. In theory, a compromised renderer 87 // could provide a writable file handle or lie about the file's path. If we 88 // trusted the handle was read only but it was not, an mmapped file could be 89 // modified after validation, allowing an escape from the NaCl sandbox. 90 // Similarly, if we trusted the file path corresponded to the file handle but 91 // it did not, the validation cache could be tricked into bypassing validation 92 // for bad code. 93 // Instead of allowing these attacks, the NaCl process only trusts information 94 // it gets directly from the browser process. Because the information is 95 // stored in a cache of bounded size, it is not guaranteed the browser process 96 // will be able to provide the requested information. In these cases, the 97 // NaCl process must make conservative assumptions about the origin of the 98 // file. 99 // In theory, a compromised renderer could guess file tokens in an attempt to 100 // read files it normally doesn't have access to. This would not compromise 101 // the NaCl sandbox, however, and only has a 1 in ~2**120 chance of success 102 // per guess. 103 // TODO(ncbray): move the cache onto NaClProcessHost so that we don't need to 104 // rely on tokens being unguessable by another process. 105 void PutFilePath(const base::FilePath& path, uint64* file_token_lo, 106 uint64* file_token_hi); 107 bool GetFilePath(uint64 file_token_lo, uint64 file_token_hi, 108 base::FilePath* path); 109 110 bool QueryKnownToValidate(const std::string& signature, bool off_the_record); 111 void SetKnownToValidate(const std::string& signature, bool off_the_record); 112 void ClearValidationCache(const base::Closure& callback); 113 #if defined(OS_WIN) 114 // Get path to NaCl loader on the filesystem if possible. 115 // |exe_path| does not change if the method fails. 116 bool GetNaCl64ExePath(base::FilePath* exe_path); 117 #endif 118 119 void EarlyStartup(); 120 static void SetDelegate(NaClBrowserDelegate* delegate); 121 static NaClBrowserDelegate* GetDelegate(); 122 private: 123 friend struct DefaultSingletonTraits<NaClBrowser>; 124 125 enum NaClResourceState { 126 NaClResourceUninitialized, 127 NaClResourceRequested, 128 NaClResourceReady 129 }; 130 131 NaClBrowser(); 132 ~NaClBrowser(); 133 134 void InitIrtFilePath(); 135 136 void OpenIrtLibraryFile(); 137 138 void OnIrtOpened(base::PlatformFileError error_code, 139 base::PassPlatformFile file, bool created); 140 141 void InitValidationCacheFilePath(); 142 void EnsureValidationCacheAvailable(); 143 void OnValidationCacheLoaded(const std::string* data); 144 void RunWithoutValidationCache(); 145 146 // Dispatch waiting tasks if we are ready, or if we know we'll never be ready. 147 void CheckWaiting(); 148 149 // Indicate that it is impossible to launch a NaCl process. 150 void MarkAsFailed(); 151 152 void MarkValidationCacheAsModified(); 153 void PersistValidationCache(); 154 155 // Singletons get destroyed at shutdown. 156 base::WeakPtrFactory<NaClBrowser> weak_factory_; 157 158 base::PlatformFile irt_platform_file_; 159 base::FilePath irt_filepath_; 160 NaClResourceState irt_state_; 161 std::vector<URLPattern> debug_patterns_; 162 bool inverse_debug_patterns_; 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 DISALLOW_COPY_AND_ASSIGN(NaClBrowser); 181 }; 182 183 #endif // CHROME_BROWSER_NACL_HOST_NACL_BROWSER_H_ 184