1a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "components/nacl/loader/nacl_listener.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(OS_POSIX) 11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <unistd.h> 12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif 13eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 179ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/rand_util.h" 19a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "components/nacl/common/nacl_messages.h" 20a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "components/nacl/loader/nacl_ipc_adapter.h" 21a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "components/nacl/loader/nacl_validation_db.h" 22a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "components/nacl/loader/nacl_validation_query.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_channel_handle.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_switches.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_sync_channel.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_sync_message_filter.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "native_client/src/trusted/service_runtime/sel_main_chrome.h" 2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "native_client/src/trusted/validator/nacl_file_info.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_descriptor_posix.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_LINUX) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/child_process_sandbox_support_linux.h" 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <fcntl.h> 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <io.h> 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/sandbox_init.h" 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// On Mac OS X, shm_open() works in the sandbox but does not give us 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// an FD that we can map as PROT_EXEC. Rather than doing an IPC to 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// get an executable SHM region when CreateMemoryObject() is called, 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// we preallocate one on startup, since NaCl's sel_ldr only needs one 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of them. This saves a round trip. 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::subtle::Atomic32 g_shm_fd = -1; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CreateMemoryObject(size_t size, int executable) { 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (executable && size > 0) { 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result_fd = base::subtle::NoBarrier_AtomicExchange(&g_shm_fd, -1); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result_fd != -1) { 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ftruncate() is disallowed by the Mac OS X sandbox and 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // returns EPERM. Luckily, we can get the same effect with 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // lseek() + write(). 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (lseek(result_fd, size - 1, SEEK_SET) == -1) { 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "lseek() failed: " << errno; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (write(result_fd, "", 1) != 1) { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "write() failed: " << errno; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result_fd; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Fall back to NaCl's default implementation. 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_LINUX) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CreateMemoryObject(size_t size, int executable) { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return content::MakeSharedMemorySegmentViaIPC(size, executable); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_WIN) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NaClListener* g_listener; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We wrap the function to convert the bool return value to an int. 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int BrokerDuplicateHandle(NaClHandle source_handle, 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32_t process_id, 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NaClHandle* target_handle, 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32_t desired_access, 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32_t options) { 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return content::BrokerDuplicateHandle(source_handle, process_id, 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) target_handle, desired_access, 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) options); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int AttachDebugExceptionHandler(const void* info, size_t info_size) { 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string info_string(reinterpret_cast<const char*>(info), info_size); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool result = false; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!g_listener->Send(new NaClProcessMsg_AttachDebugExceptionHandler( 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info_string, &result))) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BrowserValidationDBProxy : public NaClValidationDB { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit BrowserValidationDBProxy(NaClListener* listener) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : listener_(listener) { 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool QueryKnownToValidate(const std::string& signature) OVERRIDE { 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Initialize to false so that if the Send fails to write to the return 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // value we're safe. For example if the message is (for some reason) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // dispatched as an async message the return parameter will not be written. 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool result = false; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!listener_->Send(new NaClProcessMsg_QueryKnownToValidate(signature, 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &result))) { 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed to query NaCl validation cache."; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = false; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void SetKnownToValidate(const std::string& signature) OVERRIDE { 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Caching is optional: NaCl will still work correctly if the IPC fails. 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!listener_->Send(new NaClProcessMsg_SetKnownToValidate(signature))) { 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed to update NaCl validation cache."; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) virtual bool ResolveFileToken(struct NaClFileToken* file_token, 13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int32* fd, std::string* path) OVERRIDE { 14090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) *fd = -1; 14190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) *path = ""; 14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (file_token->lo == 0 && file_token->hi == 0) { 14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return false; 14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 14590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) IPC::PlatformFileForTransit ipc_fd = IPC::InvalidPlatformFileForTransit(); 14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::FilePath ipc_path; 14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!listener_->Send(new NaClProcessMsg_ResolveFileToken(file_token->lo, 14890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) file_token->hi, 14990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) &ipc_fd, 15090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) &ipc_path))) { 15190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return false; 15290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (ipc_fd == IPC::InvalidPlatformFileForTransit()) { 15490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return false; 15590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 15690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::PlatformFile handle = 15790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) IPC::PlatformFileForTransitToPlatformFile(ipc_fd); 15890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#if defined(OS_WIN) 15990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // On Windows, valid handles are 32 bit unsigned integers so this is safe. 16090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) *fd = reinterpret_cast<uintptr_t>(handle); 16190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#else 16290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) *fd = handle; 16390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif 16490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // It doesn't matter if the path is invalid UTF8 as long as it's consistent 16590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // and unforgeable. 16690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) *path = ipc_path.AsUTF8Unsafe(); 16790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return true; 16890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 16990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The listener never dies, otherwise this might be a dangling reference. 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NaClListener* listener_; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NaClListener::NaClListener() : shutdown_event_(true, false), 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io_thread_("NaCl_IOThread"), 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_LINUX) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prereserved_sandbox_size_(0), 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(OS_POSIX) 182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch number_of_cores_(-1), // unknown/error 183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) main_loop_(NULL) { 185a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) io_thread_.StartWithOptions( 186a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(g_listener == NULL); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_listener = this; 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NaClListener::~NaClListener() { 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shutdown_event_.Signal(); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_listener = NULL; 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NaClListener::Send(IPC::Message* msg) { 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(main_loop_ != NULL); 203a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (base::MessageLoop::current() == main_loop_) { 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This thread owns the channel. 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return channel_->Send(msg); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This thread does not own the channel. 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return filter_->Send(msg); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void NaClListener::Listen() { 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string channel_name = 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CommandLine::ForCurrentProcess()->GetSwitchValueASCII( 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switches::kProcessChannelID); 2167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) channel_.reset(new IPC::SyncChannel( 2177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) this, io_thread_.message_loop_proxy().get(), &shutdown_event_)); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) filter_ = new IPC::SyncMessageFilter(&shutdown_event_); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) channel_->AddFilter(filter_.get()); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) channel_->Init(channel_name, IPC::Channel::MODE_CLIENT, true); 221a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) main_loop_ = base::MessageLoop::current(); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) main_loop_->Run(); 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool NaClListener::OnMessageReceived(const IPC::Message& msg) { 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool handled = true; 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_BEGIN_MESSAGE_MAP(NaClListener, msg) 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IPC_MESSAGE_HANDLER(NaClProcessMsg_Start, OnStart) 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_MESSAGE_UNHANDLED(handled = false) 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC_END_MESSAGE_MAP() 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return handled; 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void NaClListener::OnStart(const nacl::NaClStartParams& params) { 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct NaClChromeMainArgs *args = NaClChromeMainArgsCreate(); 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (args == NULL) { 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "NaClChromeMainArgsCreate() failed"; 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (params.enable_ipc_proxy) { 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create the initial PPAPI IPC channel between the NaCl IRT and the 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // browser process. The IRT uses this channel to communicate with the 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // browser and to create additional IPC channels to renderer processes. 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC::ChannelHandle handle = 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IPC::Channel::GenerateVerifiedChannelID("nacl"); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<NaClIPCAdapter> ipc_adapter( 2487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) new NaClIPCAdapter(handle, io_thread_.message_loop_proxy().get())); 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ipc_adapter->ConnectChannel(); 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Pass a NaClDesc to the untrusted side. This will hold a ref to the 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NaClIPCAdapter. 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args->initial_ipc_desc = ipc_adapter->MakeNaClDesc(); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX) 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handle.socket = base::FileDescriptor( 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ipc_adapter->TakeClientFileDescriptor(), true); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!Send(new NaClProcessHostMsg_PpapiChannelCreated(handle))) 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed to send IPC channel handle to NaClProcessHost."; 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<nacl::FileDescriptor> handles = params.handles; 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_LINUX) || defined(OS_MACOSX) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args->urandom_fd = dup(base::GetUrandomFD()); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (args->urandom_fd < 0) { 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed to dup() the urandom FD"; 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 270eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch args->number_of_cores = number_of_cores_; 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args->create_memory_object_func = CreateMemoryObject; 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# if defined(OS_MACOSX) 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(handles.size() >= 1); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_shm_fd = nacl::ToNativeHandle(handles[handles.size() - 1]); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handles.pop_back(); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# endif 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (params.uses_irt) { 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(handles.size() >= 1); 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NaClHandle irt_handle = nacl::ToNativeHandle(handles[handles.size() - 1]); 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) handles.pop_back(); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) args->irt_fd = _open_osfhandle(reinterpret_cast<intptr_t>(irt_handle), 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) _O_RDONLY | _O_BINARY); 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (args->irt_fd < 0) { 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "_open_osfhandle() failed"; 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) args->irt_fd = irt_handle; 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Otherwise, the IRT handle is not even sent. 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) args->irt_fd = -1; 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (params.validation_cache_enabled) { 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // SHA256 block size. 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(params.validation_cache_key.length(), (size_t) 64); 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The cache structure is not freed and exists until the NaCl process exits. 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args->validation_cache = CreateValidationCache( 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new BrowserValidationDBProxy(this), params.validation_cache_key, 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params.version); 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(handles.size() == 1); 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args->imc_bootstrap_handle = nacl::ToNativeHandle(handles[0]); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args->enable_exception_handling = params.enable_exception_handling; 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args->enable_debug_stub = params.enable_debug_stub; 312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) args->enable_dyncode_syscalls = params.enable_dyncode_syscalls; 313ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!params.enable_dyncode_syscalls) { 314ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Bound the initial nexe's code segment size under PNaCl to 315ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // reduce the chance of a code spraying attack succeeding (see 316ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // https://code.google.com/p/nativeclient/issues/detail?id=3572). 317ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // We assume that !params.enable_dyncode_syscalls is synonymous 318ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // with PNaCl. We can't apply this arbitrary limit outside of 319ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // PNaCl because it might break existing NaCl apps, and this limit 320ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // is only useful if the dyncode syscalls are disabled. 321ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch args->initial_nexe_max_code_bytes = 32 << 20; // 32 MB 322ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_LINUX) || defined(OS_MACOSX) 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args->debug_stub_server_bound_socket_fd = nacl::ToNativeHandle( 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params.debug_stub_server_bound_socket); 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args->broker_duplicate_handle_func = BrokerDuplicateHandle; 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args->attach_debug_exception_handler_func = AttachDebugExceptionHandler; 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_LINUX) 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args->prereserved_sandbox_size = prereserved_sandbox_size_; 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NaClChromeMainStart(args); 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 337