nacl_message_scanner.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
10f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 20f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 30f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// found in the LICENSE file. 40f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 50f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "ppapi/proxy/nacl_message_scanner.h" 60f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 70f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include <vector> 80f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "base/bind.h" 90f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "ipc/ipc_message.h" 100f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "ipc/ipc_message_macros.h" 110f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "ppapi/proxy/ppapi_messages.h" 120f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "ppapi/proxy/resource_message_params.h" 130f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "ppapi/proxy/serialized_handle.h" 140f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "ppapi/proxy/serialized_var.h" 150f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 160f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)class NaClDescImcShm; 170f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 180f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)namespace IPC { 190f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)class Message; 200f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 210f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using ppapi::proxy::ResourceMessageReplyParams; 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using ppapi::proxy::SerializedHandle; 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using ppapi::proxy::SerializedVar; 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 260f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)namespace { 270f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)typedef std::vector<SerializedHandle> Handles; 290f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 300f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)struct ScanningResults { 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ScanningResults() : handle_index(0), pp_resource(0) {} 320f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 330f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // Vector to hold handles found in the message. 340f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) Handles handles; 350f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // Current handle index in the rewritten message. During the scan, it will be 360f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // be less than or equal to handles.size(). After the scan it should be equal. 370f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) int handle_index; 380f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // The rewritten message. This may be NULL, so all ScanParam overloads should 390f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // check for NULL before writing to it. In some cases, a ScanParam overload 400f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // may set this to NULL when it can determine that there are no parameters 410f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // that need conversion. (See the ResourceMessageReplyParams overload.) 420f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) scoped_ptr<IPC::Message> new_msg; 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Resource id for resource messages. Save this when scanning resource replies 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // so when we audit the nested message, we know which resource it is for. 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PP_Resource pp_resource; 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Callback to receive the nested message in a resource message or reply. 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Callback<void(PP_Resource, const IPC::Message&, SerializedHandle*)> 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) nested_msg_callback; 490f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}; 500f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 510f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void WriteHandle(int handle_index, 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const SerializedHandle& handle, 530f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) IPC::Message* msg) { 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SerializedHandle::WriteHeader(handle.header(), msg); 550f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 560f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // Now write the handle itself in POSIX style. 570f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) msg->WriteBool(true); // valid == true 580f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) msg->WriteInt(handle_index); 590f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 600f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 610f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// Define overloads for each kind of message parameter that requires special 620f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// handling. See ScanTuple for how these get used. 630f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 640f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// Overload to match SerializedHandle. 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ScanParam(const SerializedHandle& handle, ScanningResults* results) { 660f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) results->handles.push_back(handle); 670f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (results->new_msg) 680f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) WriteHandle(results->handle_index++, handle, results->new_msg.get()); 690f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 700f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 710f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void HandleWriter(int* handle_index, 720f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) IPC::Message* m, 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const SerializedHandle& handle) { 740f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) WriteHandle((*handle_index)++, handle, m); 750f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 760f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 770f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// Overload to match SerializedVar, which can contain handles. 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ScanParam(const SerializedVar& var, ScanningResults* results) { 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<SerializedHandle*> var_handles = var.GetHandles(); 800f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // Copy any handles and then rewrite the message. 810f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) for (size_t i = 0; i < var_handles.size(); ++i) 820f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) results->handles.push_back(*var_handles[i]); 830f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (results->new_msg) 840f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) var.WriteDataToMessage(results->new_msg.get(), 850f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) base::Bind(&HandleWriter, &results->handle_index)); 860f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 870f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 880f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// For PpapiMsg_ResourceReply and the reply to PpapiHostMsg_ResourceSyncCall, 890f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// the handles are carried inside the ResourceMessageReplyParams. 900f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// NOTE: We only intercept handles from host->NaCl. The only kind of 910f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// ResourceMessageParams that travels this direction is 920f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// ResourceMessageReplyParams, so that's the only one we need to handle. 935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ScanParam(const ResourceMessageReplyParams& params, 940f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ScanningResults* results) { 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) results->pp_resource = params.pp_resource(); 960f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // If the resource reply params don't contain handles, NULL the new message 970f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // pointer to cancel further rewriting. 980f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // NOTE: This works because only handles currently need rewriting, and we 990f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // know at this point that this message has none. 1000f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (params.handles().empty()) { 1010f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) results->new_msg.reset(NULL); 1020f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return; 1030f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 1040f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 1050f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // If we need to rewrite the message, write everything before the handles 1060f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // (there's nothing after the handles). 1070f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (results->new_msg) { 1080f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) params.WriteReplyHeader(results->new_msg.get()); 1090f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // IPC writes the vector length as an int before the contents of the 1100f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // vector. 1110f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) results->new_msg->WriteInt(static_cast<int>(params.handles().size())); 1120f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 1130f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) for (Handles::const_iterator iter = params.handles().begin(); 1140f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) iter != params.handles().end(); 1150f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ++iter) { 1160f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // ScanParam will write each handle to the new message, if necessary. 1170f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ScanParam(*iter, results); 1180f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 1190f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // Tell ResourceMessageReplyParams that we have taken the handles, so it 1200f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // shouldn't close them. The NaCl runtime will take ownership of them. 1210f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) params.ConsumeHandles(); 1220f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 1230f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Overload to match nested messages. If we need to rewrite the message, write 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// the parameter. 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ScanParam(const IPC::Message& param, ScanningResults* results) { 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (results->pp_resource && !results->nested_msg_callback.is_null()) { 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SerializedHandle* handle = NULL; 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (results->handles.size() == 1) 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) handle = &results->handles[0]; 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) results->nested_msg_callback.Run(results->pp_resource, param, handle); 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (results->new_msg) 1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) IPC::WriteParam(results->new_msg.get(), param); 1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Overload to match all other types. If we need to rewrite the message, write 1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// the parameter. 1390f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)template <class T> 1400f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void ScanParam(const T& param, ScanningResults* results) { 1410f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (results->new_msg) 1420f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) IPC::WriteParam(results->new_msg.get(), param); 1430f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 1440f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 1450f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// These just break apart the given tuple and run ScanParam over each param. 1460f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// The idea is to scan elements in the tuple which require special handling, 1470f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// and write them into the |results| struct. 1480f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)template <class A> 1490f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void ScanTuple(const Tuple1<A>& t1, ScanningResults* results) { 1500f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ScanParam(t1.a, results); 1510f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 1520f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)template <class A, class B> 1530f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void ScanTuple(const Tuple2<A, B>& t1, ScanningResults* results) { 1540f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ScanParam(t1.a, results); 1550f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ScanParam(t1.b, results); 1560f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 1570f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)template <class A, class B, class C> 1580f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void ScanTuple(const Tuple3<A, B, C>& t1, ScanningResults* results) { 1590f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ScanParam(t1.a, results); 1600f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ScanParam(t1.b, results); 1610f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ScanParam(t1.c, results); 1620f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 1630f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)template <class A, class B, class C, class D> 1640f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void ScanTuple(const Tuple4<A, B, C, D>& t1, ScanningResults* results) { 1650f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ScanParam(t1.a, results); 1660f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ScanParam(t1.b, results); 1670f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ScanParam(t1.c, results); 1680f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ScanParam(t1.d, results); 1690f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 1700f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 1710f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)template <class MessageType> 1720f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)class MessageScannerImpl { 1730f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) public: 1740f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) explicit MessageScannerImpl(const IPC::Message* msg) 1750f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) : msg_(static_cast<const MessageType*>(msg)) { 1760f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 1770f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) bool ScanMessage(ScanningResults* results) { 1780f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) typename TupleTypes<typename MessageType::Schema::Param>::ValueTuple params; 1790f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (!MessageType::Read(msg_, ¶ms)) 1800f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return false; 1810f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ScanTuple(params, results); 1820f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return true; 1830f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 1840f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 1850f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) bool ScanReply(ScanningResults* results) { 1860f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) typename TupleTypes<typename MessageType::Schema::ReplyParam>::ValueTuple 1870f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) params; 1880f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (!MessageType::ReadReplyParam(msg_, ¶ms)) 1890f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return false; 1900f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // If we need to rewrite the message, write the message id first. 1910f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (results->new_msg) { 1920f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) results->new_msg->set_reply(); 1930f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) int id = IPC::SyncMessage::GetMessageId(*msg_); 1940f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) results->new_msg->WriteInt(id); 1950f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 1960f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ScanTuple(params, results); 1970f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return true; 1980f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 1990f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // TODO(dmichael): Add ScanSyncMessage for outgoing sync messages, if we ever 2000f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // need to scan those. 2010f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 2020f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) private: 2030f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) const MessageType* msg_; 2040f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}; 2050f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 2060f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} // namespace 2070f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 2080f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#define CASE_FOR_MESSAGE(MESSAGE_TYPE) \ 2090f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) case MESSAGE_TYPE::ID: { \ 2100f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) MessageScannerImpl<MESSAGE_TYPE> scanner(&msg); \ 2110f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (rewrite_msg) \ 2120f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) results.new_msg.reset( \ 2130f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) new IPC::Message(msg.routing_id(), msg.type(), \ 2140f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) IPC::Message::PRIORITY_NORMAL)); \ 2150f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (!scanner.ScanMessage(&results)) \ 2160f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return false; \ 2170f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) break; \ 2180f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 2190f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#define CASE_FOR_REPLY(MESSAGE_TYPE) \ 2200f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) case MESSAGE_TYPE::ID: { \ 2210f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) MessageScannerImpl<MESSAGE_TYPE> scanner(&msg); \ 2220f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (rewrite_msg) \ 2230f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) results.new_msg.reset( \ 2240f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) new IPC::Message(msg.routing_id(), msg.type(), \ 2250f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) IPC::Message::PRIORITY_NORMAL)); \ 2260f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (!scanner.ScanReply(&results)) \ 2270f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return false; \ 2280f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) break; \ 2290f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 2300f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 2310f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)namespace ppapi { 2320f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)namespace proxy { 2330f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 2340f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)class SerializedHandle; 2350f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)NaClMessageScanner::FileSystem::FileSystem() 2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : reserved_quota_(0) { 2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)NaClMessageScanner::FileSystem::~FileSystem() { 2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool NaClMessageScanner::FileSystem::UpdateReservedQuota(int64_t delta) { 2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::AutoLock lock(lock_); 2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (std::numeric_limits<int64_t>::max() - reserved_quota_ < delta) 2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; // reserved_quota_ + delta would overflow. 2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (reserved_quota_ + delta < 0) 2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) reserved_quota_ += delta; 2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)NaClMessageScanner::FileIO::FileIO(FileSystem* file_system, 2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int64_t max_written_offset) 2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : file_system_(file_system), 2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) max_written_offset_(max_written_offset) { 2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)NaClMessageScanner::FileIO::~FileIO() { 2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void NaClMessageScanner::FileIO::SetMaxWrittenOffset( 2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int64_t max_written_offset) { 2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::AutoLock lock(lock_); 2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) max_written_offset_ = max_written_offset; 2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool NaClMessageScanner::FileIO::Grow(int64_t amount) { 2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::AutoLock lock(lock_); 2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(amount > 0); 2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!file_system_->UpdateReservedQuota(-amount)) 2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) max_written_offset_ += amount; 2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2770f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)NaClMessageScanner::NaClMessageScanner() { 2780f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 2790f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)NaClMessageScanner::~NaClMessageScanner() { 2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (FileSystemMap::iterator it = file_systems_.begin(); 2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it != file_systems_.end(); ++it) 2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delete it->second; 2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (FileIOMap::iterator it = files_.begin(); it != files_.end(); ++it) 2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delete it->second; 2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2880f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// Windows IPC differs from POSIX in that native handles are serialized in the 2890f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// message body, rather than passed in a separate FileDescriptorSet. Therefore, 2900f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// on Windows, any message containing handles must be rewritten in the POSIX 2910f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// format before we can send it to the NaCl plugin. 2920f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)bool NaClMessageScanner::ScanMessage( 2930f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) const IPC::Message& msg, 2940f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) std::vector<SerializedHandle>* handles, 2950f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) scoped_ptr<IPC::Message>* new_msg_ptr) { 2960f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) DCHECK(handles); 2970f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) DCHECK(handles->empty()); 2980f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) DCHECK(new_msg_ptr); 2990f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) DCHECK(!new_msg_ptr->get()); 3000f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 3010f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) bool rewrite_msg = 3020f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#if defined(OS_WIN) 3030f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) true; 3040f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#else 3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) false; 3060f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#endif 3070f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 3080f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // We can't always tell from the message ID if rewriting is needed. Therefore, 3090f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // scan any message types that might contain a handle. If we later determine 3100f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // that there are no handles, we can cancel the rewriting by clearing the 3110f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // results.new_msg pointer. 3120f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ScanningResults results; 3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) results.nested_msg_callback = 3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&NaClMessageScanner::AuditNestedMessage, 3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Unretained(this)); 3160f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) switch (msg.type()) { 3170f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) CASE_FOR_MESSAGE(PpapiMsg_PPBAudio_NotifyAudioStreamCreated) 3180f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) CASE_FOR_MESSAGE(PpapiMsg_PPPMessaging_HandleMessage) 3190f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) CASE_FOR_MESSAGE(PpapiPluginMsg_ResourceReply) 3200f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) case IPC_REPLY_ID: { 3210f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) int id = IPC::SyncMessage::GetMessageId(msg); 3220f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) PendingSyncMsgMap::iterator iter(pending_sync_msgs_.find(id)); 3230f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (iter == pending_sync_msgs_.end()) { 3240f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) NOTREACHED(); 3250f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return false; 3260f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 3270f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) uint32_t type = iter->second; 3280f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) pending_sync_msgs_.erase(iter); 3290f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) switch (type) { 3300f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) CASE_FOR_REPLY(PpapiHostMsg_PPBGraphics3D_GetTransferBuffer) 3310f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) CASE_FOR_REPLY(PpapiHostMsg_PPBImageData_CreateSimple) 3320f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) CASE_FOR_REPLY(PpapiHostMsg_ResourceSyncCall) 3330f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) CASE_FOR_REPLY(PpapiHostMsg_SharedMemory_CreateSharedMemory) 3340f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) default: 3350f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // Do nothing for messages we don't know. 3360f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) break; 3370f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 3380f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) break; 3390f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 3400f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) default: 3410f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // Do nothing for messages we don't know. 3420f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) break; 3430f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 3440f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 3450f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // Only messages containing handles need to be rewritten. If no handles are 3460f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // found, don't return the rewritten message either. This must be changed if 3470f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // we ever add new param types that also require rewriting. 3480f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (!results.handles.empty()) { 3490f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) handles->swap(results.handles); 3500f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) *new_msg_ptr = results.new_msg.Pass(); 3510f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 3520f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return true; 3530f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 3540f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void NaClMessageScanner::ScanUntrustedMessage( 3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const IPC::Message& untrusted_msg, 3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<IPC::Message>* new_msg_ptr) { 3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (untrusted_msg.is_sync()) 3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RegisterSyncMessageForReply(untrusted_msg); 3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Audit FileIO and FileSystem messages to ensure that the plugin doesn't 3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // exceed its file quota. If we find the message is malformed, just pass it 3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // through - we only care about well formed messages to the host. 3645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (untrusted_msg.type() == PpapiHostMsg_ResourceCall::ID) { 3655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ResourceMessageCallParams params; 3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) IPC::Message nested_msg; 3675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!UnpackMessage<PpapiHostMsg_ResourceCall>( 3685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) untrusted_msg, ¶ms, &nested_msg)) 3695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 3705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) switch (nested_msg.type()) { 3725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case PpapiHostMsg_FileIO_Close::ID: { 3735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FileIOMap::iterator it = files_.find(params.pp_resource()); 3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (it == files_.end()) 3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Audit FileIO Close messages to make sure the plugin reports an 3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // accurate file size. 3785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FileGrowth file_growth; 3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!UnpackMessage<PpapiHostMsg_FileIO_Close>( 3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) nested_msg, &file_growth)) 3815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 3825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int64_t trusted_max_written_offset = it->second->max_written_offset(); 3845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delete it->second; 3855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) files_.erase(it); 3865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // If the plugin is under-reporting, rewrite the message with the 3875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // trusted value. 3885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (trusted_max_written_offset > file_growth.max_written_offset) { 3895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new_msg_ptr->reset( 3905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new PpapiHostMsg_ResourceCall( 3915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) params, 3925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PpapiHostMsg_FileIO_Close( 3935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FileGrowth(trusted_max_written_offset, 0)))); 3945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case PpapiHostMsg_FileIO_SetLength::ID: { 3975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FileIOMap::iterator it = files_.find(params.pp_resource()); 3985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (it == files_.end()) 3995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 4005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Audit FileIO SetLength messages to make sure the plugin is within 4015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // the current quota reservation. In addition, deduct the file size 4025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // increase from the quota reservation. 4035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int64_t length = 0; 4045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!UnpackMessage<PpapiHostMsg_FileIO_SetLength>( 4055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) nested_msg, &length)) 4065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 4075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Calculate file size increase, taking care to avoid overflows. 4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (length < 0) 4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 4115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int64_t trusted_max_written_offset = it->second->max_written_offset(); 4125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int64_t increase = length - trusted_max_written_offset; 4135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (increase <= 0) 4145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 4155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!it->second->Grow(increase)) { 4165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new_msg_ptr->reset( 4175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new PpapiHostMsg_ResourceCall( 4185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) params, 4195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PpapiHostMsg_FileIO_SetLength(-1))); 4205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 4225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case PpapiHostMsg_FileSystem_ReserveQuota::ID: { 4245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Audit FileSystem ReserveQuota messages to make sure the plugin 4255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // reports accurate file sizes. 4265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int64_t amount = 0; 4275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FileGrowthMap file_growths; 4285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!UnpackMessage<PpapiHostMsg_FileSystem_ReserveQuota>( 4295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) nested_msg, &amount, &file_growths)) 4305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 4315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool audit_failed = false; 4335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (FileGrowthMap::iterator it = file_growths.begin(); 4345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it != file_growths.end(); ++it) { 4355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FileIOMap::iterator file_it = files_.find(it->first); 4365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (file_it == files_.end()) 4375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) continue; 4385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int64_t trusted_max_written_offset = 4395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) file_it->second->max_written_offset(); 4405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (trusted_max_written_offset > it->second.max_written_offset) { 4415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) audit_failed = true; 4425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it->second.max_written_offset = trusted_max_written_offset; 4435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (it->second.append_mode_write_amount < 0) { 4455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) audit_failed = true; 4465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it->second.append_mode_write_amount = 0; 4475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (audit_failed) { 4505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new_msg_ptr->reset( 4515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new PpapiHostMsg_ResourceCall( 4525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) params, 4535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PpapiHostMsg_FileSystem_ReserveQuota( 4545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) amount, file_growths))); 4555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 4575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case PpapiHostMsg_ResourceDestroyed::ID: { 4595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Audit resource destroyed messages to release FileSystems. 4605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PP_Resource resource; 4615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!UnpackMessage<PpapiHostMsg_ResourceDestroyed>( 4625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) nested_msg, &resource)) 4635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 4645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FileSystemMap::iterator fs_it = file_systems_.find(resource); 4655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (fs_it != file_systems_.end()) { 4665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delete fs_it->second; 4675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) file_systems_.erase(fs_it); 4685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4730f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 4745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void NaClMessageScanner::RegisterSyncMessageForReply(const IPC::Message& msg) { 4750f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) int msg_id = IPC::SyncMessage::GetMessageId(msg); 4760f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) DCHECK(pending_sync_msgs_.find(msg_id) == pending_sync_msgs_.end()); 4770f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 4780f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) pending_sync_msgs_[msg_id] = msg.type(); 4790f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 4800f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 4815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)NaClMessageScanner::FileIO* NaClMessageScanner::GetFile( 4825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PP_Resource file_io) { 4835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FileIOMap::iterator it = files_.find(file_io); 4845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(it != files_.end()); 4855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return it->second; 4865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void NaClMessageScanner::AuditNestedMessage(PP_Resource resource, 4895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const IPC::Message& msg, 4905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SerializedHandle* handle) { 4915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) switch (msg.type()) { 4925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case PpapiPluginMsg_FileIO_OpenReply::ID: { 4935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // A file that requires quota checking was opened. 4945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PP_Resource quota_file_system; 4955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int64_t max_written_offset = 0; 4965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (ppapi::UnpackMessage<PpapiPluginMsg_FileIO_OpenReply>( 4975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) msg, "a_file_system, &max_written_offset)) { 4985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (quota_file_system) { 4995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Look up the FileSystem by inserting a new one. If it was already 5005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // present, get the existing one, otherwise construct it. 5015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FileSystem* file_system = NULL; 5025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::pair<FileSystemMap::iterator, bool> insert_result = 5035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) file_systems_.insert(std::make_pair(quota_file_system, 5045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) file_system)); 5055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (insert_result.second) 5065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) insert_result.first->second = new FileSystem(); 5075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) file_system = insert_result.first->second; 5085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Create the FileIO. 5095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(files_.find(resource) == files_.end()); 5105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) files_.insert(std::make_pair( 5115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) resource, 5125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new FileIO(file_system, max_written_offset))); 5135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 5165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case PpapiPluginMsg_FileSystem_ReserveQuotaReply::ID: { 5185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // The amount of reserved quota for a FileSystem was refreshed. 5195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int64_t amount = 0; 5205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FileSizeMap file_sizes; 5215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (ppapi::UnpackMessage<PpapiPluginMsg_FileSystem_ReserveQuotaReply>( 5225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) msg, &amount, &file_sizes)) { 5235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FileSystemMap::iterator it = file_systems_.find(resource); 5245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(it != file_systems_.end()); 5255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) it->second->UpdateReservedQuota(amount); 5265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FileSizeMap::const_iterator offset_it = file_sizes.begin(); 5285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (; offset_it != file_sizes.end(); ++offset_it) { 5295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FileIOMap::iterator fio_it = files_.find(offset_it->first); 5305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(fio_it != files_.end()); 5315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (fio_it != files_.end()) 5325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) fio_it->second->SetMaxWrittenOffset(offset_it->second); 5335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 5365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5400f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} // namespace proxy 5410f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} // namespace ppapi 542