[dawn][wire] Introduce server/client MemoryHandle. This single handle class (one for each side of the wire) will replace the Read/WriteHandles. First introduce the new interfaces unimplemented to allow for a multi-sided patch to update Chromium as well. Bug: 524776858 Change-Id: I78697c51dd2a0248578b5f957fbc5ed78757f029 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/317535 Reviewed-by: Loko Kung <lokokung@google.com> Reviewed-by: Shao, Jiawei <jiawei.shao@intel.com> Commit-Queue: Corentin Wallez <cwallez@chromium.org>
diff --git a/include/dawn/wire/WireClient.h b/include/dawn/wire/WireClient.h index 43c572a..5169119 100644 --- a/include/dawn/wire/WireClient.h +++ b/include/dawn/wire/WireClient.h
@@ -109,17 +109,25 @@ MemoryTransferService(); virtual ~MemoryTransferService(); - class ReadHandle; - class WriteHandle; // Create a handle for reading server data. // This may fail and return nullptr. + class ReadHandle; virtual ReadHandle* CreateReadHandle(size_t) = 0; // Create a handle for writing server data. // This may fail and return nullptr. + class WriteHandle; virtual WriteHandle* CreateWriteHandle(size_t) = 0; + // Create a handle for sharing memory with the server. + // This may fail and return nullptr. + class MemoryHandle; + virtual std::unique_ptr<MemoryHandle> CreateMemoryHandle(size_t size) { + // TODO(https://crbug.com/524776858): Make pure virtual once Chromium implements it. + return nullptr; + } + class DAWN_WIRE_EXPORT ReadHandle { public: ReadHandle(); @@ -185,6 +193,55 @@ WriteHandle& operator=(const WriteHandle&) = delete; }; + class DAWN_WIRE_EXPORT MemoryHandle { + public: + MemoryHandle(); + virtual ~MemoryHandle(); + + // Get the required serialization size for SerializeCreate + virtual size_t GetSerializeCreateSize() const = 0; + + // Serialize the handle into |serializeSpace| so it can be received by the server. + virtual void SerializeCreate(std::span<std::byte> serializeSpace) const = 0; + + // Returns a const view of the memory. + virtual std::span<const std::byte> GetConstData() const { return GetData(); } + + // Returns a mutable view of the memory. + virtual std::span<std::byte> GetData() const = 0; + + // Get the required serialization size for SerializeDataUpdate for the range [offset, offset + // + size) + virtual size_t GetSerializeDataUpdateSize(size_t offset, size_t size) const = 0; + + // Serializes into |serializeData| the modification of the contents in the range [offset, + // offset + size). + virtual void SerializeDataUpdate(std::span<std::byte> serializeData, + size_t offset, + size_t size) const = 0; + + // Applies a data update for the range [offset, offset + size) that was produced by + // `server::MemoryTransferService::MemoryHandle::SerializeDataUpdate`. + // + // For hardening, the implementation must return false if offset + size overflows the size + // of the memory (or if offset + size overflows a size_t). + // + // Parameters: + // - `deserializeData`: The serialized payload from the server specifying the updated + // buffer contents. + // - `offset`: The byte offset of the range to update within the whole allocation. + // - `size`: The size of the range to update. + // + // Returns true on success, or false if the deserialization is invalid (e.g. OOB access). + virtual bool DeserializeDataUpdate(std::span<const std::byte> deserializeData, + size_t offset, + size_t size) = 0; + + private: + MemoryHandle(const MemoryHandle&) = delete; + MemoryHandle& operator=(const MemoryHandle&) = delete; + }; + private: MemoryTransferService(const MemoryTransferService&) = delete; MemoryTransferService& operator=(const MemoryTransferService&) = delete;
diff --git a/include/dawn/wire/WireServer.h b/include/dawn/wire/WireServer.h index 654b39f..b21beba 100644 --- a/include/dawn/wire/WireServer.h +++ b/include/dawn/wire/WireServer.h
@@ -89,18 +89,24 @@ MemoryTransferService(); virtual ~MemoryTransferService(); - class ReadHandle; - class WriteHandle; - // Deserialize data to create Read/Write handles. These handles are for the client // to Read/Write data. // TODO(https://issues.chromium.org/492456046): Pass as a `span<uint8_t> deseriazlizeData`. + class ReadHandle; virtual bool DeserializeReadHandle(const void* deserializePointer, size_t deserializeSize, ReadHandle** readHandle) = 0; + class WriteHandle; virtual bool DeserializeWriteHandle(const void* deserializePointer, size_t deserializeSize, WriteHandle** writeHandle) = 0; + // Returns a MemoryHandle from the parameters in creationData. May return nullptr on failure. + class MemoryHandle; + virtual std::unique_ptr<MemoryHandle> DeserializeMemoryHandle( + std::span<const std::byte> creationData) { + // TODO(https://crbug.com/524776858): Make pure virtual once Chromium implements it. + return nullptr; + } class DAWN_WIRE_EXPORT ReadHandle { public: @@ -166,6 +172,56 @@ virtual size_t GetSourceSize() const { return 0; } }; + class DAWN_WIRE_EXPORT MemoryHandle { + public: + MemoryHandle(); + virtual ~MemoryHandle(); + + // Return a direct view of the memory if this MemoryHandle supports it, nullptr when not + // supported. + virtual std::span<std::byte> GetSource() const { return {}; } + + // Get the required serialization size for SerializeDataUpdate for the range [offset, offset + // + size) + virtual size_t GetSerializeDataUpdateSize(size_t offset, size_t size) const = 0; + + // Serializes into |serializeData| the modification of the contents in the range [offset, + // offset + size). The modified contents is passed in |data|. + // + // Parameters: + // - `serializeData`: The output buffer to write the serialized payload into. + // - `offset`: The byte offset of data.data() within the whole allocation.. + // - `size`: The size of the range to update (must be <= data.size()). + // - `data`: The new contents for the range [offset, offset + data.size()). + virtual void SerializeDataUpdate(std::span<std::byte> serializeData, + size_t offset, + size_t size, + std::span<const std::byte> data) const = 0; + + // Applies a data update for the range [offset, offset + size) that was produced by + // `client::MemoryTransferService::MemoryHandle::SerializeDataUpdate`. + // + // For hardening, the implementation must return false if offset + size overflows the size + // of the memory (or if offset + size overflows a size_t), or if size > target.size(). + // + // Parameters: + // - `deserializeData`: The serialized payload from the client specifying the updated + // buffer contents. + // - `offset`: The byte offset for target.data() within the whole allocation. + // - `size`: The size of the range to update. + // - `target`: The range of data that is written by the update. + // + // Returns true on success, or false if the deserialization is invalid (e.g. OOB access). + virtual bool DeserializeDataUpdate(std::span<const std::byte> deserializeData, + size_t offset, + size_t size, + std::span<std::byte> target) = 0; + + private: + MemoryHandle(const MemoryHandle&) = delete; + MemoryHandle& operator=(const MemoryHandle&) = delete; + }; + private: MemoryTransferService(const MemoryTransferService&) = delete; MemoryTransferService& operator=(const MemoryTransferService&) = delete;
diff --git a/src/dawn/wire/WireClient.cpp b/src/dawn/wire/WireClient.cpp index 9ca5d2b..73451b1 100644 --- a/src/dawn/wire/WireClient.cpp +++ b/src/dawn/wire/WireClient.cpp
@@ -107,6 +107,10 @@ MemoryTransferService::WriteHandle::WriteHandle() = default; MemoryTransferService::WriteHandle::~WriteHandle() = default; + +MemoryTransferService::MemoryHandle::MemoryHandle() = default; + +MemoryTransferService::MemoryHandle::~MemoryHandle() = default; } // namespace client } // namespace dawn::wire
diff --git a/src/dawn/wire/WireServer.cpp b/src/dawn/wire/WireServer.cpp index d68311a..1dd74eb 100644 --- a/src/dawn/wire/WireServer.cpp +++ b/src/dawn/wire/WireServer.cpp
@@ -89,6 +89,10 @@ MemoryTransferService::WriteHandle::WriteHandle() = default; MemoryTransferService::WriteHandle::~WriteHandle() = default; + +MemoryTransferService::MemoryHandle::MemoryHandle() = default; + +MemoryTransferService::MemoryHandle::~MemoryHandle() = default; } // namespace server } // namespace dawn::wire