• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
ValidationCacheIsEnabled()70   bool ValidationCacheIsEnabled() const {
71     return validation_cache_is_enabled_;
72   }
73 
GetValidationCacheKey()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