blob: 8c31b831664a1555d6714c68757742f1b0c95bde [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
tzika0f614d2016-03-08 00:35:159#include <tuple>
dchengd2b9f612015-12-18 19:08:5110#include <utility>
[email protected]6276b492013-11-02 13:38:3111#include <vector>
dchengd2b9f612015-12-18 19:08:5112
[email protected]6276b492013-11-02 13:38:3113#include "base/bind.h"
avie029c4132015-12-23 06:45:2214#include "build/build_config.h"
[email protected]6276b492013-11-02 13:38:3115#include "ipc/ipc_message.h"
16#include "ipc/ipc_message_macros.h"
17#include "ppapi/proxy/ppapi_messages.h"
18#include "ppapi/proxy/resource_message_params.h"
19#include "ppapi/proxy/serialized_handle.h"
20#include "ppapi/proxy/serialized_var.h"
21
22class NaClDescImcShm;
23
24namespace IPC {
25class Message;
26}
27
[email protected]7a90b852013-12-28 17:54:2728using ppapi::proxy::ResourceMessageReplyParams;
29using ppapi::proxy::SerializedHandle;
30using ppapi::proxy::SerializedVar;
31
[email protected]6276b492013-11-02 13:38:3132namespace {
33
[email protected]7a90b852013-12-28 17:54:2734typedef std::vector<SerializedHandle> Handles;
[email protected]6276b492013-11-02 13:38:3135
36struct ScanningResults {
[email protected]7a90b852013-12-28 17:54:2737 ScanningResults() : handle_index(0), pp_resource(0) {}
[email protected]6276b492013-11-02 13:38:3138
39 // Vector to hold handles found in the message.
40 Handles handles;
41 // Current handle index in the rewritten message. During the scan, it will be
42 // be less than or equal to handles.size(). After the scan it should be equal.
43 int handle_index;
44 // The rewritten message. This may be NULL, so all ScanParam overloads should
[email protected]e74d2d12013-11-02 16:17:3745 // check for NULL before writing to it. In some cases, a ScanParam overload
46 // may set this to NULL when it can determine that there are no parameters
47 // that need conversion. (See the ResourceMessageReplyParams overload.)
dchengced92242016-04-07 00:00:1248 std::unique_ptr<IPC::Message> new_msg;
[email protected]7a90b852013-12-28 17:54:2749 // Resource id for resource messages. Save this when scanning resource replies
50 // so when we audit the nested message, we know which resource it is for.
51 PP_Resource pp_resource;
52 // Callback to receive the nested message in a resource message or reply.
53 base::Callback<void(PP_Resource, const IPC::Message&, SerializedHandle*)>
54 nested_msg_callback;
[email protected]6276b492013-11-02 13:38:3155};
56
57void WriteHandle(int handle_index,
[email protected]7a90b852013-12-28 17:54:2758 const SerializedHandle& handle,
rockot502c94f2016-02-03 20:20:1659 base::Pickle* msg) {
[email protected]7a90b852013-12-28 17:54:2760 SerializedHandle::WriteHeader(handle.header(), msg);
[email protected]6276b492013-11-02 13:38:3161
erikchen14525202017-05-06 19:16:5162 if (handle.type() == SerializedHandle::SHARED_MEMORY) {
Justin TerAvestcffdd032014-09-10 19:21:5663 // Now write the handle itself in POSIX style.
erikchen14525202017-05-06 19:16:5164 // This serialization must be kept in sync with
65 // ParamTraits<SharedMemoryHandle>::Write and
66 // ParamTraits<UnguessableToken>::Write.
67 if (handle.shmem().IsValid()) {
68 msg->WriteBool(true); // valid == true
69 msg->WriteInt(handle_index);
70 msg->WriteUInt64(handle.shmem().GetGUID().GetHighForSerialization());
71 msg->WriteUInt64(handle.shmem().GetGUID().GetLowForSerialization());
erikchen9d6afd712017-05-18 17:49:0672 msg->WriteUInt64(handle.shmem().GetSize());
erikchen14525202017-05-06 19:16:5173 } else {
74 msg->WriteBool(false); // valid == false
75 }
76 } else if (handle.type() != SerializedHandle::INVALID) {
77 // Now write the handle itself in POSIX style.
78 // This serialization must be kept in sync with
79 // ParamTraits<FileDescriptor>::Write.
Justin TerAvestcffdd032014-09-10 19:21:5680 msg->WriteBool(true); // valid == true
81 msg->WriteInt(handle_index);
82 }
[email protected]6276b492013-11-02 13:38:3183}
84
85// Define overloads for each kind of message parameter that requires special
86// handling. See ScanTuple for how these get used.
87
88// Overload to match SerializedHandle.
[email protected]7a90b852013-12-28 17:54:2789void ScanParam(const SerializedHandle& handle, ScanningResults* results) {
[email protected]6276b492013-11-02 13:38:3190 results->handles.push_back(handle);
91 if (results->new_msg)
92 WriteHandle(results->handle_index++, handle, results->new_msg.get());
93}
94
95void HandleWriter(int* handle_index,
rockot502c94f2016-02-03 20:20:1696 base::Pickle* m,
[email protected]7a90b852013-12-28 17:54:2797 const SerializedHandle& handle) {
[email protected]6276b492013-11-02 13:38:3198 WriteHandle((*handle_index)++, handle, m);
99}
100
101// Overload to match SerializedVar, which can contain handles.
[email protected]7a90b852013-12-28 17:54:27102void ScanParam(const SerializedVar& var, ScanningResults* results) {
103 std::vector<SerializedHandle*> var_handles = var.GetHandles();
[email protected]e74d2d12013-11-02 16:17:37104 // Copy any handles and then rewrite the message.
[email protected]6276b492013-11-02 13:38:31105 for (size_t i = 0; i < var_handles.size(); ++i)
106 results->handles.push_back(*var_handles[i]);
107 if (results->new_msg)
108 var.WriteDataToMessage(results->new_msg.get(),
109 base::Bind(&HandleWriter, &results->handle_index));
110}
111
112// For PpapiMsg_ResourceReply and the reply to PpapiHostMsg_ResourceSyncCall,
113// the handles are carried inside the ResourceMessageReplyParams.
114// NOTE: We only intercept handles from host->NaCl. The only kind of
115// ResourceMessageParams that travels this direction is
116// ResourceMessageReplyParams, so that's the only one we need to handle.
[email protected]7a90b852013-12-28 17:54:27117void ScanParam(const ResourceMessageReplyParams& params,
[email protected]6276b492013-11-02 13:38:31118 ScanningResults* results) {
[email protected]7a90b852013-12-28 17:54:27119 results->pp_resource = params.pp_resource();
[email protected]e74d2d12013-11-02 16:17:37120 // If the resource reply params don't contain handles, NULL the new message
121 // pointer to cancel further rewriting.
122 // NOTE: This works because only handles currently need rewriting, and we
123 // know at this point that this message has none.
124 if (params.handles().empty()) {
125 results->new_msg.reset(NULL);
126 return;
127 }
128
[email protected]6276b492013-11-02 13:38:31129 // If we need to rewrite the message, write everything before the handles
130 // (there's nothing after the handles).
131 if (results->new_msg) {
132 params.WriteReplyHeader(results->new_msg.get());
133 // IPC writes the vector length as an int before the contents of the
134 // vector.
135 results->new_msg->WriteInt(static_cast<int>(params.handles().size()));
136 }
137 for (Handles::const_iterator iter = params.handles().begin();
138 iter != params.handles().end();
139 ++iter) {
140 // ScanParam will write each handle to the new message, if necessary.
141 ScanParam(*iter, results);
142 }
143 // Tell ResourceMessageReplyParams that we have taken the handles, so it
144 // shouldn't close them. The NaCl runtime will take ownership of them.
145 params.ConsumeHandles();
146}
147
[email protected]7a90b852013-12-28 17:54:27148// Overload to match nested messages. If we need to rewrite the message, write
149// the parameter.
150void ScanParam(const IPC::Message& param, ScanningResults* results) {
151 if (results->pp_resource && !results->nested_msg_callback.is_null()) {
152 SerializedHandle* handle = NULL;
153 if (results->handles.size() == 1)
154 handle = &results->handles[0];
155 results->nested_msg_callback.Run(results->pp_resource, param, handle);
156 }
157 if (results->new_msg)
158 IPC::WriteParam(results->new_msg.get(), param);
159}
160
mseaborn3bedcdc2016-01-04 21:14:13161template <class T>
162void ScanParam(const std::vector<T>& vec, ScanningResults* results) {
163 if (results->new_msg)
164 IPC::WriteParam(results->new_msg.get(), static_cast<int>(vec.size()));
165 for (const T& element : vec) {
166 ScanParam(element, results);
167 }
168}
169
[email protected]7a90b852013-12-28 17:54:27170// Overload to match all other types. If we need to rewrite the message, write
171// the parameter.
[email protected]6276b492013-11-02 13:38:31172template <class T>
173void ScanParam(const T& param, ScanningResults* results) {
174 if (results->new_msg)
175 IPC::WriteParam(results->new_msg.get(), param);
176}
177
178// These just break apart the given tuple and run ScanParam over each param.
179// The idea is to scan elements in the tuple which require special handling,
180// and write them into the |results| struct.
181template <class A>
tzika0f614d2016-03-08 00:35:15182void ScanTuple(const std::tuple<A>& t1, ScanningResults* results) {
183 ScanParam(std::get<0>(t1), results);
[email protected]6276b492013-11-02 13:38:31184}
185template <class A, class B>
tzika0f614d2016-03-08 00:35:15186void ScanTuple(const std::tuple<A, B>& t1, ScanningResults* results) {
187 ScanParam(std::get<0>(t1), results);
188 ScanParam(std::get<1>(t1), results);
[email protected]6276b492013-11-02 13:38:31189}
190template <class A, class B, class C>
tzika0f614d2016-03-08 00:35:15191void ScanTuple(const std::tuple<A, B, C>& t1, ScanningResults* results) {
192 ScanParam(std::get<0>(t1), results);
193 ScanParam(std::get<1>(t1), results);
194 ScanParam(std::get<2>(t1), results);
[email protected]6276b492013-11-02 13:38:31195}
196template <class A, class B, class C, class D>
tzika0f614d2016-03-08 00:35:15197void ScanTuple(const std::tuple<A, B, C, D>& t1, ScanningResults* results) {
198 ScanParam(std::get<0>(t1), results);
199 ScanParam(std::get<1>(t1), results);
200 ScanParam(std::get<2>(t1), results);
201 ScanParam(std::get<3>(t1), results);
[email protected]6276b492013-11-02 13:38:31202}
203
204template <class MessageType>
205class MessageScannerImpl {
206 public:
207 explicit MessageScannerImpl(const IPC::Message* msg)
krasin86a5a182016-02-23 09:59:09208 // The cast below is invalid. See https://crbug.com/520760.
[email protected]6276b492013-11-02 13:38:31209 : msg_(static_cast<const MessageType*>(msg)) {
210 }
211 bool ScanMessage(ScanningResults* results) {
mdempsky390ab1e2016-03-07 22:18:35212 typename MessageType::Param params;
[email protected]6276b492013-11-02 13:38:31213 if (!MessageType::Read(msg_, &params))
214 return false;
215 ScanTuple(params, results);
216 return true;
217 }
218
mseaborn3bedcdc2016-01-04 21:14:13219 bool ScanSyncMessage(ScanningResults* results) {
mdempsky390ab1e2016-03-07 22:18:35220 typename MessageType::SendParam params;
mseaborn3bedcdc2016-01-04 21:14:13221 if (!MessageType::ReadSendParam(msg_, &params))
222 return false;
223 // If we need to rewrite the message, write the message id first.
224 if (results->new_msg) {
225 results->new_msg->set_sync();
226 int id = IPC::SyncMessage::GetMessageId(*msg_);
227 results->new_msg->WriteInt(id);
228 }
229 ScanTuple(params, results);
230 return true;
231 }
232
[email protected]6276b492013-11-02 13:38:31233 bool ScanReply(ScanningResults* results) {
mdempsky390ab1e2016-03-07 22:18:35234 typename MessageType::ReplyParam params;
[email protected]6276b492013-11-02 13:38:31235 if (!MessageType::ReadReplyParam(msg_, &params))
236 return false;
237 // If we need to rewrite the message, write the message id first.
238 if (results->new_msg) {
239 results->new_msg->set_reply();
240 int id = IPC::SyncMessage::GetMessageId(*msg_);
241 results->new_msg->WriteInt(id);
242 }
243 ScanTuple(params, results);
244 return true;
245 }
[email protected]6276b492013-11-02 13:38:31246
247 private:
248 const MessageType* msg_;
249};
250
251} // namespace
252
253#define CASE_FOR_MESSAGE(MESSAGE_TYPE) \
254 case MESSAGE_TYPE::ID: { \
255 MessageScannerImpl<MESSAGE_TYPE> scanner(&msg); \
256 if (rewrite_msg) \
257 results.new_msg.reset( \
[email protected]753bb252013-11-04 22:28:12258 new IPC::Message(msg.routing_id(), msg.type(), \
259 IPC::Message::PRIORITY_NORMAL)); \
[email protected]6276b492013-11-02 13:38:31260 if (!scanner.ScanMessage(&results)) \
261 return false; \
262 break; \
263 }
mseaborn3bedcdc2016-01-04 21:14:13264#define CASE_FOR_SYNC_MESSAGE(MESSAGE_TYPE) \
265 case MESSAGE_TYPE::ID: { \
266 MessageScannerImpl<MESSAGE_TYPE> scanner(&msg); \
267 if (rewrite_msg) \
268 results.new_msg.reset( \
269 new IPC::Message(msg.routing_id(), msg.type(), \
270 IPC::Message::PRIORITY_NORMAL)); \
271 if (!scanner.ScanSyncMessage(&results)) \
272 return false; \
273 break; \
274 }
[email protected]6276b492013-11-02 13:38:31275#define CASE_FOR_REPLY(MESSAGE_TYPE) \
276 case MESSAGE_TYPE::ID: { \
277 MessageScannerImpl<MESSAGE_TYPE> scanner(&msg); \
278 if (rewrite_msg) \
279 results.new_msg.reset( \
[email protected]753bb252013-11-04 22:28:12280 new IPC::Message(msg.routing_id(), msg.type(), \
281 IPC::Message::PRIORITY_NORMAL)); \
[email protected]6276b492013-11-02 13:38:31282 if (!scanner.ScanReply(&results)) \
283 return false; \
284 break; \
285 }
286
287namespace ppapi {
288namespace proxy {
289
290class SerializedHandle;
291
[email protected]7a90b852013-12-28 17:54:27292NaClMessageScanner::FileSystem::FileSystem()
293 : reserved_quota_(0) {
294}
295
296NaClMessageScanner::FileSystem::~FileSystem() {
297}
298
299bool NaClMessageScanner::FileSystem::UpdateReservedQuota(int64_t delta) {
300 base::AutoLock lock(lock_);
301 if (std::numeric_limits<int64_t>::max() - reserved_quota_ < delta)
302 return false; // reserved_quota_ + delta would overflow.
303 if (reserved_quota_ + delta < 0)
304 return false;
305 reserved_quota_ += delta;
306 return true;
307}
308
309NaClMessageScanner::FileIO::FileIO(FileSystem* file_system,
310 int64_t max_written_offset)
311 : file_system_(file_system),
312 max_written_offset_(max_written_offset) {
313}
314
315NaClMessageScanner::FileIO::~FileIO() {
316}
317
318void NaClMessageScanner::FileIO::SetMaxWrittenOffset(
319 int64_t max_written_offset) {
320 base::AutoLock lock(lock_);
321 max_written_offset_ = max_written_offset;
322}
323
324bool NaClMessageScanner::FileIO::Grow(int64_t amount) {
325 base::AutoLock lock(lock_);
326 DCHECK(amount > 0);
327 if (!file_system_->UpdateReservedQuota(-amount))
328 return false;
329 max_written_offset_ += amount;
330 return true;
331}
332
[email protected]6276b492013-11-02 13:38:31333NaClMessageScanner::NaClMessageScanner() {
334}
335
[email protected]7a90b852013-12-28 17:54:27336NaClMessageScanner::~NaClMessageScanner() {
337 for (FileSystemMap::iterator it = file_systems_.begin();
338 it != file_systems_.end(); ++it)
339 delete it->second;
340 for (FileIOMap::iterator it = files_.begin(); it != files_.end(); ++it)
341 delete it->second;
342}
343
[email protected]6276b492013-11-02 13:38:31344// Windows IPC differs from POSIX in that native handles are serialized in the
345// message body, rather than passed in a separate FileDescriptorSet. Therefore,
346// on Windows, any message containing handles must be rewritten in the POSIX
347// format before we can send it to the NaCl plugin.
scottmgd19b4f72015-06-19 22:51:00348// On Mac, base::SharedMemoryHandle has a different serialization than
349// base::FileDescriptor (which base::SharedMemoryHandle is typedef-ed to in
350// OS_NACL).
[email protected]6276b492013-11-02 13:38:31351bool NaClMessageScanner::ScanMessage(
352 const IPC::Message& msg,
[email protected]c8f326a2014-08-21 23:19:07353 uint32_t type,
[email protected]6276b492013-11-02 13:38:31354 std::vector<SerializedHandle>* handles,
dchengced92242016-04-07 00:00:12355 std::unique_ptr<IPC::Message>* new_msg_ptr) {
[email protected]6276b492013-11-02 13:38:31356 DCHECK(handles);
357 DCHECK(handles->empty());
358 DCHECK(new_msg_ptr);
359 DCHECK(!new_msg_ptr->get());
360
361 bool rewrite_msg =
scottmgd19b4f72015-06-19 22:51:00362#if defined(OS_WIN) || defined(OS_MACOSX)
[email protected]6276b492013-11-02 13:38:31363 true;
364#else
[email protected]73af6332014-02-06 23:28:10365 false;
[email protected]6276b492013-11-02 13:38:31366#endif
367
368 // We can't always tell from the message ID if rewriting is needed. Therefore,
[email protected]e74d2d12013-11-02 16:17:37369 // scan any message types that might contain a handle. If we later determine
370 // that there are no handles, we can cancel the rewriting by clearing the
371 // results.new_msg pointer.
[email protected]6276b492013-11-02 13:38:31372 ScanningResults results;
[email protected]7a90b852013-12-28 17:54:27373 results.nested_msg_callback =
374 base::Bind(&NaClMessageScanner::AuditNestedMessage,
375 base::Unretained(this));
[email protected]c8f326a2014-08-21 23:19:07376 switch (type) {
[email protected]6276b492013-11-02 13:38:31377 CASE_FOR_MESSAGE(PpapiMsg_PPBAudio_NotifyAudioStreamCreated)
378 CASE_FOR_MESSAGE(PpapiMsg_PPPMessaging_HandleMessage)
379 CASE_FOR_MESSAGE(PpapiPluginMsg_ResourceReply)
dmichael822ba8f2016-01-11 17:54:52380 CASE_FOR_SYNC_MESSAGE(PpapiMsg_PPPMessageHandler_HandleBlockingMessage)
mseaborn98d206ca2016-01-08 11:43:28381 CASE_FOR_SYNC_MESSAGE(PpapiMsg_PnaclTranslatorCompileInit)
mseaborn3bedcdc2016-01-04 21:14:13382 CASE_FOR_SYNC_MESSAGE(PpapiMsg_PnaclTranslatorLink)
Justin TerAvestcffdd032014-09-10 19:21:56383 CASE_FOR_REPLY(PpapiHostMsg_OpenResource)
penghuanga206fb492014-09-09 21:27:32384 CASE_FOR_REPLY(PpapiHostMsg_PPBGraphics3D_Create)
[email protected]c8f326a2014-08-21 23:19:07385 CASE_FOR_REPLY(PpapiHostMsg_PPBGraphics3D_CreateTransferBuffer)
386 CASE_FOR_REPLY(PpapiHostMsg_PPBImageData_CreateSimple)
387 CASE_FOR_REPLY(PpapiHostMsg_ResourceSyncCall)
388 CASE_FOR_REPLY(PpapiHostMsg_SharedMemory_CreateSharedMemory)
[email protected]6276b492013-11-02 13:38:31389 default:
390 // Do nothing for messages we don't know.
391 break;
392 }
393
394 // Only messages containing handles need to be rewritten. If no handles are
395 // found, don't return the rewritten message either. This must be changed if
396 // we ever add new param types that also require rewriting.
397 if (!results.handles.empty()) {
398 handles->swap(results.handles);
dchengd2b9f612015-12-18 19:08:51399 *new_msg_ptr = std::move(results.new_msg);
[email protected]6276b492013-11-02 13:38:31400 }
401 return true;
402}
403
[email protected]c586216c2013-12-18 21:59:17404void NaClMessageScanner::ScanUntrustedMessage(
405 const IPC::Message& untrusted_msg,
dchengced92242016-04-07 00:00:12406 std::unique_ptr<IPC::Message>* new_msg_ptr) {
[email protected]7a90b852013-12-28 17:54:27407 // Audit FileIO and FileSystem messages to ensure that the plugin doesn't
408 // exceed its file quota. If we find the message is malformed, just pass it
409 // through - we only care about well formed messages to the host.
410 if (untrusted_msg.type() == PpapiHostMsg_ResourceCall::ID) {
411 ResourceMessageCallParams params;
412 IPC::Message nested_msg;
413 if (!UnpackMessage<PpapiHostMsg_ResourceCall>(
414 untrusted_msg, &params, &nested_msg))
415 return;
416
417 switch (nested_msg.type()) {
418 case PpapiHostMsg_FileIO_Close::ID: {
419 FileIOMap::iterator it = files_.find(params.pp_resource());
420 if (it == files_.end())
421 return;
422 // Audit FileIO Close messages to make sure the plugin reports an
423 // accurate file size.
[email protected]540d6af42014-01-28 21:19:03424 FileGrowth file_growth;
[email protected]7a90b852013-12-28 17:54:27425 if (!UnpackMessage<PpapiHostMsg_FileIO_Close>(
[email protected]540d6af42014-01-28 21:19:03426 nested_msg, &file_growth))
[email protected]7a90b852013-12-28 17:54:27427 return;
428
429 int64_t trusted_max_written_offset = it->second->max_written_offset();
430 delete it->second;
431 files_.erase(it);
432 // If the plugin is under-reporting, rewrite the message with the
433 // trusted value.
[email protected]540d6af42014-01-28 21:19:03434 if (trusted_max_written_offset > file_growth.max_written_offset) {
[email protected]7a90b852013-12-28 17:54:27435 new_msg_ptr->reset(
436 new PpapiHostMsg_ResourceCall(
437 params,
[email protected]540d6af42014-01-28 21:19:03438 PpapiHostMsg_FileIO_Close(
439 FileGrowth(trusted_max_written_offset, 0))));
[email protected]7a90b852013-12-28 17:54:27440 }
[email protected]2d585cbd2014-06-03 02:13:22441 break;
[email protected]7a90b852013-12-28 17:54:27442 }
443 case PpapiHostMsg_FileIO_SetLength::ID: {
444 FileIOMap::iterator it = files_.find(params.pp_resource());
445 if (it == files_.end())
446 return;
447 // Audit FileIO SetLength messages to make sure the plugin is within
448 // the current quota reservation. In addition, deduct the file size
449 // increase from the quota reservation.
450 int64_t length = 0;
451 if (!UnpackMessage<PpapiHostMsg_FileIO_SetLength>(
452 nested_msg, &length))
453 return;
454
455 // Calculate file size increase, taking care to avoid overflows.
456 if (length < 0)
457 return;
458 int64_t trusted_max_written_offset = it->second->max_written_offset();
459 int64_t increase = length - trusted_max_written_offset;
460 if (increase <= 0)
461 return;
462 if (!it->second->Grow(increase)) {
463 new_msg_ptr->reset(
464 new PpapiHostMsg_ResourceCall(
465 params,
466 PpapiHostMsg_FileIO_SetLength(-1)));
467 }
468 break;
469 }
470 case PpapiHostMsg_FileSystem_ReserveQuota::ID: {
471 // Audit FileSystem ReserveQuota messages to make sure the plugin
472 // reports accurate file sizes.
473 int64_t amount = 0;
[email protected]540d6af42014-01-28 21:19:03474 FileGrowthMap file_growths;
[email protected]7a90b852013-12-28 17:54:27475 if (!UnpackMessage<PpapiHostMsg_FileSystem_ReserveQuota>(
[email protected]540d6af42014-01-28 21:19:03476 nested_msg, &amount, &file_growths))
[email protected]7a90b852013-12-28 17:54:27477 return;
478
479 bool audit_failed = false;
[email protected]540d6af42014-01-28 21:19:03480 for (FileGrowthMap::iterator it = file_growths.begin();
481 it != file_growths.end(); ++it) {
[email protected]7a90b852013-12-28 17:54:27482 FileIOMap::iterator file_it = files_.find(it->first);
483 if (file_it == files_.end())
484 continue;
485 int64_t trusted_max_written_offset =
486 file_it->second->max_written_offset();
[email protected]540d6af42014-01-28 21:19:03487 if (trusted_max_written_offset > it->second.max_written_offset) {
[email protected]7a90b852013-12-28 17:54:27488 audit_failed = true;
[email protected]540d6af42014-01-28 21:19:03489 it->second.max_written_offset = trusted_max_written_offset;
490 }
491 if (it->second.append_mode_write_amount < 0) {
492 audit_failed = true;
493 it->second.append_mode_write_amount = 0;
[email protected]7a90b852013-12-28 17:54:27494 }
495 }
496 if (audit_failed) {
497 new_msg_ptr->reset(
498 new PpapiHostMsg_ResourceCall(
499 params,
500 PpapiHostMsg_FileSystem_ReserveQuota(
[email protected]540d6af42014-01-28 21:19:03501 amount, file_growths)));
[email protected]7a90b852013-12-28 17:54:27502 }
503 break;
504 }
505 case PpapiHostMsg_ResourceDestroyed::ID: {
506 // Audit resource destroyed messages to release FileSystems.
507 PP_Resource resource;
508 if (!UnpackMessage<PpapiHostMsg_ResourceDestroyed>(
509 nested_msg, &resource))
510 return;
511 FileSystemMap::iterator fs_it = file_systems_.find(resource);
512 if (fs_it != file_systems_.end()) {
513 delete fs_it->second;
514 file_systems_.erase(fs_it);
515 }
[email protected]2d585cbd2014-06-03 02:13:22516 break;
[email protected]7a90b852013-12-28 17:54:27517 }
518 }
519 }
[email protected]c586216c2013-12-18 21:59:17520}
[email protected]6276b492013-11-02 13:38:31521
[email protected]7a90b852013-12-28 17:54:27522NaClMessageScanner::FileIO* NaClMessageScanner::GetFile(
523 PP_Resource file_io) {
524 FileIOMap::iterator it = files_.find(file_io);
525 DCHECK(it != files_.end());
526 return it->second;
527}
528
529void NaClMessageScanner::AuditNestedMessage(PP_Resource resource,
530 const IPC::Message& msg,
531 SerializedHandle* handle) {
532 switch (msg.type()) {
533 case PpapiPluginMsg_FileIO_OpenReply::ID: {
534 // A file that requires quota checking was opened.
535 PP_Resource quota_file_system;
536 int64_t max_written_offset = 0;
537 if (ppapi::UnpackMessage<PpapiPluginMsg_FileIO_OpenReply>(
538 msg, &quota_file_system, &max_written_offset)) {
539 if (quota_file_system) {
540 // Look up the FileSystem by inserting a new one. If it was already
541 // present, get the existing one, otherwise construct it.
542 FileSystem* file_system = NULL;
543 std::pair<FileSystemMap::iterator, bool> insert_result =
544 file_systems_.insert(std::make_pair(quota_file_system,
545 file_system));
546 if (insert_result.second)
547 insert_result.first->second = new FileSystem();
548 file_system = insert_result.first->second;
549 // Create the FileIO.
550 DCHECK(files_.find(resource) == files_.end());
551 files_.insert(std::make_pair(
552 resource,
553 new FileIO(file_system, max_written_offset)));
554 }
555 }
556 break;
557 }
558 case PpapiPluginMsg_FileSystem_ReserveQuotaReply::ID: {
559 // The amount of reserved quota for a FileSystem was refreshed.
560 int64_t amount = 0;
[email protected]540d6af42014-01-28 21:19:03561 FileSizeMap file_sizes;
[email protected]7a90b852013-12-28 17:54:27562 if (ppapi::UnpackMessage<PpapiPluginMsg_FileSystem_ReserveQuotaReply>(
[email protected]540d6af42014-01-28 21:19:03563 msg, &amount, &file_sizes)) {
[email protected]7a90b852013-12-28 17:54:27564 FileSystemMap::iterator it = file_systems_.find(resource);
565 DCHECK(it != file_systems_.end());
566 it->second->UpdateReservedQuota(amount);
567
[email protected]540d6af42014-01-28 21:19:03568 FileSizeMap::const_iterator offset_it = file_sizes.begin();
569 for (; offset_it != file_sizes.end(); ++offset_it) {
[email protected]7a90b852013-12-28 17:54:27570 FileIOMap::iterator fio_it = files_.find(offset_it->first);
571 DCHECK(fio_it != files_.end());
572 if (fio_it != files_.end())
573 fio_it->second->SetMaxWrittenOffset(offset_it->second);
574 }
575 }
576 break;
577 }
578 }
579}
580
[email protected]6276b492013-11-02 13:38:31581} // namespace proxy
582} // namespace ppapi