summaryrefslogtreecommitdiffstats
path: root/ipc/chromium/src/base/shared_memory.h
diff options
context:
space:
mode:
Diffstat (limited to 'ipc/chromium/src/base/shared_memory.h')
-rw-r--r--ipc/chromium/src/base/shared_memory.h199
1 files changed, 199 insertions, 0 deletions
diff --git a/ipc/chromium/src/base/shared_memory.h b/ipc/chromium/src/base/shared_memory.h
new file mode 100644
index 0000000000..ec3f9fc259
--- /dev/null
+++ b/ipc/chromium/src/base/shared_memory.h
@@ -0,0 +1,199 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+// Copyright (c) 2006-2008 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.
+
+#ifndef BASE_SHARED_MEMORY_H_
+#define BASE_SHARED_MEMORY_H_
+
+#include "build/build_config.h"
+
+#if defined(OS_POSIX)
+# include <sys/types.h>
+# include <semaphore.h>
+#endif
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/process.h"
+#include "mozilla/Attributes.h"
+#include "mozilla/UniquePtrExtensions.h"
+
+namespace base {
+
+// SharedMemoryHandle is a platform specific type which represents
+// the underlying OS handle to a shared memory segment.
+typedef mozilla::UniqueFileHandle SharedMemoryHandle;
+
+// Platform abstraction for shared memory. Provides a C++ wrapper
+// around the OS primitive for a memory mapped file.
+class SharedMemory {
+ public:
+ // Create a new SharedMemory object.
+ SharedMemory() = default;
+
+ // Create a new SharedMemory object from an existing, open
+ // shared memory file.
+ SharedMemory(SharedMemoryHandle init_handle, bool read_only)
+ : SharedMemory() {
+ SetHandle(std::move(init_handle), read_only);
+ }
+
+ // Move constructor; transfers ownership.
+ SharedMemory(SharedMemory&& other) = default;
+
+ // Destructor. Will close any open files.
+ ~SharedMemory();
+
+ // Initialize a new SharedMemory object from an existing, open
+ // shared memory file.
+ bool SetHandle(SharedMemoryHandle handle, bool read_only);
+
+ // Return true iff the given handle is valid (i.e. not the distingished
+ // invalid value; NULL for a HANDLE and -1 for a file descriptor)
+ static bool IsHandleValid(const SharedMemoryHandle& handle);
+
+ // IsHandleValid applied to this object's handle.
+ bool IsValid() const { return static_cast<bool>(mapped_file_); }
+
+ // Return invalid handle (see comment above for exact definition).
+ static SharedMemoryHandle NULLHandle();
+
+ // Creates a shared memory segment.
+ // Returns true on success, false on failure.
+ bool Create(size_t size) { return CreateInternal(size, false); }
+
+ // Creates a shared memory segment that supports the Freeze()
+ // method; see below. (Warning: creating freezeable shared memory
+ // within a sandboxed process isn't possible on some platforms.)
+ // Returns true on success, false on failure.
+ bool CreateFreezeable(size_t size) { return CreateInternal(size, true); }
+
+ // Maps the shared memory into the caller's address space.
+ // Returns true on success, false otherwise. The memory address
+ // is accessed via the memory() accessor.
+ //
+ // If the specified fixed address is not null, it is the address that the
+ // shared memory must be mapped at. Returns false if the shared memory
+ // could not be mapped at that address.
+ bool Map(size_t bytes, void* fixed_address = nullptr);
+
+ // Unmaps the shared memory from the caller's address space.
+ void Unmap() { memory_ = nullptr; }
+
+ // Get the size of the opened shared memory backing file.
+ // Note: This size is only available to the creator of the
+ // shared memory, and not to those that opened shared memory
+ // created externally.
+ // Returns 0 if not opened or unknown.
+ size_t max_size() const { return max_size_; }
+
+ // Gets a pointer to the opened memory space if it has been
+ // Mapped via Map(). Returns NULL if it is not mapped.
+ void* memory() const { return memory_.get(); }
+
+ // Extracts the underlying file handle, returning a RAII type.
+ // This unmaps the memory as a side-effect (and cleans up any OS-specific
+ // resources).
+ mozilla::UniqueFileHandle TakeHandle() {
+ mozilla::UniqueFileHandle handle = std::move(mapped_file_);
+ Close();
+ return handle;
+ }
+
+ // Creates a copy of the underlying file handle, returning a RAII type.
+ // This operation may fail, in which case the returned file handle will be
+ // invalid.
+ mozilla::UniqueFileHandle CloneHandle();
+
+ // Make the shared memory object read-only, such that it cannot be
+ // written even if it's sent to an untrusted process. If it was
+ // mapped in this process, it will be unmapped. The object must
+ // have been created with CreateFreezeable(), and must not have
+ // already been shared to another process.
+ //
+ // (See bug 1479960 comment #0 for OS-specific implementation
+ // details.)
+ [[nodiscard]] bool Freeze() {
+ Unmap();
+ return ReadOnlyCopy(this);
+ }
+
+ // Similar to Freeze(), but assigns the read-only capability to
+ // another SharedMemory object and leaves this object's mapping in
+ // place and writeable. This can be used to broadcast data to
+ // several untrusted readers without copying.
+ //
+ // The other constraints of Freeze() still apply: this object closes
+ // its handle (as if by `Close(false)`), it cannot have been
+ // previously shared, and the read-only handle cannot be used to
+ // write the memory even by a malicious process.
+ //
+ // (The out parameter can currently be the same as `this` if and
+ // only if the memory was unmapped, but this is an implementation
+ // detail and shouldn't be relied on; for that use case Freeze()
+ // should be used instead.)
+ [[nodiscard]] bool ReadOnlyCopy(SharedMemory* ro_out);
+
+ // Closes the open shared memory segment.
+ // It is safe to call Close repeatedly.
+ void Close(bool unmap_view = true);
+
+ // Returns a page-aligned address at which the given number of bytes could
+ // probably be mapped. Returns NULL on error or if there is insufficient
+ // contiguous address space to map the required number of pages.
+ //
+ // Note that there is no guarantee that the given address space will actually
+ // be free by the time this function returns, since another thread might map
+ // something there in the meantime.
+ static void* FindFreeAddressSpace(size_t size);
+
+#ifdef OS_POSIX
+ // If named POSIX shm is being used, append the prefix (including
+ // the leading '/') that would be used by a process with the given
+ // pid to the given string and return true. If not, return false.
+ // (This is public so that the Linux sandboxing code can use it.)
+ static bool AppendPosixShmPrefix(std::string* str, pid_t pid);
+ // Similar, but simply returns whether POSIX shm is in use.
+ static bool UsingPosixShm();
+#endif
+
+ private:
+ bool CreateInternal(size_t size, bool freezeable);
+
+ // Unmapping shared memory requires the mapped size on Unix but not
+ // Windows; this encapsulates that difference.
+ struct MappingDeleter {
+#ifdef OS_POSIX
+ // A default-constructed deleter must be used only with nullptr
+ // (to allow default-constructing UniqueMapping). A deleter with
+ // a size must be used at most once.
+ size_t mapped_size_ = 0;
+ explicit MappingDeleter(size_t size) : mapped_size_(size) {}
+#endif
+ MappingDeleter() = default;
+ void operator()(void* ptr);
+ };
+ using UniqueMapping = mozilla::UniquePtr<void, MappingDeleter>;
+
+ UniqueMapping memory_;
+ size_t max_size_ = 0;
+ mozilla::UniqueFileHandle mapped_file_;
+#if defined(OS_WIN)
+ // If true indicates this came from an external source so needs extra checks
+ // before being mapped.
+ bool external_section_ = false;
+#elif defined(OS_POSIX) && !defined(ANDROID)
+ mozilla::UniqueFileHandle frozen_file_;
+ bool is_memfd_ = false;
+#endif
+ bool read_only_ = false;
+ bool freezeable_ = false;
+
+ DISALLOW_EVIL_CONSTRUCTORS(SharedMemory);
+};
+
+} // namespace base
+
+#endif // BASE_SHARED_MEMORY_H_