| Index: base/memory/shared_memory_win.cc
|
| diff --git a/base/memory/shared_memory_win.cc b/base/memory/shared_memory_win.cc
|
| index fd8d2fdd0c8a00bf91b54b8d5bee6606770e1542..34b306a4576b41c5bd101367a7833465ba3b3c26 100644
|
| --- a/base/memory/shared_memory_win.cc
|
| +++ b/base/memory/shared_memory_win.cc
|
| @@ -14,6 +14,23 @@
|
|
|
| namespace {
|
|
|
| +typedef enum _SECTION_INFORMATION_CLASS {
|
| + SectionBasicInformation,
|
| +} SECTION_INFORMATION_CLASS;
|
| +
|
| +typedef struct _SECTION_BASIC_INFORMATION {
|
| + PVOID BaseAddress;
|
| + ULONG Attributes;
|
| + LARGE_INTEGER Size;
|
| +} SECTION_BASIC_INFORMATION, *PSECTION_BASIC_INFORMATION;
|
| +
|
| +typedef ULONG(__stdcall* NtQuerySectionType)(
|
| + HANDLE SectionHandle,
|
| + SECTION_INFORMATION_CLASS SectionInformationClass,
|
| + PVOID SectionInformation,
|
| + ULONG SectionInformationLength,
|
| + PULONG ResultLength);
|
| +
|
| // Returns the length of the memory section starting at the supplied address.
|
| size_t GetMemorySectionSize(void* address) {
|
| MEMORY_BASIC_INFORMATION memory_info;
|
| @@ -23,6 +40,26 @@ size_t GetMemorySectionSize(void* address) {
|
| static_cast<char*>(memory_info.AllocationBase));
|
| }
|
|
|
| +// Checks if the section object is safe to map. At the moment this just means
|
| +// it's not an image section.
|
| +bool IsSectionSafeToMap(HANDLE handle) {
|
| + static NtQuerySectionType nt_query_section_func;
|
| + if (!nt_query_section_func) {
|
| + nt_query_section_func = reinterpret_cast<NtQuerySectionType>(
|
| + ::GetProcAddress(::GetModuleHandle(L"ntdll.dll"), "NtQuerySection"));
|
| + DCHECK(nt_query_section_func);
|
| + }
|
| +
|
| + // The handle must have SECTION_QUERY access for this to succeed.
|
| + SECTION_BASIC_INFORMATION basic_information = {};
|
| + ULONG status =
|
| + nt_query_section_func(handle, SectionBasicInformation, &basic_information,
|
| + sizeof(basic_information), nullptr);
|
| + if (status)
|
| + return false;
|
| + return (basic_information.Attributes & SEC_IMAGE) != SEC_IMAGE;
|
| +}
|
| +
|
| } // namespace.
|
|
|
| namespace base {
|
| @@ -35,24 +72,25 @@ SharedMemoryCreateOptions::SharedMemoryCreateOptions()
|
| share_read_only(false) {}
|
|
|
| SharedMemory::SharedMemory()
|
| - : mapped_file_(NULL),
|
| + : external_section_(false),
|
| + mapped_file_(NULL),
|
| mapped_size_(0),
|
| memory_(NULL),
|
| read_only_(false),
|
| - requested_size_(0) {
|
| -}
|
| + requested_size_(0) {}
|
|
|
| SharedMemory::SharedMemory(const std::wstring& name)
|
| - : name_(name),
|
| + : external_section_(false),
|
| + name_(name),
|
| mapped_file_(NULL),
|
| mapped_size_(0),
|
| memory_(NULL),
|
| read_only_(false),
|
| - requested_size_(0) {
|
| -}
|
| + requested_size_(0) {}
|
|
|
| SharedMemory::SharedMemory(const SharedMemoryHandle& handle, bool read_only)
|
| - : mapped_file_(handle.GetHandle()),
|
| + : external_section_(true),
|
| + mapped_file_(handle.GetHandle()),
|
| mapped_size_(0),
|
| memory_(NULL),
|
| read_only_(read_only),
|
| @@ -63,14 +101,16 @@ SharedMemory::SharedMemory(const SharedMemoryHandle& handle, bool read_only)
|
| SharedMemory::SharedMemory(const SharedMemoryHandle& handle,
|
| bool read_only,
|
| ProcessHandle process)
|
| - : mapped_file_(NULL),
|
| + : external_section_(true),
|
| + mapped_file_(NULL),
|
| mapped_size_(0),
|
| memory_(NULL),
|
| read_only_(read_only),
|
| requested_size_(0) {
|
| - ::DuplicateHandle(
|
| - process, handle.GetHandle(), GetCurrentProcess(), &mapped_file_,
|
| - read_only_ ? FILE_MAP_READ : FILE_MAP_READ | FILE_MAP_WRITE, FALSE, 0);
|
| + DWORD access = FILE_MAP_READ | SECTION_QUERY;
|
| + ::DuplicateHandle(process, handle.GetHandle(), GetCurrentProcess(),
|
| + &mapped_file_,
|
| + read_only_ ? access : access | FILE_MAP_WRITE, FALSE, 0);
|
| }
|
|
|
| SharedMemory::~SharedMemory() {
|
| @@ -170,6 +210,7 @@ bool SharedMemory::Create(const SharedMemoryCreateOptions& options) {
|
| // If the file already existed, set requested_size_ to 0 to show that
|
| // we don't know the size.
|
| requested_size_ = 0;
|
| + external_section_ = true;
|
| if (!options.open_existing_deprecated) {
|
| Close();
|
| return false;
|
| @@ -186,17 +227,20 @@ bool SharedMemory::Delete(const std::string& name) {
|
|
|
| bool SharedMemory::Open(const std::string& name, bool read_only) {
|
| DCHECK(!mapped_file_);
|
| -
|
| + DWORD access = FILE_MAP_READ | SECTION_QUERY;
|
| + if (!read_only)
|
| + access |= FILE_MAP_WRITE;
|
| name_ = ASCIIToUTF16(name);
|
| read_only_ = read_only;
|
| - mapped_file_ = OpenFileMapping(
|
| - read_only_ ? FILE_MAP_READ : FILE_MAP_READ | FILE_MAP_WRITE,
|
| - false, name_.empty() ? NULL : name_.c_str());
|
| - if (mapped_file_ != NULL) {
|
| - // Note: size_ is not set in this case.
|
| - return true;
|
| - }
|
| - return false;
|
| + mapped_file_ =
|
| + OpenFileMapping(access, false, name_.empty() ? nullptr : name_.c_str());
|
| + if (!mapped_file_)
|
| + return false;
|
| + // If a name specified assume it's an external section.
|
| + if (!name_.empty())
|
| + external_section_ = true;
|
| + // Note: size_ is not set in this case.
|
| + return true;
|
| }
|
|
|
| bool SharedMemory::MapAt(off_t offset, size_t bytes) {
|
| @@ -209,6 +253,9 @@ bool SharedMemory::MapAt(off_t offset, size_t bytes) {
|
| if (memory_)
|
| return false;
|
|
|
| + if (external_section_ && !IsSectionSafeToMap(mapped_file_))
|
| + return false;
|
| +
|
| memory_ = MapViewOfFile(mapped_file_,
|
| read_only_ ? FILE_MAP_READ : FILE_MAP_READ |
|
| FILE_MAP_WRITE,
|
| @@ -238,7 +285,7 @@ bool SharedMemory::ShareToProcessCommon(ProcessHandle process,
|
| bool close_self,
|
| ShareMode share_mode) {
|
| *new_handle = SharedMemoryHandle();
|
| - DWORD access = FILE_MAP_READ;
|
| + DWORD access = FILE_MAP_READ | SECTION_QUERY;
|
| DWORD options = 0;
|
| HANDLE mapped_file = mapped_file_;
|
| HANDLE result;
|
|
|