diff options
-rw-r--r-- | chrome/browser/nacl_host/nacl_process_host.cc | 10 | ||||
-rw-r--r-- | chrome/nacl/nacl_listener.cc | 70 |
2 files changed, 48 insertions, 32 deletions
diff --git a/chrome/browser/nacl_host/nacl_process_host.cc b/chrome/browser/nacl_host/nacl_process_host.cc index d254d44..a119ec3 100644 --- a/chrome/browser/nacl_host/nacl_process_host.cc +++ b/chrome/browser/nacl_host/nacl_process_host.cc @@ -498,11 +498,11 @@ void NaClProcessHost::SendStart(base::PlatformFile irt_file) { return; } -#if defined(OS_MACOSX) - // For dynamic loading support, NaCl requires a file descriptor that - // was created in /tmp, since those created with shm_open() are not - // mappable with PROT_EXEC. Rather than requiring an extra IPC - // round trip out of the sandbox, we create an FD here. +#if defined(OS_POSIX) + // For dynamic loading support, NaCl requires a file descriptor on an + // anonymous file that can have PROT_EXEC applied to its mappings. + // Rather than requiring an extra IPC round trip out of the sandbox, + // we create an FD here. base::SharedMemory memory_buffer; if (!memory_buffer.CreateAnonymous(/* size= */ 1)) { LOG(ERROR) << "Failed to allocate memory buffer"; diff --git a/chrome/nacl/nacl_listener.cc b/chrome/nacl/nacl_listener.cc index 55f7e43..9141025 100644 --- a/chrome/nacl/nacl_listener.cc +++ b/chrome/nacl/nacl_listener.cc @@ -33,41 +33,59 @@ typedef HANDLE NaClHandle; typedef int NaClHandle; #endif // NaClHandle -#if defined(OS_MACOSX) +#if defined(OS_POSIX) namespace { -// On Mac OS X, shm_open() works in the sandbox but does not give us -// an FD that we can map as PROT_EXEC. Rather than doing an IPC to -// get an executable SHM region when CreateMemoryObject() is called, -// we preallocate one on startup, since NaCl's sel_ldr only needs one -// of them. This saves a round trip. +// On Mac OS X, shm_open() works in the sandbox but does not give us an FD +// that we can map as PROT_EXEC. On Linux, shm_open() can only be used +// outside the sandbox anyway. Rather than doing an IPC to get an +// executable SHM region when CreateMemoryObject() is called, we +// preallocate one on startup, since NaCl's sel_ldr only needs one of them. +// This saves a round trip. + +bool SetShmFdSize(int fd, size_t size) { +#if defined(OS_MACOSX) + // ftruncate() is disallowed by the Mac OS X sandbox and returns EPERM. + // Luckily, we can get the same effect with lseek() + write(). + if (lseek(fd, size - 1, SEEK_SET) == -1) { + LOG(ERROR) << "lseek() failed: " << errno; + close(fd); + return false; + } + if (write(fd, "", 1) != 1) { + LOG(ERROR) << "write() failed: " << errno; + close(fd); + return -1; + } +#else + if (ftruncate(fd, size) < 0) { + LOG(ERROR) << "ftruncate() failed: " << errno; + close(fd); + return false; + } +#endif // defined(OS_MACOSX) + return true; +} base::subtle::Atomic32 g_shm_fd = -1; int CreateMemoryObject(size_t size, bool executable) { if (executable && size > 0) { int result_fd = base::subtle::NoBarrier_AtomicExchange(&g_shm_fd, -1); - if (result_fd != -1) { - // ftruncate() is disallowed by the Mac OS X sandbox and - // returns EPERM. Luckily, we can get the same effect with - // lseek() + write(). - if (lseek(result_fd, size - 1, SEEK_SET) == -1) { - LOG(ERROR) << "lseek() failed: " << errno; - return -1; - } - if (write(result_fd, "", 1) != 1) { - LOG(ERROR) << "write() failed: " << errno; - return -1; - } + if (result_fd != -1 && SetShmFdSize(result_fd, size)) return result_fd; - } } +#if defined(OS_LINUX) + // Use the proxied implementation. It doesn't really support executability. + CHECK(!executable); + return content::MakeSharedMemorySegmentViaIPC(size, executable); +#endif // Fall back to NaCl's default implementation. return -1; } } // namespace -#endif // defined(OS_MACOSX) +#endif // defined(OS_POSIX) extern "C" void NaClMainForChromium(int handle_count, const NaClHandle* handles, @@ -97,17 +115,15 @@ bool NaClListener::OnMessageReceived(const IPC::Message& msg) { } void NaClListener::OnStartSelLdr(std::vector<nacl::FileDescriptor> handles) { -#if defined(OS_LINUX) - nacl::SetCreateMemoryObjectFunc(content::MakeSharedMemorySegmentViaIPC); -#elif defined(OS_MACOSX) +#if defined(OS_POSIX) nacl::SetCreateMemoryObjectFunc(CreateMemoryObject); - CHECK(handles.size() >= 1); - g_shm_fd = nacl::ToNativeHandle(handles[handles.size() - 1]); + CHECK(!handles.empty()); + g_shm_fd = nacl::ToNativeHandle(handles.back()); handles.pop_back(); #endif - CHECK(handles.size() >= 1); - NaClHandle irt_handle = nacl::ToNativeHandle(handles[handles.size() - 1]); + CHECK(!handles.empty()); + NaClHandle irt_handle = nacl::ToNativeHandle(handles.back()); handles.pop_back(); #if defined(OS_WIN) |