mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2024-11-24 22:36:09 +03:00
155 lines
4.5 KiB
C++
155 lines
4.5 KiB
C++
|
// Copyright 2015 The Chromium Authors. All rights reserved.
|
||
|
// Use of this source code is governed by a BSD-style license that can be
|
||
|
// found in the LICENSE file.
|
||
|
|
||
|
#include "base/memory/shared_memory_handle.h"
|
||
|
|
||
|
#include <mach/mach_vm.h>
|
||
|
#include <stddef.h>
|
||
|
#include <sys/mman.h>
|
||
|
#include <unistd.h>
|
||
|
|
||
|
#include "base/mac/mac_util.h"
|
||
|
#include "base/mac/mach_logging.h"
|
||
|
#include "base/posix/eintr_wrapper.h"
|
||
|
#include "base/unguessable_token.h"
|
||
|
|
||
|
namespace base {
|
||
|
|
||
|
SharedMemoryHandle::SharedMemoryHandle() {}
|
||
|
|
||
|
SharedMemoryHandle::SharedMemoryHandle(
|
||
|
const base::FileDescriptor& file_descriptor,
|
||
|
size_t size,
|
||
|
const base::UnguessableToken& guid)
|
||
|
: type_(POSIX),
|
||
|
file_descriptor_(file_descriptor),
|
||
|
guid_(guid),
|
||
|
size_(size) {}
|
||
|
|
||
|
SharedMemoryHandle::SharedMemoryHandle(mach_vm_size_t size,
|
||
|
const base::UnguessableToken& guid) {
|
||
|
type_ = MACH;
|
||
|
mach_port_t named_right;
|
||
|
kern_return_t kr = mach_make_memory_entry_64(
|
||
|
mach_task_self(),
|
||
|
&size,
|
||
|
0, // Address.
|
||
|
MAP_MEM_NAMED_CREATE | VM_PROT_READ | VM_PROT_WRITE,
|
||
|
&named_right,
|
||
|
MACH_PORT_NULL); // Parent handle.
|
||
|
if (kr != KERN_SUCCESS) {
|
||
|
memory_object_ = MACH_PORT_NULL;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
memory_object_ = named_right;
|
||
|
size_ = size;
|
||
|
ownership_passes_to_ipc_ = false;
|
||
|
guid_ = guid;
|
||
|
}
|
||
|
|
||
|
SharedMemoryHandle::SharedMemoryHandle(mach_port_t memory_object,
|
||
|
mach_vm_size_t size,
|
||
|
const base::UnguessableToken& guid)
|
||
|
: type_(MACH),
|
||
|
memory_object_(memory_object),
|
||
|
ownership_passes_to_ipc_(false),
|
||
|
guid_(guid),
|
||
|
size_(size) {}
|
||
|
|
||
|
SharedMemoryHandle SharedMemoryHandle::Duplicate() const {
|
||
|
switch (type_) {
|
||
|
case POSIX: {
|
||
|
if (!IsValid())
|
||
|
return SharedMemoryHandle();
|
||
|
int duped_fd = HANDLE_EINTR(dup(file_descriptor_.fd));
|
||
|
if (duped_fd < 0)
|
||
|
return SharedMemoryHandle();
|
||
|
return SharedMemoryHandle(FileDescriptor(duped_fd, true), size_, guid_);
|
||
|
}
|
||
|
case MACH: {
|
||
|
if (!IsValid())
|
||
|
return SharedMemoryHandle();
|
||
|
|
||
|
// Increment the ref count.
|
||
|
kern_return_t kr = mach_port_mod_refs(mach_task_self(), memory_object_,
|
||
|
MACH_PORT_RIGHT_SEND, 1);
|
||
|
DCHECK_EQ(kr, KERN_SUCCESS);
|
||
|
SharedMemoryHandle handle(*this);
|
||
|
handle.SetOwnershipPassesToIPC(true);
|
||
|
return handle;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool SharedMemoryHandle::IsValid() const {
|
||
|
switch (type_) {
|
||
|
case POSIX:
|
||
|
return file_descriptor_.fd >= 0;
|
||
|
case MACH:
|
||
|
return memory_object_ != MACH_PORT_NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
mach_port_t SharedMemoryHandle::GetMemoryObject() const {
|
||
|
DCHECK_EQ(type_, MACH);
|
||
|
return memory_object_;
|
||
|
}
|
||
|
|
||
|
bool SharedMemoryHandle::MapAt(off_t offset,
|
||
|
size_t bytes,
|
||
|
void** memory,
|
||
|
bool read_only) {
|
||
|
DCHECK(IsValid());
|
||
|
switch (type_) {
|
||
|
case SharedMemoryHandle::POSIX:
|
||
|
*memory = mmap(nullptr, bytes, PROT_READ | (read_only ? 0 : PROT_WRITE),
|
||
|
MAP_SHARED, file_descriptor_.fd, offset);
|
||
|
return *memory != MAP_FAILED;
|
||
|
case SharedMemoryHandle::MACH:
|
||
|
kern_return_t kr = mach_vm_map(
|
||
|
mach_task_self(),
|
||
|
reinterpret_cast<mach_vm_address_t*>(memory), // Output parameter
|
||
|
bytes,
|
||
|
0, // Alignment mask
|
||
|
VM_FLAGS_ANYWHERE,
|
||
|
memory_object_,
|
||
|
offset,
|
||
|
FALSE, // Copy
|
||
|
VM_PROT_READ | (read_only ? 0 : VM_PROT_WRITE), // Current protection
|
||
|
VM_PROT_WRITE | VM_PROT_READ | VM_PROT_IS_MASK, // Maximum protection
|
||
|
VM_INHERIT_NONE);
|
||
|
return kr == KERN_SUCCESS;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void SharedMemoryHandle::Close() const {
|
||
|
if (!IsValid())
|
||
|
return;
|
||
|
|
||
|
switch (type_) {
|
||
|
case POSIX:
|
||
|
if (IGNORE_EINTR(close(file_descriptor_.fd)) < 0)
|
||
|
DPLOG(ERROR) << "Error closing fd";
|
||
|
break;
|
||
|
case MACH:
|
||
|
kern_return_t kr = mach_port_deallocate(mach_task_self(), memory_object_);
|
||
|
if (kr != KERN_SUCCESS)
|
||
|
MACH_DLOG(ERROR, kr) << "Error deallocating mach port";
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void SharedMemoryHandle::SetOwnershipPassesToIPC(bool ownership_passes) {
|
||
|
DCHECK_EQ(type_, MACH);
|
||
|
ownership_passes_to_ipc_ = ownership_passes;
|
||
|
}
|
||
|
|
||
|
bool SharedMemoryHandle::OwnershipPassesToIPC() const {
|
||
|
DCHECK_EQ(type_, MACH);
|
||
|
return ownership_passes_to_ipc_;
|
||
|
}
|
||
|
|
||
|
} // namespace base
|