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