Index: base/memory/shared_memory_posix.cc |
diff --git a/base/memory/shared_memory_posix.cc b/base/memory/shared_memory_posix.cc |
index efb0caf5bc9a29d805700c3abdad18ad6671a199..ee87f8b7863b8d8262c3d8ed13e0f664c90ff2ee 100644 |
--- a/base/memory/shared_memory_posix.cc |
+++ b/base/memory/shared_memory_posix.cc |
@@ -101,6 +101,55 @@ size_t SharedMemory::GetHandleLimit() { |
return base::GetMaxFds(); |
} |
+// static |
+scoped_ptr<SharedMemory> SharedMemory::NewAnonymousReadOnly( |
+ StringPiece contents) { |
+ // This function theoretically can block on the disk, but realistically |
+ // the temporary files we create will just go into the buffer cache |
+ // and be deleted before they ever make it out to disk. |
+ base::ThreadRestrictions::ScopedAllowIO allow_io; |
+ |
+ FilePath path; |
+ file_util::ScopedFILE writable_fp( |
+ file_util::CreateAndOpenTemporaryShmemFile(&path, /*executable=*/false)); |
+ if (!writable_fp) { |
+ LOG(ERROR) << "Failed to create temp shmem file."; |
+ return scoped_ptr<SharedMemory>(); |
+ } |
+ |
+ int readonly_fd = HANDLE_EINTR(open(path.value().c_str(), O_RDONLY)); |
+ if (readonly_fd < 0) { |
+ PLOG(ERROR) << "Failed to reopen temp shmem file readonly."; |
+ return scoped_ptr<SharedMemory>(); |
+ } |
+ file_util::ScopedFD readonly_fd_closer(&readonly_fd); |
+ |
+ if (unlink(path.value().c_str())) |
+ PLOG(WARNING) << "unlink"; |
+ |
+ if (fwrite(contents.data(), 1, contents.size(), writable_fp.get()) != |
+ contents.size()) { |
+ LOG(ERROR) << "Failed to write " << contents.size() |
+ << " bytes to memory block."; |
+ return scoped_ptr<SharedMemory>(); |
+ } |
+ |
+ if (fclose(writable_fp.release()) != 0) { |
+ PLOG(ERROR) << "Failed to flush contents of memory block."; |
+ return scoped_ptr<SharedMemory>(); |
+ } |
+ |
+ // Protect against people accidentally reopening as read/write. It's still |
+ // possible to intentionally fchmod() the FD back and then open it from /dev, |
+ // but the renderer can't open from a filesystem path. |
+ if (0 != fchmod(readonly_fd, S_IRUSR)) |
+ PLOG(DFATAL) << "Failed to make FD " << readonly_fd << " read-only"; |
+ |
+ return make_scoped_ptr(new SharedMemory( |
+ FileDescriptor(*readonly_fd_closer.release(), /*iauto_close=*/false), |
+ /*read_only=*/true)); |
+} |
+ |
bool SharedMemory::CreateAndMapAnonymous(size_t size) { |
return CreateAnonymous(size) && Map(size); |
} |