xref: /aosp_15_r20/external/cronet/components/nacl/browser/nacl_browser.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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