blob: 643f6f7beabf4077a3fe86e2d0b8187b23c5c93d [file] [log] [blame]
[email protected]6276b492013-11-02 13:38:311// 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#include "ppapi/proxy/nacl_message_scanner.h"
6
avie029c4132015-12-23 06:45:227#include <stddef.h>
8
dchengd2b9f612015-12-18 19:08:519#include <utility>
[email protected]6276b492013-11-02 13:38:3110#include <vector>
dchengd2b9f612015-12-18 19:08:5111
[email protected]6276b492013-11-02 13:38:3112#include "base/bind.h"
avie029c4132015-12-23 06:45:2213#include "build/build_config.h"
[email protected]6276b492013-11-02 13:38:3114#include "ipc/ipc_message.h"
15#include "ipc/ipc_message_macros.h"
16#include "ppapi/proxy/ppapi_messages.h"
17#include "ppapi/proxy/resource_message_params.h"
18#include "ppapi/proxy/serialized_handle.h"
19#include "ppapi/proxy/serialized_var.h"
20
21class NaClDescImcShm;
22
23namespace IPC {
24class Message;
25}
26
[email protected]7a90b852013-12-28 17:54:2727using ppapi::proxy::ResourceMessageReplyParams;
28using ppapi::proxy::SerializedHandle;
29using ppapi::proxy::SerializedVar;
30
[email protected]6276b492013-11-02 13:38:3131namespace {
32
[email protected]7a90b852013-12-28 17:54:2733typedef std::vector<SerializedHandle> Handles;
[email protected]6276b492013-11-02 13:38:3134
35struct ScanningResults {
[email protected]7a90b852013-12-28 17:54:2736 ScanningResults() : handle_index(0), pp_resource(0) {}
[email protected]6276b492013-11-02 13:38:3137
38 // Vector to hold handles found in the message.
39 Handles handles;
40 // Current handle index in the rewritten message. During the scan, it will be
41 // be less than or equal to handles.size(). After the scan it should be equal.
42 int handle_index;
43 // The rewritten message. This may be NULL, so all ScanParam overloads should
[email protected]e74d2d12013-11-02 16:17:3744 // check for NULL before writing to it. In some cases, a ScanParam overload
45 // may set this to NULL when it can determine that there are no parameters
46 // that need conversion. (See the ResourceMessageReplyParams overload.)
[email protected]6276b492013-11-02 13:38:3147 scoped_ptr<IPC::Message> new_msg;
[email protected]7a90b852013-12-28 17:54:2748 // Resource id for resource messages. Save this when scanning resource replies
49 // so when we audit the nested message, we know which resource it is for.
50 PP_Resource pp_resource;
51 // Callback to receive the nested message in a resource message or reply.
52 base::Callback<void(PP_Resource, const IPC::Message&, SerializedHandle*)>
53 nested_msg_callback;
[email protected]6276b492013-11-02 13:38:3154};
55
56void WriteHandle(int handle_index,
[email protected]7a90b852013-12-28 17:54:2757 const SerializedHandle& handle,
rockot502c94f2016-02-03 20:20:1658 base::Pickle* msg) {
[email protected]7a90b852013-12-28 17:54:2759 SerializedHandle::WriteHeader(handle.header(), msg);
[email protected]6276b492013-11-02 13:38:3160
Justin TerAvestcffdd032014-09-10 19:21:5661 if (handle.type() != SerializedHandle::INVALID) {
62 // Now write the handle itself in POSIX style.
63 // See ParamTraits<FileDescriptor>::Read for where these values are read.
64 msg->WriteBool(true); // valid == true
erikchenae6d3212015-10-10 02:43:4965 msg->WriteBool(false); // brokerable == false
Justin TerAvestcffdd032014-09-10 19:21:5666 msg->WriteInt(handle_index);
67 }
[email protected]6276b492013-11-02 13:38:3168}
69
70// Define overloads for each kind of message parameter that requires special
71// handling. See ScanTuple for how these get used.
72
73// Overload to match SerializedHandle.
[email protected]7a90b852013-12-28 17:54:2774void ScanParam(const SerializedHandle& handle, ScanningResults* results) {
[email protected]6276b492013-11-02 13:38:3175 results->handles.push_back(handle);
76 if (results->new_msg)
77 WriteHandle(results->handle_index++, handle, results->new_msg.get());
78}
79
80void HandleWriter(int* handle_index,
rockot502c94f2016-02-03 20:20:1681 base::Pickle* m,
[email protected]7a90b852013-12-28 17:54:2782 const SerializedHandle& handle) {
[email protected]6276b492013-11-02 13:38:3183 WriteHandle((*handle_index)++, handle, m);
84}
85
86// Overload to match SerializedVar, which can contain handles.
[email protected]7a90b852013-12-28 17:54:2787void ScanParam(const SerializedVar& var, ScanningResults* results) {
88 std::vector<SerializedHandle*> var_handles = var.GetHandles();
[email protected]e74d2d12013-11-02 16:17:3789 // Copy any handles and then rewrite the message.
[email protected]6276b492013-11-02 13:38:3190 for (size_t i = 0; i < var_handles.size(); ++i)
91 results->handles.push_back(*var_handles[i]);
92 if (results->new_msg)
93 var.WriteDataToMessage(results->new_msg.get(),
94 base::Bind(&HandleWriter, &results->handle_index));
95}
96
97// For PpapiMsg_ResourceReply and the reply to PpapiHostMsg_ResourceSyncCall,
98// the handles are carried inside the ResourceMessageReplyParams.
99// NOTE: We only intercept handles from host->NaCl. The only kind of
100// ResourceMessageParams that travels this direction is
101// ResourceMessageReplyParams, so that's the only one we need to handle.
[email protected]7a90b852013-12-28 17:54:27102void ScanParam(const ResourceMessageReplyParams& params,
[email protected]6276b492013-11-02 13:38:31103 ScanningResults* results) {
[email protected]7a90b852013-12-28 17:54:27104 results->pp_resource = params.pp_resource();
[email protected]e74d2d12013-11-02 16:17:37105 // If the resource reply params don't contain handles, NULL the new message
106 // pointer to cancel further rewriting.
107 // NOTE: This works because only handles currently need rewriting, and we
108 // know at this point that this message has none.
109 if (params.handles().empty()) {
110 results->new_msg.reset(NULL);
111 return;
112 }
113
[email protected]6276b492013-11-02 13:38:31114 // If we need to rewrite the message, write everything before the handles
115 // (there's nothing after the handles).
116 if (results->new_msg) {
117 params.WriteReplyHeader(results->new_msg.get());
118 // IPC writes the vector length as an int before the contents of the
119 // vector.
120 results->new_msg->WriteInt(static_cast<int>(params.handles().size()));
121 }
122 for (Handles::const_iterator iter = params.handles().begin();
123 iter != params.handles().end();
124 ++iter) {
125 // ScanParam will write each handle to the new message, if necessary.
126 ScanParam(*iter, results);
127 }
128 // Tell ResourceMessageReplyParams that we have taken the handles, so it
129 // shouldn't close them. The NaCl runtime will take ownership of them.
130 params.ConsumeHandles();
131}
132
[email protected]7a90b852013-12-28 17:54:27133// Overload to match nested messages. If we need to rewrite the message, write
134// the parameter.
135void ScanParam(const IPC::Message& param, ScanningResults* results) {
136 if (results->pp_resource && !results->nested_msg_callback.is_null()) {
137 SerializedHandle* handle = NULL;
138 if (results->handles.size() == 1)
139 handle = &results->handles[0];
140 results->nested_msg_callback.Run(results->pp_resource, param, handle);
141 }
142 if (results->new_msg)
143 IPC::WriteParam(results->new_msg.get(), param);
144}
145
mseaborn3bedcdc2016-01-04 21:14:13146template <class T>
147void ScanParam(const std::vector<T>& vec, ScanningResults* results) {
148 if (results->new_msg)
149 IPC::WriteParam(results->new_msg.get(), static_cast<int>(vec.size()));
150 for (const T& element : vec) {
151 ScanParam(element, results);
152 }
153}
154
[email protected]7a90b852013-12-28 17:54:27155// Overload to match all other types. If we need to rewrite the message, write
156// the parameter.
[email protected]6276b492013-11-02 13:38:31157template <class T>
158void ScanParam(const T& param, ScanningResults* results) {
159 if (results->new_msg)
160 IPC::WriteParam(results->new_msg.get(), param);
161}
162
163// These just break apart the given tuple and run ScanParam over each param.
164// The idea is to scan elements in the tuple which require special handling,
165// and write them into the |results| struct.
166template <class A>
brettwd5ca2bc2015-05-29 22:15:47167void ScanTuple(const base::Tuple<A>& t1, ScanningResults* results) {
168 ScanParam(base::get<0>(t1), results);
[email protected]6276b492013-11-02 13:38:31169}
170template <class A, class B>
brettwd5ca2bc2015-05-29 22:15:47171void ScanTuple(const base::Tuple<A, B>& t1, ScanningResults* results) {
172 ScanParam(base::get<0>(t1), results);
173 ScanParam(base::get<1>(t1), results);
[email protected]6276b492013-11-02 13:38:31174}
175template <class A, class B, class C>
brettwd5ca2bc2015-05-29 22:15:47176void ScanTuple(const base::Tuple<A, B, C>& t1, ScanningResults* results) {
177 ScanParam(base::get<0>(t1), results);
178 ScanParam(base::get<1>(t1), results);
179 ScanParam(base::get<2>(t1), results);
[email protected]6276b492013-11-02 13:38:31180}
181template <class A, class B, class C, class D>
brettwd5ca2bc2015-05-29 22:15:47182void ScanTuple(const base::Tuple<A, B, C, D>& t1, ScanningResults* results) {
183 ScanParam(base::get<0>(t1), results);
184 ScanParam(base::get<1>(t1), results);
185 ScanParam(base::get<2>(t1), results);
186 ScanParam(base::get<3>(t1), results);
[email protected]6276b492013-11-02 13:38:31187}
188
189template <class MessageType>
190class MessageScannerImpl {
191 public:
192 explicit MessageScannerImpl(const IPC::Message* msg)
krasin86a5a182016-02-23 09:59:09193 // The cast below is invalid. See https://crbug.com/520760.
[email protected]6276b492013-11-02 13:38:31194 : msg_(static_cast<const MessageType*>(msg)) {
195 }
196 bool ScanMessage(ScanningResults* results) {
brettwd5ca2bc2015-05-29 22:15:47197 typename base::TupleTypes<typename MessageType::Schema::Param>::ValueTuple
198 params;
[email protected]6276b492013-11-02 13:38:31199 if (!MessageType::Read(msg_, &params))
200 return false;
201 ScanTuple(params, results);
202 return true;
203 }
204
mseaborn3bedcdc2016-01-04 21:14:13205 bool ScanSyncMessage(ScanningResults* results) {
206 typename base::TupleTypes<typename MessageType::Schema::SendParam>
207 ::ValueTuple params;
208 if (!MessageType::ReadSendParam(msg_, &params))
209 return false;
210 // If we need to rewrite the message, write the message id first.
211 if (results->new_msg) {
212 results->new_msg->set_sync();
213 int id = IPC::SyncMessage::GetMessageId(*msg_);
214 results->new_msg->WriteInt(id);
215 }
216 ScanTuple(params, results);
217 return true;
218 }
219
[email protected]6276b492013-11-02 13:38:31220 bool ScanReply(ScanningResults* results) {
brettwd5ca2bc2015-05-29 22:15:47221 typename base::TupleTypes<typename MessageType::Schema::ReplyParam>
222 ::ValueTuple params;
[email protected]6276b492013-11-02 13:38:31223 if (!MessageType::ReadReplyParam(msg_, &params))
224 return false;
225 // If we need to rewrite the message, write the message id first.
226 if (results->new_msg) {
227 results->new_msg->set_reply();
228 int id = IPC::SyncMessage::GetMessageId(*msg_);
229 results->new_msg->WriteInt(id);
230 }
231 ScanTuple(params, results);
232 return true;
233 }
[email protected]6276b492013-11-02 13:38:31234
235 private:
236 const MessageType* msg_;
237};
238
239} // namespace
240
241#define CASE_FOR_MESSAGE(MESSAGE_TYPE) \
242 case MESSAGE_TYPE::ID: { \
243 MessageScannerImpl<MESSAGE_TYPE> scanner(&msg); \
244 if (rewrite_msg) \
245 results.new_msg.reset( \
[email protected]753bb252013-11-04 22:28:12246 new IPC::Message(msg.routing_id(), msg.type(), \
247 IPC::Message::PRIORITY_NORMAL)); \
[email protected]6276b492013-11-02 13:38:31248 if (!scanner.ScanMessage(&results)) \
249 return false; \
250 break; \
251 }
mseaborn3bedcdc2016-01-04 21:14:13252#define CASE_FOR_SYNC_MESSAGE(MESSAGE_TYPE) \
253 case MESSAGE_TYPE::ID: { \
254 MessageScannerImpl<MESSAGE_TYPE> scanner(&msg); \
255 if (rewrite_msg) \
256 results.new_msg.reset( \
257 new IPC::Message(msg.routing_id(), msg.type(), \
258 IPC::Message::PRIORITY_NORMAL)); \
259 if (!scanner.ScanSyncMessage(&results)) \
260 return false; \
261 break; \
262 }
[email protected]6276b492013-11-02 13:38:31263#define CASE_FOR_REPLY(MESSAGE_TYPE) \
264 case MESSAGE_TYPE::ID: { \
265 MessageScannerImpl<MESSAGE_TYPE> scanner(&msg); \
266 if (rewrite_msg) \
267 results.new_msg.reset( \
[email protected]753bb252013-11-04 22:28:12268 new IPC::Message(msg.routing_id(), msg.type(), \
269 IPC::Message::PRIORITY_NORMAL)); \
[email protected]6276b492013-11-02 13:38:31270 if (!scanner.ScanReply(&results)) \
271 return false; \
272 break; \
273 }
274
275namespace ppapi {
276namespace proxy {
277
278class SerializedHandle;
279
[email protected]7a90b852013-12-28 17:54:27280NaClMessageScanner::FileSystem::FileSystem()
281 : reserved_quota_(0) {
282}
283
284NaClMessageScanner::FileSystem::~FileSystem() {
285}
286
287bool NaClMessageScanner::FileSystem::UpdateReservedQuota(int64_t delta) {
288 base::AutoLock lock(lock_);
289 if (std::numeric_limits<int64_t>::max() - reserved_quota_ < delta)
290 return false; // reserved_quota_ + delta would overflow.
291 if (reserved_quota_ + delta < 0)
292 return false;
293 reserved_quota_ += delta;
294 return true;
295}
296
297NaClMessageScanner::FileIO::FileIO(FileSystem* file_system,
298 int64_t max_written_offset)
299 : file_system_(file_system),
300 max_written_offset_(max_written_offset) {
301}
302
303NaClMessageScanner::FileIO::~FileIO() {
304}
305
306void NaClMessageScanner::FileIO::SetMaxWrittenOffset(
307 int64_t max_written_offset) {
308 base::AutoLock lock(lock_);
309 max_written_offset_ = max_written_offset;
310}
311
312bool NaClMessageScanner::FileIO::Grow(int64_t amount) {
313 base::AutoLock lock(lock_);
314 DCHECK(amount > 0);
315 if (!file_system_->UpdateReservedQuota(-amount))
316 return false;
317 max_written_offset_ += amount;
318 return true;
319}
320
[email protected]6276b492013-11-02 13:38:31321NaClMessageScanner::NaClMessageScanner() {
322}
323
[email protected]7a90b852013-12-28 17:54:27324NaClMessageScanner::~NaClMessageScanner() {
325 for (FileSystemMap::iterator it = file_systems_.begin();
326 it != file_systems_.end(); ++it)
327 delete it->second;
328 for (FileIOMap::iterator it = files_.begin(); it != files_.end(); ++it)
329 delete it->second;
330}
331
[email protected]6276b492013-11-02 13:38:31332// Windows IPC differs from POSIX in that native handles are serialized in the
333// message body, rather than passed in a separate FileDescriptorSet. Therefore,
334// on Windows, any message containing handles must be rewritten in the POSIX
335// format before we can send it to the NaCl plugin.
scottmgd19b4f72015-06-19 22:51:00336// On Mac, base::SharedMemoryHandle has a different serialization than
337// base::FileDescriptor (which base::SharedMemoryHandle is typedef-ed to in
338// OS_NACL).
[email protected]6276b492013-11-02 13:38:31339bool NaClMessageScanner::ScanMessage(
340 const IPC::Message& msg,
[email protected]c8f326a2014-08-21 23:19:07341 uint32_t type,
[email protected]6276b492013-11-02 13:38:31342 std::vector<SerializedHandle>* handles,
343 scoped_ptr<IPC::Message>* new_msg_ptr) {
344 DCHECK(handles);
345 DCHECK(handles->empty());
346 DCHECK(new_msg_ptr);
347 DCHECK(!new_msg_ptr->get());
348
349 bool rewrite_msg =
scottmgd19b4f72015-06-19 22:51:00350#if defined(OS_WIN) || defined(OS_MACOSX)
[email protected]6276b492013-11-02 13:38:31351 true;
352#else
[email protected]73af6332014-02-06 23:28:10353 false;
[email protected]6276b492013-11-02 13:38:31354#endif
355
356 // We can't always tell from the message ID if rewriting is needed. Therefore,
[email protected]e74d2d12013-11-02 16:17:37357 // scan any message types that might contain a handle. If we later determine
358 // that there are no handles, we can cancel the rewriting by clearing the
359 // results.new_msg pointer.
[email protected]6276b492013-11-02 13:38:31360 ScanningResults results;
[email protected]7a90b852013-12-28 17:54:27361 results.nested_msg_callback =
362 base::Bind(&NaClMessageScanner::AuditNestedMessage,
363 base::Unretained(this));
[email protected]c8f326a2014-08-21 23:19:07364 switch (type) {
[email protected]6276b492013-11-02 13:38:31365 CASE_FOR_MESSAGE(PpapiMsg_PPBAudio_NotifyAudioStreamCreated)
366 CASE_FOR_MESSAGE(PpapiMsg_PPPMessaging_HandleMessage)
367 CASE_FOR_MESSAGE(PpapiPluginMsg_ResourceReply)
dmichael822ba8f2016-01-11 17:54:52368 CASE_FOR_SYNC_MESSAGE(PpapiMsg_PPPMessageHandler_HandleBlockingMessage)
mseaborn98d206ca2016-01-08 11:43:28369 CASE_FOR_SYNC_MESSAGE(PpapiMsg_PnaclTranslatorCompileInit)
mseaborn3bedcdc2016-01-04 21:14:13370 CASE_FOR_SYNC_MESSAGE(PpapiMsg_PnaclTranslatorLink)
Justin TerAvestcffdd032014-09-10 19:21:56371 CASE_FOR_REPLY(PpapiHostMsg_OpenResource)
penghuanga206fb492014-09-09 21:27:32372 CASE_FOR_REPLY(PpapiHostMsg_PPBGraphics3D_Create)
[email protected]c8f326a2014-08-21 23:19:07373 CASE_FOR_REPLY(PpapiHostMsg_PPBGraphics3D_CreateTransferBuffer)
374 CASE_FOR_REPLY(PpapiHostMsg_PPBImageData_CreateSimple)
375 CASE_FOR_REPLY(PpapiHostMsg_ResourceSyncCall)
376 CASE_FOR_REPLY(PpapiHostMsg_SharedMemory_CreateSharedMemory)
[email protected]6276b492013-11-02 13:38:31377 default:
378 // Do nothing for messages we don't know.
379 break;
380 }
381
382 // Only messages containing handles need to be rewritten. If no handles are
383 // found, don't return the rewritten message either. This must be changed if
384 // we ever add new param types that also require rewriting.
385 if (!results.handles.empty()) {
386 handles->swap(results.handles);
dchengd2b9f612015-12-18 19:08:51387 *new_msg_ptr = std::move(results.new_msg);
[email protected]6276b492013-11-02 13:38:31388 }
389 return true;
390}
391
[email protected]c586216c2013-12-18 21:59:17392void NaClMessageScanner::ScanUntrustedMessage(
393 const IPC::Message& untrusted_msg,
394 scoped_ptr<IPC::Message>* new_msg_ptr) {
[email protected]7a90b852013-12-28 17:54:27395 // Audit FileIO and FileSystem messages to ensure that the plugin doesn't
396 // exceed its file quota. If we find the message is malformed, just pass it
397 // through - we only care about well formed messages to the host.
398 if (untrusted_msg.type() == PpapiHostMsg_ResourceCall::ID) {
399 ResourceMessageCallParams params;
400 IPC::Message nested_msg;
401 if (!UnpackMessage<PpapiHostMsg_ResourceCall>(
402 untrusted_msg, &params, &nested_msg))
403 return;
404
405 switch (nested_msg.type()) {
406 case PpapiHostMsg_FileIO_Close::ID: {
407 FileIOMap::iterator it = files_.find(params.pp_resource());
408 if (it == files_.end())
409 return;
410 // Audit FileIO Close messages to make sure the plugin reports an
411 // accurate file size.
[email protected]540d6af42014-01-28 21:19:03412 FileGrowth file_growth;
[email protected]7a90b852013-12-28 17:54:27413 if (!UnpackMessage<PpapiHostMsg_FileIO_Close>(
[email protected]540d6af42014-01-28 21:19:03414 nested_msg, &file_growth))
[email protected]7a90b852013-12-28 17:54:27415 return;
416
417 int64_t trusted_max_written_offset = it->second->max_written_offset();
418 delete it->second;
419 files_.erase(it);
420 // If the plugin is under-reporting, rewrite the message with the
421 // trusted value.
[email protected]540d6af42014-01-28 21:19:03422 if (trusted_max_written_offset > file_growth.max_written_offset) {
[email protected]7a90b852013-12-28 17:54:27423 new_msg_ptr->reset(
424 new PpapiHostMsg_ResourceCall(
425 params,
[email protected]540d6af42014-01-28 21:19:03426 PpapiHostMsg_FileIO_Close(
427 FileGrowth(trusted_max_written_offset, 0))));
[email protected]7a90b852013-12-28 17:54:27428 }
[email protected]2d585cbd2014-06-03 02:13:22429 break;
[email protected]7a90b852013-12-28 17:54:27430 }
431 case PpapiHostMsg_FileIO_SetLength::ID: {
432 FileIOMap::iterator it = files_.find(params.pp_resource());
433 if (it == files_.end())
434 return;
435 // Audit FileIO SetLength messages to make sure the plugin is within
436 // the current quota reservation. In addition, deduct the file size
437 // increase from the quota reservation.
438 int64_t length = 0;
439 if (!UnpackMessage<PpapiHostMsg_FileIO_SetLength>(
440 nested_msg, &length))
441 return;
442
443 // Calculate file size increase, taking care to avoid overflows.
444 if (length < 0)
445 return;
446 int64_t trusted_max_written_offset = it->second->max_written_offset();
447 int64_t increase = length - trusted_max_written_offset;
448 if (increase <= 0)
449 return;
450 if (!it->second->Grow(increase)) {
451 new_msg_ptr->reset(
452 new PpapiHostMsg_ResourceCall(
453 params,
454 PpapiHostMsg_FileIO_SetLength(-1)));
455 }
456 break;
457 }
458 case PpapiHostMsg_FileSystem_ReserveQuota::ID: {
459 // Audit FileSystem ReserveQuota messages to make sure the plugin
460 // reports accurate file sizes.
461 int64_t amount = 0;
[email protected]540d6af42014-01-28 21:19:03462 FileGrowthMap file_growths;
[email protected]7a90b852013-12-28 17:54:27463 if (!UnpackMessage<PpapiHostMsg_FileSystem_ReserveQuota>(
[email protected]540d6af42014-01-28 21:19:03464 nested_msg, &amount, &file_growths))
[email protected]7a90b852013-12-28 17:54:27465 return;
466
467 bool audit_failed = false;
[email protected]540d6af42014-01-28 21:19:03468 for (FileGrowthMap::iterator it = file_growths.begin();
469 it != file_growths.end(); ++it) {
[email protected]7a90b852013-12-28 17:54:27470 FileIOMap::iterator file_it = files_.find(it->first);
471 if (file_it == files_.end())
472 continue;
473 int64_t trusted_max_written_offset =
474 file_it->second->max_written_offset();
[email protected]540d6af42014-01-28 21:19:03475 if (trusted_max_written_offset > it->second.max_written_offset) {
[email protected]7a90b852013-12-28 17:54:27476 audit_failed = true;
[email protected]540d6af42014-01-28 21:19:03477 it->second.max_written_offset = trusted_max_written_offset;
478 }
479 if (it->second.append_mode_write_amount < 0) {
480 audit_failed = true;
481 it->second.append_mode_write_amount = 0;
[email protected]7a90b852013-12-28 17:54:27482 }
483 }
484 if (audit_failed) {
485 new_msg_ptr->reset(
486 new PpapiHostMsg_ResourceCall(
487 params,
488 PpapiHostMsg_FileSystem_ReserveQuota(
[email protected]540d6af42014-01-28 21:19:03489 amount, file_growths)));
[email protected]7a90b852013-12-28 17:54:27490 }
491 break;
492 }
493 case PpapiHostMsg_ResourceDestroyed::ID: {
494 // Audit resource destroyed messages to release FileSystems.
495 PP_Resource resource;
496 if (!UnpackMessage<PpapiHostMsg_ResourceDestroyed>(
497 nested_msg, &resource))
498 return;
499 FileSystemMap::iterator fs_it = file_systems_.find(resource);
500 if (fs_it != file_systems_.end()) {
501 delete fs_it->second;
502 file_systems_.erase(fs_it);
503 }
[email protected]2d585cbd2014-06-03 02:13:22504 break;
[email protected]7a90b852013-12-28 17:54:27505 }
506 }
507 }
[email protected]c586216c2013-12-18 21:59:17508}
[email protected]6276b492013-11-02 13:38:31509
[email protected]7a90b852013-12-28 17:54:27510NaClMessageScanner::FileIO* NaClMessageScanner::GetFile(
511 PP_Resource file_io) {
512 FileIOMap::iterator it = files_.find(file_io);
513 DCHECK(it != files_.end());
514 return it->second;
515}
516
517void NaClMessageScanner::AuditNestedMessage(PP_Resource resource,
518 const IPC::Message& msg,
519 SerializedHandle* handle) {
520 switch (msg.type()) {
521 case PpapiPluginMsg_FileIO_OpenReply::ID: {
522 // A file that requires quota checking was opened.
523 PP_Resource quota_file_system;
524 int64_t max_written_offset = 0;
525 if (ppapi::UnpackMessage<PpapiPluginMsg_FileIO_OpenReply>(
526 msg, &quota_file_system, &max_written_offset)) {
527 if (quota_file_system) {
528 // Look up the FileSystem by inserting a new one. If it was already
529 // present, get the existing one, otherwise construct it.
530 FileSystem* file_system = NULL;
531 std::pair<FileSystemMap::iterator, bool> insert_result =
532 file_systems_.insert(std::make_pair(quota_file_system,
533 file_system));
534 if (insert_result.second)
535 insert_result.first->second = new FileSystem();
536 file_system = insert_result.first->second;
537 // Create the FileIO.
538 DCHECK(files_.find(resource) == files_.end());
539 files_.insert(std::make_pair(
540 resource,
541 new FileIO(file_system, max_written_offset)));
542 }
543 }
544 break;
545 }
546 case PpapiPluginMsg_FileSystem_ReserveQuotaReply::ID: {
547 // The amount of reserved quota for a FileSystem was refreshed.
548 int64_t amount = 0;
[email protected]540d6af42014-01-28 21:19:03549 FileSizeMap file_sizes;
[email protected]7a90b852013-12-28 17:54:27550 if (ppapi::UnpackMessage<PpapiPluginMsg_FileSystem_ReserveQuotaReply>(
[email protected]540d6af42014-01-28 21:19:03551 msg, &amount, &file_sizes)) {
[email protected]7a90b852013-12-28 17:54:27552 FileSystemMap::iterator it = file_systems_.find(resource);
553 DCHECK(it != file_systems_.end());
554 it->second->UpdateReservedQuota(amount);
555
[email protected]540d6af42014-01-28 21:19:03556 FileSizeMap::const_iterator offset_it = file_sizes.begin();
557 for (; offset_it != file_sizes.end(); ++offset_it) {
[email protected]7a90b852013-12-28 17:54:27558 FileIOMap::iterator fio_it = files_.find(offset_it->first);
559 DCHECK(fio_it != files_.end());
560 if (fio_it != files_.end())
561 fio_it->second->SetMaxWrittenOffset(offset_it->second);
562 }
563 }
564 break;
565 }
566 }
567}
568
[email protected]6276b492013-11-02 13:38:31569} // namespace proxy
570} // namespace ppapi