1*6777b538SAndroid Build Coastguard Worker // Copyright 2013 The Chromium Authors 2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file. 4*6777b538SAndroid Build Coastguard Worker 5*6777b538SAndroid Build Coastguard Worker #ifndef COMPONENTS_NACL_BROWSER_NACL_BROWSER_H_ 6*6777b538SAndroid Build Coastguard Worker #define COMPONENTS_NACL_BROWSER_NACL_BROWSER_H_ 7*6777b538SAndroid Build Coastguard Worker 8*6777b538SAndroid Build Coastguard Worker #include <stdint.h> 9*6777b538SAndroid Build Coastguard Worker 10*6777b538SAndroid Build Coastguard Worker #include <memory> 11*6777b538SAndroid Build Coastguard Worker 12*6777b538SAndroid Build Coastguard Worker #include "base/containers/circular_deque.h" 13*6777b538SAndroid Build Coastguard Worker #include "base/containers/lru_cache.h" 14*6777b538SAndroid Build Coastguard Worker #include "base/files/file.h" 15*6777b538SAndroid Build Coastguard Worker #include "base/functional/bind.h" 16*6777b538SAndroid Build Coastguard Worker #include "base/task/sequenced_task_runner.h" 17*6777b538SAndroid Build Coastguard Worker #include "base/task/thread_pool.h" 18*6777b538SAndroid Build Coastguard Worker #include "base/time/time.h" 19*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h" 20*6777b538SAndroid Build Coastguard Worker #include "components/nacl/browser/nacl_browser_delegate.h" 21*6777b538SAndroid Build Coastguard Worker #include "components/nacl/browser/nacl_validation_cache.h" 22*6777b538SAndroid Build Coastguard Worker 23*6777b538SAndroid Build Coastguard Worker namespace base { 24*6777b538SAndroid Build Coastguard Worker class FileProxy; 25*6777b538SAndroid Build Coastguard Worker } 26*6777b538SAndroid Build Coastguard Worker 27*6777b538SAndroid Build Coastguard Worker namespace nacl { 28*6777b538SAndroid Build Coastguard Worker 29*6777b538SAndroid Build Coastguard Worker static const int kGdbDebugStubPortUnknown = -1; 30*6777b538SAndroid Build Coastguard Worker static const int kGdbDebugStubPortUnused = 0; 31*6777b538SAndroid Build Coastguard Worker 32*6777b538SAndroid Build Coastguard Worker // Keep the cache bounded to an arbitrary size. If it's too small, useful 33*6777b538SAndroid Build Coastguard Worker // entries could be evicted when multiple .nexes are loaded at once. On the 34*6777b538SAndroid Build Coastguard Worker // other hand, entries are not always claimed (and hence removed), so the size 35*6777b538SAndroid Build Coastguard Worker // of the cache will likely saturate at its maximum size. 36*6777b538SAndroid Build Coastguard Worker // Entries may not be claimed for two main reasons. 1) the NaCl process could 37*6777b538SAndroid Build Coastguard Worker // be killed while it is loading. 2) the trusted NaCl plugin opens files using 38*6777b538SAndroid Build Coastguard Worker // the code path but doesn't resolve them. 39*6777b538SAndroid Build Coastguard Worker // TODO(ncbray) don't cache files that the plugin will not resolve. 40*6777b538SAndroid Build Coastguard Worker static const int kFilePathCacheSize = 100; 41*6777b538SAndroid Build Coastguard Worker 42*6777b538SAndroid Build Coastguard Worker // Open an immutable executable file that can be mmapped (or a read-only file). 43*6777b538SAndroid Build Coastguard Worker // This function should only be called on a thread that can perform file IO. 44*6777b538SAndroid Build Coastguard Worker base::File OpenNaClReadExecImpl(const base::FilePath& file_path, 45*6777b538SAndroid Build Coastguard Worker bool is_executable); 46*6777b538SAndroid Build Coastguard Worker 47*6777b538SAndroid Build Coastguard Worker // Represents shared state for all NaClProcessHost objects in the browser. 48*6777b538SAndroid Build Coastguard Worker class NaClBrowser { 49*6777b538SAndroid Build Coastguard Worker public: 50*6777b538SAndroid Build Coastguard Worker static NaClBrowser* GetInstance(); 51*6777b538SAndroid Build Coastguard Worker 52*6777b538SAndroid Build Coastguard Worker NaClBrowser(const NaClBrowser&) = delete; 53*6777b538SAndroid Build Coastguard Worker NaClBrowser& operator=(const NaClBrowser&) = delete; 54*6777b538SAndroid Build Coastguard Worker 55*6777b538SAndroid Build Coastguard Worker // Will it be possible to launch a NaCl process, eventually? 56*6777b538SAndroid Build Coastguard Worker bool IsOk() const; 57*6777b538SAndroid Build Coastguard Worker 58*6777b538SAndroid Build Coastguard Worker // Are we ready to launch a NaCl process now? Implies IsOk(). 59*6777b538SAndroid Build Coastguard Worker bool IsReady() const; 60*6777b538SAndroid Build Coastguard Worker 61*6777b538SAndroid Build Coastguard Worker // Attempt to asynchronously acquire all resources needed to start a process. 62*6777b538SAndroid Build Coastguard Worker // This method is idempotent - it is safe to call multiple times. 63*6777b538SAndroid Build Coastguard Worker void EnsureAllResourcesAvailable(); 64*6777b538SAndroid Build Coastguard Worker 65*6777b538SAndroid Build Coastguard Worker // Enqueues reply() in the message loop when all the resources needed to start 66*6777b538SAndroid Build Coastguard Worker // a process have been acquired. 67*6777b538SAndroid Build Coastguard Worker void WaitForResources(base::OnceClosure reply); 68*6777b538SAndroid Build Coastguard Worker 69*6777b538SAndroid Build Coastguard Worker // Asynchronously attempt to get the IRT open. 70*6777b538SAndroid Build Coastguard Worker // This is entailed by EnsureInitialized. This method is exposed as part of 71*6777b538SAndroid Build Coastguard Worker // the public interface, however, so the IRT can be explicitly opened as 72*6777b538SAndroid Build Coastguard Worker // early as possible to prevent autoupdate issues. 73*6777b538SAndroid Build Coastguard Worker void EnsureIrtAvailable(); 74*6777b538SAndroid Build Coastguard Worker 75*6777b538SAndroid Build Coastguard Worker // Path to IRT. Available even before IRT is loaded. 76*6777b538SAndroid Build Coastguard Worker const base::FilePath& GetIrtFilePath(); 77*6777b538SAndroid Build Coastguard Worker 78*6777b538SAndroid Build Coastguard Worker // IRT file handle, only available when IsReady(). 79*6777b538SAndroid Build Coastguard Worker const base::File& IrtFile() const; 80*6777b538SAndroid Build Coastguard Worker 81*6777b538SAndroid Build Coastguard Worker // Methods for tracking the GDB debug stub port associated with each NaCl 82*6777b538SAndroid Build Coastguard Worker // process. 83*6777b538SAndroid Build Coastguard Worker void SetProcessGdbDebugStubPort(int process_id, int port); 84*6777b538SAndroid Build Coastguard Worker int GetProcessGdbDebugStubPort(int process_id); 85*6777b538SAndroid Build Coastguard Worker 86*6777b538SAndroid Build Coastguard Worker // While a test has a GDB debug port callback set, Chrome will allocate a 87*6777b538SAndroid Build Coastguard Worker // currently-unused TCP port to the debug stub server, instead of a fixed 88*6777b538SAndroid Build Coastguard Worker // one. 89*6777b538SAndroid Build Coastguard Worker static void SetGdbDebugStubPortListenerForTest( 90*6777b538SAndroid Build Coastguard Worker base::RepeatingCallback<void(int)> listener); 91*6777b538SAndroid Build Coastguard Worker static void ClearGdbDebugStubPortListenerForTest(); 92*6777b538SAndroid Build Coastguard Worker 93*6777b538SAndroid Build Coastguard Worker enum ValidationCacheStatus { 94*6777b538SAndroid Build Coastguard Worker CACHE_MISS = 0, 95*6777b538SAndroid Build Coastguard Worker CACHE_HIT, 96*6777b538SAndroid Build Coastguard Worker CACHE_MAX 97*6777b538SAndroid Build Coastguard Worker }; 98*6777b538SAndroid Build Coastguard Worker ValidationCacheIsEnabled()99*6777b538SAndroid Build Coastguard Worker bool ValidationCacheIsEnabled() const { 100*6777b538SAndroid Build Coastguard Worker return validation_cache_is_enabled_; 101*6777b538SAndroid Build Coastguard Worker } 102*6777b538SAndroid Build Coastguard Worker GetValidationCacheKey()103*6777b538SAndroid Build Coastguard Worker const std::string& GetValidationCacheKey() const { 104*6777b538SAndroid Build Coastguard Worker return validation_cache_.GetValidationCacheKey(); 105*6777b538SAndroid Build Coastguard Worker } 106*6777b538SAndroid Build Coastguard Worker 107*6777b538SAndroid Build Coastguard Worker // The instance keeps information about NaCl executable files opened via 108*6777b538SAndroid Build Coastguard Worker // PPAPI. This allows the NaCl process to get trusted information about the 109*6777b538SAndroid Build Coastguard Worker // file directly from the browser process. In theory, a compromised renderer 110*6777b538SAndroid Build Coastguard Worker // could provide a writable file handle or lie about the file's path. If we 111*6777b538SAndroid Build Coastguard Worker // trusted the handle was read only but it was not, an mmapped file could be 112*6777b538SAndroid Build Coastguard Worker // modified after validation, allowing an escape from the NaCl sandbox. 113*6777b538SAndroid Build Coastguard Worker // Similarly, if we trusted the file path corresponded to the file handle but 114*6777b538SAndroid Build Coastguard Worker // it did not, the validation cache could be tricked into bypassing validation 115*6777b538SAndroid Build Coastguard Worker // for bad code. 116*6777b538SAndroid Build Coastguard Worker // Instead of allowing these attacks, the NaCl process only trusts information 117*6777b538SAndroid Build Coastguard Worker // it gets directly from the browser process. Because the information is 118*6777b538SAndroid Build Coastguard Worker // stored in a cache of bounded size, it is not guaranteed the browser process 119*6777b538SAndroid Build Coastguard Worker // will be able to provide the requested information. In these cases, the 120*6777b538SAndroid Build Coastguard Worker // NaCl process must make conservative assumptions about the origin of the 121*6777b538SAndroid Build Coastguard Worker // file. 122*6777b538SAndroid Build Coastguard Worker // In theory, a compromised renderer could guess file tokens in an attempt to 123*6777b538SAndroid Build Coastguard Worker // read files it normally doesn't have access to. This would not compromise 124*6777b538SAndroid Build Coastguard Worker // the NaCl sandbox, however, and only has a 1 in ~2**120 chance of success 125*6777b538SAndroid Build Coastguard Worker // per guess. 126*6777b538SAndroid Build Coastguard Worker // TODO(ncbray): move the cache onto NaClProcessHost so that we don't need to 127*6777b538SAndroid Build Coastguard Worker // rely on tokens being unguessable by another process. 128*6777b538SAndroid Build Coastguard Worker void PutFilePath(const base::FilePath& path, 129*6777b538SAndroid Build Coastguard Worker uint64_t* file_token_lo, 130*6777b538SAndroid Build Coastguard Worker uint64_t* file_token_hi); 131*6777b538SAndroid Build Coastguard Worker bool GetFilePath(uint64_t file_token_lo, 132*6777b538SAndroid Build Coastguard Worker uint64_t file_token_hi, 133*6777b538SAndroid Build Coastguard Worker base::FilePath* path); 134*6777b538SAndroid Build Coastguard Worker 135*6777b538SAndroid Build Coastguard Worker bool QueryKnownToValidate(const std::string& signature, bool off_the_record); 136*6777b538SAndroid Build Coastguard Worker void SetKnownToValidate(const std::string& signature, bool off_the_record); 137*6777b538SAndroid Build Coastguard Worker void ClearValidationCache(base::OnceClosure callback); 138*6777b538SAndroid Build Coastguard Worker 139*6777b538SAndroid Build Coastguard Worker void EarlyStartup(); 140*6777b538SAndroid Build Coastguard Worker 141*6777b538SAndroid Build Coastguard Worker // Set/get the NaClBrowserDelegate. The |delegate| must be set at startup, 142*6777b538SAndroid Build Coastguard Worker // from the Browser's UI thread. It will be leaked at browser teardown. 143*6777b538SAndroid Build Coastguard Worker static void SetDelegate(std::unique_ptr<NaClBrowserDelegate> delegate); 144*6777b538SAndroid Build Coastguard Worker static NaClBrowserDelegate* GetDelegate(); 145*6777b538SAndroid Build Coastguard Worker static void ClearAndDeleteDelegate(); 146*6777b538SAndroid Build Coastguard Worker 147*6777b538SAndroid Build Coastguard Worker // Called whenever a NaCl process exits. 148*6777b538SAndroid Build Coastguard Worker void OnProcessEnd(int process_id); 149*6777b538SAndroid Build Coastguard Worker 150*6777b538SAndroid Build Coastguard Worker // Called whenever a NaCl process crashes, before OnProcessEnd(). 151*6777b538SAndroid Build Coastguard Worker void OnProcessCrashed(); 152*6777b538SAndroid Build Coastguard Worker 153*6777b538SAndroid Build Coastguard Worker // If "too many" crashes occur within a given time period, NaCl is throttled 154*6777b538SAndroid Build Coastguard Worker // until the rate again drops below the threshold. 155*6777b538SAndroid Build Coastguard Worker bool IsThrottled(); 156*6777b538SAndroid Build Coastguard Worker 157*6777b538SAndroid Build Coastguard Worker private: 158*6777b538SAndroid Build Coastguard Worker enum NaClResourceState { 159*6777b538SAndroid Build Coastguard Worker NaClResourceUninitialized, 160*6777b538SAndroid Build Coastguard Worker NaClResourceRequested, 161*6777b538SAndroid Build Coastguard Worker NaClResourceReady 162*6777b538SAndroid Build Coastguard Worker }; 163*6777b538SAndroid Build Coastguard Worker 164*6777b538SAndroid Build Coastguard Worker static NaClBrowser* GetInstanceInternal(); 165*6777b538SAndroid Build Coastguard Worker 166*6777b538SAndroid Build Coastguard Worker NaClBrowser(); 167*6777b538SAndroid Build Coastguard Worker ~NaClBrowser(); 168*6777b538SAndroid Build Coastguard Worker 169*6777b538SAndroid Build Coastguard Worker void InitIrtFilePath(); 170*6777b538SAndroid Build Coastguard Worker 171*6777b538SAndroid Build Coastguard Worker void OpenIrtLibraryFile(); 172*6777b538SAndroid Build Coastguard Worker 173*6777b538SAndroid Build Coastguard Worker void OnIrtOpened(std::unique_ptr<base::FileProxy> file_proxy, 174*6777b538SAndroid Build Coastguard Worker base::File::Error error_code); 175*6777b538SAndroid Build Coastguard Worker 176*6777b538SAndroid Build Coastguard Worker void InitValidationCacheFilePath(); 177*6777b538SAndroid Build Coastguard Worker void EnsureValidationCacheAvailable(); 178*6777b538SAndroid Build Coastguard Worker void OnValidationCacheLoaded(const std::string* data); 179*6777b538SAndroid Build Coastguard Worker void RunWithoutValidationCache(); 180*6777b538SAndroid Build Coastguard Worker 181*6777b538SAndroid Build Coastguard Worker // Dispatch waiting tasks if we are ready, or if we know we'll never be ready. 182*6777b538SAndroid Build Coastguard Worker void CheckWaiting(); 183*6777b538SAndroid Build Coastguard Worker 184*6777b538SAndroid Build Coastguard Worker // Indicate that it is impossible to launch a NaCl process. 185*6777b538SAndroid Build Coastguard Worker void MarkAsFailed(); 186*6777b538SAndroid Build Coastguard Worker 187*6777b538SAndroid Build Coastguard Worker void MarkValidationCacheAsModified(); 188*6777b538SAndroid Build Coastguard Worker void PersistValidationCache(); 189*6777b538SAndroid Build Coastguard Worker 190*6777b538SAndroid Build Coastguard Worker base::File irt_file_; 191*6777b538SAndroid Build Coastguard Worker base::FilePath irt_filepath_; 192*6777b538SAndroid Build Coastguard Worker NaClResourceState irt_state_ = NaClResourceUninitialized; 193*6777b538SAndroid Build Coastguard Worker NaClValidationCache validation_cache_; 194*6777b538SAndroid Build Coastguard Worker NaClValidationCache off_the_record_validation_cache_; 195*6777b538SAndroid Build Coastguard Worker base::FilePath validation_cache_file_path_; 196*6777b538SAndroid Build Coastguard Worker bool validation_cache_is_enabled_ = false; 197*6777b538SAndroid Build Coastguard Worker bool validation_cache_is_modified_ = false; 198*6777b538SAndroid Build Coastguard Worker NaClResourceState validation_cache_state_ = NaClResourceUninitialized; 199*6777b538SAndroid Build Coastguard Worker base::RepeatingCallback<void(int)> debug_stub_port_listener_; 200*6777b538SAndroid Build Coastguard Worker 201*6777b538SAndroid Build Coastguard Worker // Map from process id to debug stub port if any. 202*6777b538SAndroid Build Coastguard Worker typedef std::map<int, int> GdbDebugStubPortMap; 203*6777b538SAndroid Build Coastguard Worker GdbDebugStubPortMap gdb_debug_stub_port_map_; 204*6777b538SAndroid Build Coastguard Worker 205*6777b538SAndroid Build Coastguard Worker typedef base::HashingLRUCache<std::string, base::FilePath> PathCacheType; 206*6777b538SAndroid Build Coastguard Worker PathCacheType path_cache_{kFilePathCacheSize}; 207*6777b538SAndroid Build Coastguard Worker 208*6777b538SAndroid Build Coastguard Worker // True if it is no longer possible to launch NaCl processes. 209*6777b538SAndroid Build Coastguard Worker bool has_failed_ = false; 210*6777b538SAndroid Build Coastguard Worker 211*6777b538SAndroid Build Coastguard Worker // A list of pending tasks to start NaCl processes. 212*6777b538SAndroid Build Coastguard Worker std::vector<base::OnceClosure> waiting_; 213*6777b538SAndroid Build Coastguard Worker 214*6777b538SAndroid Build Coastguard Worker base::circular_deque<base::Time> crash_times_; 215*6777b538SAndroid Build Coastguard Worker 216*6777b538SAndroid Build Coastguard Worker scoped_refptr<base::SequencedTaskRunner> file_task_runner_ = 217*6777b538SAndroid Build Coastguard Worker base::ThreadPool::CreateSequencedTaskRunner( 218*6777b538SAndroid Build Coastguard Worker {base::MayBlock(), base::TaskPriority::USER_VISIBLE}); 219*6777b538SAndroid Build Coastguard Worker }; 220*6777b538SAndroid Build Coastguard Worker 221*6777b538SAndroid Build Coastguard Worker } // namespace nacl 222*6777b538SAndroid Build Coastguard Worker 223*6777b538SAndroid Build Coastguard Worker #endif // COMPONENTS_NACL_BROWSER_NACL_BROWSER_H_ 224