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