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_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 
     70   bool ValidationCacheIsEnabled() const {
     71     return validation_cache_is_enabled_;
     72   }
     73 
     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