diff options
author | Michael BrĂ¼ning <michael.bruning@qt.io> | 2019-03-22 13:51:01 +0100 |
---|---|---|
committer | Michael BrĂ¼ning <michael.bruning@qt.io> | 2019-03-27 16:13:36 +0000 |
commit | 700a4af1fb50b5b912c8e7b4013d7e3e1f93dfd2 (patch) | |
tree | 65cd58412a964c3559866c75a61c967ab9253cd2 | |
parent | 03c4a4ffb989460f0c07567535892b5f5479df6d (diff) | |
download | qtwebengine-chromium-700a4af1fb50b5b912c8e7b4013d7e3e1f93dfd2.tar.gz |
[Backport] Security bug 905509 (12/13)
Backport of original patch by Antoine Labour <piman@chromium.org>:
Sanitize use of size_t in {Service,Client}FontManager and
RasterCHROMIUM
Because transfer buffers are 4GB at the max, use uint32_t instead of
size_t (or uint64_t) for sizes in font manager serialized data.
Bug: 905509
Change-Id: Iafc1e86f2f053eb978103fb02704d3513ac908af
Reviewed-on: https://chromium-review.googlesource.com/c/1404390
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
10 files changed, 69 insertions, 66 deletions
diff --git a/chromium/cc/paint/paint_op_buffer_fuzzer.cc b/chromium/cc/paint/paint_op_buffer_fuzzer.cc index 77070e59cec..7b27f169306 100644 --- a/chromium/cc/paint/paint_op_buffer_fuzzer.cc +++ b/chromium/cc/paint/paint_op_buffer_fuzzer.cc @@ -109,7 +109,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { base::CommandLine::Init(0, nullptr); // Partition the data to use some bytes for populating the font cache. - size_t bytes_for_fonts = data[0]; + uint32_t bytes_for_fonts = data[0]; if (bytes_for_fonts > size) bytes_for_fonts = size / 2; diff --git a/chromium/gpu/command_buffer/client/client_font_manager.cc b/chromium/gpu/command_buffer/client/client_font_manager.cc index 89e6a8151f5..52008dfd76f 100644 --- a/chromium/gpu/command_buffer/client/client_font_manager.cc +++ b/chromium/gpu/command_buffer/client/client_font_manager.cc @@ -11,7 +11,7 @@ namespace { class Serializer { public: - Serializer(char* memory, size_t memory_size) + Serializer(char* memory, uint32_t memory_size) : memory_(memory), memory_size_(memory_size) {} ~Serializer() = default; @@ -21,7 +21,7 @@ class Serializer { WriteData(val, sizeof(T), alignof(T)); } - void WriteData(const void* input, size_t bytes, size_t alignment) { + void WriteData(const void* input, uint32_t bytes, size_t alignment) { AlignMemory(bytes, alignment); if (bytes == 0) return; @@ -32,7 +32,7 @@ class Serializer { } private: - void AlignMemory(size_t size, size_t alignment) { + void AlignMemory(uint32_t size, size_t alignment) { // Due to the math below, alignment must be a power of two. DCHECK_GT(alignment, 0u); DCHECK_EQ(alignment & (alignment - 1), 0u); @@ -46,8 +46,8 @@ class Serializer { } char* memory_ = nullptr; - size_t memory_size_ = 0u; - size_t bytes_written_ = 0u; + uint32_t memory_size_ = 0u; + uint32_t bytes_written_ = 0u; }; } // namespace @@ -96,7 +96,7 @@ void ClientFontManager::Serialize() { std::vector<uint8_t> strike_data; strike_server_.writeStrikeData(&strike_data); - const size_t num_handles_created = + const uint32_t num_handles_created = last_allocated_handle_id_ - last_serialized_handle_id_; if (strike_data.size() == 0u && num_handles_created == 0u && locked_handles_.size() == 0u) { @@ -104,19 +104,29 @@ void ClientFontManager::Serialize() { return; } - // Size requires for serialization. - size_t bytes_required = - // Skia data size. - +sizeof(size_t) + alignof(size_t) + strike_data.size() + - alignof(std::max_align_t) - // num of handles created + SerializableHandles. - + sizeof(size_t) + alignof(size_t) + - num_handles_created * sizeof(SerializableSkiaHandle) + - alignof(SerializableSkiaHandle) + - // num of handles locked + DiscardableHandleIds. - +sizeof(size_t) + alignof(size_t) + - locked_handles_.size() * sizeof(SkDiscardableHandleId) + - alignof(SkDiscardableHandleId); + // Size required for serialization. + base::CheckedNumeric<uint32_t> checked_bytes_required = 0; + // Skia data size. + checked_bytes_required += sizeof(uint32_t) + alignof(uint32_t) + 16; + checked_bytes_required += strike_data.size(); + + // num of handles created + SerializableHandles. + checked_bytes_required += + sizeof(uint32_t) + alignof(uint32_t) + alignof(SerializableSkiaHandle); + checked_bytes_required += + base::CheckMul(num_handles_created, sizeof(SerializableSkiaHandle)); + + // num of handles locked + DiscardableHandleIds. + checked_bytes_required += + sizeof(uint32_t) + alignof(uint32_t) + alignof(SkDiscardableHandleId); + checked_bytes_required += + base::CheckMul(locked_handles_.size(), sizeof(SkDiscardableHandleId)); + + uint32_t bytes_required = 0; + if (!checked_bytes_required.AssignIfValid(&bytes_required)) { + DLOG(FATAL) << "ClientFontManager::Serialize: font buffer overflow"; + return; + } // Allocate memory. void* memory = client_->MapFontBuffer(bytes_required); @@ -128,7 +138,7 @@ void ClientFontManager::Serialize() { Serializer serializer(reinterpret_cast<char*>(memory), bytes_required); // Serialize all new handles. - serializer.Write<size_t>(&num_handles_created); + serializer.Write<uint32_t>(&num_handles_created); for (SkDiscardableHandleId handle_id = last_serialized_handle_id_ + 1; handle_id <= last_allocated_handle_id_; handle_id++) { auto it = discardable_handle_map_.find(handle_id); @@ -141,14 +151,16 @@ void ClientFontManager::Serialize() { } // Serialize all locked handle ids, so the raster unlocks them when done. - const size_t num_locked_handles = locked_handles_.size(); - serializer.Write<size_t>(&num_locked_handles); + DCHECK(base::IsValueInRangeForNumericType<uint32_t>(locked_handles_.size())); + const uint32_t num_locked_handles = locked_handles_.size(); + serializer.Write<uint32_t>(&num_locked_handles); for (auto handle_id : locked_handles_) serializer.Write<SkDiscardableHandleId>(&handle_id); // Serialize skia data. - const size_t skia_data_size = strike_data.size(); - serializer.Write<size_t>(&skia_data_size); + DCHECK(base::IsValueInRangeForNumericType<uint32_t>(strike_data.size())); + const uint32_t skia_data_size = strike_data.size(); + serializer.Write<uint32_t>(&skia_data_size); serializer.WriteData(strike_data.data(), strike_data.size(), alignof(std::max_align_t)); diff --git a/chromium/gpu/command_buffer/client/client_font_manager.h b/chromium/gpu/command_buffer/client/client_font_manager.h index faf822660dc..2cc4663189d 100644 --- a/chromium/gpu/command_buffer/client/client_font_manager.h +++ b/chromium/gpu/command_buffer/client/client_font_manager.h @@ -22,7 +22,7 @@ class RASTER_EXPORT ClientFontManager public: virtual ~Client() {} - virtual void* MapFontBuffer(size_t size) = 0; + virtual void* MapFontBuffer(uint32_t size) = 0; }; ClientFontManager(Client* client, CommandBuffer* command_buffer); diff --git a/chromium/gpu/command_buffer/client/raster_implementation.cc b/chromium/gpu/command_buffer/client/raster_implementation.cc index effa86ad402..a116bba0aa7 100644 --- a/chromium/gpu/command_buffer/client/raster_implementation.cc +++ b/chromium/gpu/command_buffer/client/raster_implementation.cc @@ -1011,7 +1011,7 @@ void* RasterImplementation::MapRasterCHROMIUM(GLsizeiptr size) { return raster_mapped_buffer_->address(); } -void* RasterImplementation::MapFontBuffer(size_t size) { +void* RasterImplementation::MapFontBuffer(uint32_t size) { if (size < 0) { SetGLError(GL_INVALID_VALUE, "glMapFontBufferCHROMIUM", "negative size"); return nullptr; @@ -1026,11 +1026,6 @@ void* RasterImplementation::MapFontBuffer(size_t size) { "mapped font buffer with no raster buffer"); return nullptr; } - if (size > std::numeric_limits<uint32_t>::max()) { - SetGLError(GL_INVALID_OPERATION, "glMapFontBufferCHROMIUM", - "trying to map too large font buffer"); - return nullptr; - } font_mapped_buffer_.emplace(size, helper_, mapped_memory_.get()); if (!font_mapped_buffer_->valid()) { diff --git a/chromium/gpu/command_buffer/client/raster_implementation.h b/chromium/gpu/command_buffer/client/raster_implementation.h index 3dff8709f51..336599a6c69 100644 --- a/chromium/gpu/command_buffer/client/raster_implementation.h +++ b/chromium/gpu/command_buffer/client/raster_implementation.h @@ -167,7 +167,7 @@ class RASTER_EXPORT RasterImplementation : public RasterInterface, void UnmapRasterCHROMIUM(uint32_t written_size); // ClientFontManager::Client implementation. - void* MapFontBuffer(size_t size) override; + void* MapFontBuffer(uint32_t size) override; private: friend class RasterImplementationTest; diff --git a/chromium/gpu/command_buffer/raster_cmd_buffer_functions.txt b/chromium/gpu/command_buffer/raster_cmd_buffer_functions.txt index 12261645a1c..5702c0358a1 100644 --- a/chromium/gpu/command_buffer/raster_cmd_buffer_functions.txt +++ b/chromium/gpu/command_buffer/raster_cmd_buffer_functions.txt @@ -34,7 +34,7 @@ GL_APICALL GLenum GL_APIENTRY glGetGraphicsResetStatusKHR (void); // Extension CHROMIUM_raster_transport GL_APICALL void GL_APIENTRY glBeginRasterCHROMIUM (GLuint sk_color, GLuint msaa_sample_count, GLboolean can_use_lcd_text, GLint color_type, GLuint color_space_transfer_cache_id, const GLbyte* mailbox); -GL_APICALL void GL_APIENTRY glRasterCHROMIUM (GLuint raster_shm_id, GLuint raster_shm_offset, GLsizeiptr raster_shm_size, GLuint font_shm_id, GLuint font_shm_offset, GLsizeiptr font_shm_size); +GL_APICALL void GL_APIENTRY glRasterCHROMIUM (GLuint raster_shm_id, GLuint raster_shm_offset, GLuint raster_shm_size, GLuint font_shm_id, GLuint font_shm_offset, GLuint font_shm_size); GL_APICALL void GL_APIENTRY glEndRasterCHROMIUM (void); GL_APICALL void GL_APIENTRY glCreateTransferCacheEntryINTERNAL (GLuint entry_type, GLuint entry_id, GLuint handle_shm_id, GLuint handle_shm_offset, GLuint data_shm_id, GLuint data_shm_offset, GLuint data_size); GL_APICALL void GL_APIENTRY glDeleteTransferCacheEntryINTERNAL (GLuint entry_type, GLuint entry_id); diff --git a/chromium/gpu/command_buffer/service/raster_decoder.cc b/chromium/gpu/command_buffer/service/raster_decoder.cc index ff88ad77e5f..24ad0fc683d 100644 --- a/chromium/gpu/command_buffer/service/raster_decoder.cc +++ b/chromium/gpu/command_buffer/service/raster_decoder.cc @@ -657,10 +657,10 @@ class RasterDecoderImpl final : public RasterDecoder, const volatile GLbyte* key); void DoRasterCHROMIUM(GLuint raster_shm_id, GLuint raster_shm_offset, - GLsizeiptr raster_shm_size, + GLuint raster_shm_size, GLuint font_shm_id, GLuint font_shm_offset, - GLsizeiptr font_shm_size); + GLuint font_shm_size); void DoEndRasterCHROMIUM(); void DoCreateTransferCacheEntryINTERNAL(GLuint entry_type, GLuint entry_id, @@ -3103,10 +3103,10 @@ scoped_refptr<Buffer> RasterDecoderImpl::GetShmBuffer(uint32_t shm_id) { void RasterDecoderImpl::DoRasterCHROMIUM(GLuint raster_shm_id, GLuint raster_shm_offset, - GLsizeiptr raster_shm_size, + GLuint raster_shm_size, GLuint font_shm_id, GLuint font_shm_offset, - GLsizeiptr font_shm_size) { + GLuint font_shm_size) { TRACE_EVENT1("gpu", "RasterDecoderImpl::DoRasterCHROMIUM", "raster_id", ++raster_chromium_id_); diff --git a/chromium/gpu/command_buffer/service/raster_decoder_autogen.h b/chromium/gpu/command_buffer/service/raster_decoder_autogen.h index 5ac48410224..d239d6578db 100644 --- a/chromium/gpu/command_buffer/service/raster_decoder_autogen.h +++ b/chromium/gpu/command_buffer/service/raster_decoder_autogen.h @@ -241,20 +241,10 @@ error::Error RasterDecoderImpl::HandleRasterCHROMIUM( GLuint raster_shm_id = static_cast<GLuint>(c.raster_shm_id); GLuint raster_shm_offset = static_cast<GLuint>(c.raster_shm_offset); - GLsizeiptr raster_shm_size = static_cast<GLsizeiptr>(c.raster_shm_size); + GLuint raster_shm_size = static_cast<GLuint>(c.raster_shm_size); GLuint font_shm_id = static_cast<GLuint>(c.font_shm_id); GLuint font_shm_offset = static_cast<GLuint>(c.font_shm_offset); - GLsizeiptr font_shm_size = static_cast<GLsizeiptr>(c.font_shm_size); - if (raster_shm_size < 0) { - LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glRasterCHROMIUM", - "raster_shm_size < 0"); - return error::kNoError; - } - if (font_shm_size < 0) { - LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glRasterCHROMIUM", - "font_shm_size < 0"); - return error::kNoError; - } + GLuint font_shm_size = static_cast<GLuint>(c.font_shm_size); DoRasterCHROMIUM(raster_shm_id, raster_shm_offset, raster_shm_size, font_shm_id, font_shm_offset, font_shm_size); return error::kNoError; diff --git a/chromium/gpu/command_buffer/service/service_font_manager.cc b/chromium/gpu/command_buffer/service/service_font_manager.cc index 21eb859fdf9..5f96284469d 100644 --- a/chromium/gpu/command_buffer/service/service_font_manager.cc +++ b/chromium/gpu/command_buffer/service/service_font_manager.cc @@ -14,7 +14,7 @@ namespace gpu { namespace { class Deserializer { public: - Deserializer(const volatile char* memory, size_t memory_size) + Deserializer(const volatile char* memory, uint32_t memory_size) : memory_(memory), memory_size_(memory_size) {} ~Deserializer() = default; @@ -32,7 +32,7 @@ class Deserializer { return true; } - bool ReadStrikeData(SkStrikeClient* strike_client, size_t size) { + bool ReadStrikeData(SkStrikeClient* strike_client, uint32_t size) { if (size == 0u) return true; @@ -48,14 +48,20 @@ class Deserializer { } private: - bool AlignMemory(size_t size, size_t alignment) { + bool AlignMemory(uint32_t size, size_t alignment) { // Due to the math below, alignment must be a power of two. DCHECK_GT(alignment, 0u); DCHECK_EQ(alignment & (alignment - 1), 0u); uintptr_t memory = reinterpret_cast<uintptr_t>(memory_); size_t padding = ((memory + alignment - 1) & ~(alignment - 1)) - memory; - if (bytes_read_ + size + padding > memory_size_) + + base::CheckedNumeric<uint32_t> checked_padded_size = bytes_read_; + checked_padded_size += padding; + checked_padded_size += size; + uint32_t padded_size = 0; + if (!checked_padded_size.AssignIfValid(&padded_size) || + padded_size > memory_size_) return false; memory_ += padding; @@ -64,8 +70,8 @@ class Deserializer { } const volatile char* memory_; - size_t memory_size_; - size_t bytes_read_ = 0u; + uint32_t memory_size_; + uint32_t bytes_read_ = 0u; }; } // namespace @@ -114,18 +120,18 @@ ServiceFontManager::~ServiceFontManager() { bool ServiceFontManager::Deserialize( const volatile char* memory, - size_t memory_size, + uint32_t memory_size, std::vector<SkDiscardableHandleId>* locked_handles) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(locked_handles->empty()); // All new handles. Deserializer deserializer(memory, memory_size); - size_t new_handles_created; - if (!deserializer.Read<size_t>(&new_handles_created)) + uint32_t new_handles_created; + if (!deserializer.Read<uint32_t>(&new_handles_created)) return false; - for (size_t i = 0; i < new_handles_created; ++i) { + for (uint32_t i = 0; i < new_handles_created; ++i) { SerializableSkiaHandle handle; if (!deserializer.Read<SerializableSkiaHandle>(&handle)) return false; @@ -143,19 +149,19 @@ bool ServiceFontManager::Deserialize( } // All locked handles - size_t num_locked_handles; - if (!deserializer.Read<size_t>(&num_locked_handles)) + uint32_t num_locked_handles; + if (!deserializer.Read<uint32_t>(&num_locked_handles)) return false; locked_handles->resize(num_locked_handles); - for (size_t i = 0; i < num_locked_handles; ++i) { + for (uint32_t i = 0; i < num_locked_handles; ++i) { if (!deserializer.Read<SkDiscardableHandleId>(&locked_handles->at(i))) return false; } // Skia font data. - size_t skia_data_size = 0u; - if (!deserializer.Read<size_t>(&skia_data_size)) + uint32_t skia_data_size = 0u; + if (!deserializer.Read<uint32_t>(&skia_data_size)) return false; if (!deserializer.ReadStrikeData(strike_client_.get(), skia_data_size)) diff --git a/chromium/gpu/command_buffer/service/service_font_manager.h b/chromium/gpu/command_buffer/service/service_font_manager.h index f46e723b837..0870cf11bd0 100644 --- a/chromium/gpu/command_buffer/service/service_font_manager.h +++ b/chromium/gpu/command_buffer/service/service_font_manager.h @@ -27,7 +27,7 @@ class GPU_GLES2_EXPORT ServiceFontManager { ~ServiceFontManager(); bool Deserialize(const volatile char* memory, - size_t memory_size, + uint32_t memory_size, std::vector<SkDiscardableHandleId>* locked_handles); bool Unlock(const std::vector<SkDiscardableHandleId>& handles); SkStrikeClient* strike_client() { return strike_client_.get(); } |