diff options
author | epenner@chromium.org <epenner@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-27 06:10:12 +0000 |
---|---|---|
committer | epenner@chromium.org <epenner@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-27 06:10:12 +0000 |
commit | c8021e0389e481a019865d77773c17f1d8492cdc (patch) | |
tree | 307d36abcb1a252d9c90f0fef1eaa601354dcc5a /gpu | |
parent | f645be519c2a95fb0540c62d5f957527ac9e9d6f (diff) | |
download | chromium_src-c8021e0389e481a019865d77773c17f1d8492cdc.zip chromium_src-c8021e0389e481a019865d77773c17f1d8492cdc.tar.gz chromium_src-c8021e0389e481a019865d77773c17f1d8492cdc.tar.bz2 |
GPU: Remove memory duplication in async uploads.
Now that gpu::Buffer is ref-counted, we can avoid duplicating
memory for security (to prevent use-after-free).
BUG=177063, 353822
Review URL: https://codereview.chromium.org/211493006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@259807 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu')
15 files changed, 86 insertions, 465 deletions
diff --git a/gpu/command_buffer/common/buffer.cc b/gpu/command_buffer/common/buffer.cc index 5ba4e51..bbf40a1 100644 --- a/gpu/command_buffer/common/buffer.cc +++ b/gpu/command_buffer/common/buffer.cc @@ -6,6 +6,8 @@ #include "base/logging.h" +#include "base/numerics/safe_math.h" + namespace gpu { Buffer::Buffer(scoped_ptr<base::SharedMemory> shared_memory, size_t size) @@ -17,4 +19,12 @@ Buffer::Buffer(scoped_ptr<base::SharedMemory> shared_memory, size_t size) Buffer::~Buffer() {} +void* Buffer::GetDataAddress(uint32 data_offset, uint32 data_size) const { + base::CheckedNumeric<uint32> end = data_offset; + end += data_size; + if (!end.IsValid() || end.ValueOrDie() > static_cast<uint32>(size_)) + return NULL; + return static_cast<uint8*>(memory_) + data_offset; +} + } // namespace gpu diff --git a/gpu/command_buffer/common/buffer.h b/gpu/command_buffer/common/buffer.h index 74d9705..e9a1558 100644 --- a/gpu/command_buffer/common/buffer.h +++ b/gpu/command_buffer/common/buffer.h @@ -22,9 +22,12 @@ class GPU_EXPORT Buffer : public base::RefCountedThreadSafe<Buffer> { public: Buffer(scoped_ptr<base::SharedMemory> shared_memory, size_t size); - base::SharedMemory* shared_memory() { return shared_memory_.get(); } - void* memory() { return memory_; } - size_t size() { return size_; } + base::SharedMemory* shared_memory() const { return shared_memory_.get(); } + void* memory() const { return memory_; } + size_t size() const { return size_; } + + // Returns NULL if the address overflows the memory. + void* GetDataAddress(uint32 data_offset, uint32 data_size) const; private: friend class base::RefCountedThreadSafe<Buffer>; diff --git a/gpu/command_buffer/service/async_pixel_transfer_delegate.cc b/gpu/command_buffer/service/async_pixel_transfer_delegate.cc index 074f675..6b1dbc6 100644 --- a/gpu/command_buffer/service/async_pixel_transfer_delegate.cc +++ b/gpu/command_buffer/service/async_pixel_transfer_delegate.cc @@ -4,26 +4,18 @@ #include "gpu/command_buffer/service/async_pixel_transfer_delegate.h" -#include "base/memory/shared_memory.h" -#include "gpu/command_buffer/service/safe_shared_memory_pool.h" - namespace gpu { -namespace { - -void* GetAddressImpl(base::SharedMemory* shared_memory, - uint32 shm_size, - uint32 shm_data_offset, - uint32 shm_data_size) { - // Memory bounds have already been validated, so there - // are just DCHECKS here. - DCHECK(shared_memory); - DCHECK(shared_memory->memory()); - DCHECK_LE(shm_data_offset + shm_data_size, shm_size); - return static_cast<int8*>(shared_memory->memory()) + shm_data_offset; +AsyncMemoryParams::AsyncMemoryParams(scoped_refptr<Buffer> buffer, + uint32 data_offset, + uint32 data_size) + : buffer_(buffer), data_offset_(data_offset), data_size_(data_size) { + DCHECK(buffer_); + DCHECK(buffer_->memory()); } -} // namespace +AsyncMemoryParams::~AsyncMemoryParams() { +} AsyncPixelTransferUploadStats::AsyncPixelTransferUploadStats() : texture_upload_count_(0) {} @@ -44,27 +36,8 @@ int AsyncPixelTransferUploadStats::GetStats( return texture_upload_count_; } -AsyncPixelTransferDelegate::AsyncPixelTransferDelegate(){} - -AsyncPixelTransferDelegate::~AsyncPixelTransferDelegate(){} +AsyncPixelTransferDelegate::AsyncPixelTransferDelegate() {} -// static -void* AsyncPixelTransferDelegate::GetAddress( - const AsyncMemoryParams& mem_params) { - return GetAddressImpl(mem_params.shared_memory, - mem_params.shm_size, - mem_params.shm_data_offset, - mem_params.shm_data_size); -} - -// static -void* AsyncPixelTransferDelegate::GetAddress( - ScopedSafeSharedMemory* safe_shared_memory, - const AsyncMemoryParams& mem_params) { - return GetAddressImpl(safe_shared_memory->shared_memory(), - mem_params.shm_size, - mem_params.shm_data_offset, - mem_params.shm_data_size); -} +AsyncPixelTransferDelegate::~AsyncPixelTransferDelegate() {} } // namespace gpu diff --git a/gpu/command_buffer/service/async_pixel_transfer_delegate.h b/gpu/command_buffer/service/async_pixel_transfer_delegate.h index dc0f2d7..47d71d8 100644 --- a/gpu/command_buffer/service/async_pixel_transfer_delegate.h +++ b/gpu/command_buffer/service/async_pixel_transfer_delegate.h @@ -11,6 +11,7 @@ #include "base/memory/scoped_ptr.h" #include "base/synchronization/lock.h" #include "base/time/time.h" +#include "gpu/command_buffer/common/buffer.h" #include "gpu/gpu_export.h" #include "ui/gl/gl_bindings.h" @@ -44,11 +45,24 @@ struct AsyncTexSubImage2DParams { GLenum type; }; -struct AsyncMemoryParams { - base::SharedMemory* shared_memory; - uint32 shm_size; - uint32 shm_data_offset; - uint32 shm_data_size; +class AsyncMemoryParams { + public: + AsyncMemoryParams(scoped_refptr<Buffer> buffer, + uint32 data_offset, + uint32 data_size); + ~AsyncMemoryParams(); + + scoped_refptr<Buffer> buffer() const { return buffer_; } + uint32 data_size() const { return data_size_; } + uint32 data_offset() const { return data_offset_; } + void* GetDataAddress() const { + return buffer_->GetDataAddress(data_offset_, data_size_); + } + + private: + scoped_refptr<Buffer> buffer_; + uint32 data_offset_; + uint32 data_size_; }; class AsyncPixelTransferUploadStats @@ -92,13 +106,6 @@ class GPU_EXPORT AsyncPixelTransferDelegate { // Block until the specified transfer completes. virtual void WaitForTransferCompletion() = 0; - // Gets the address of the data from shared memory. - static void* GetAddress(const AsyncMemoryParams& mem_params); - - // Sometimes the |safe_shared_memory| is duplicate to prevent use after free. - static void* GetAddress(ScopedSafeSharedMemory* safe_shared_memory, - const AsyncMemoryParams& mem_params); - protected: AsyncPixelTransferDelegate(); diff --git a/gpu/command_buffer/service/async_pixel_transfer_manager.h b/gpu/command_buffer/service/async_pixel_transfer_manager.h index d0ea5da..4b57619 100644 --- a/gpu/command_buffer/service/async_pixel_transfer_manager.h +++ b/gpu/command_buffer/service/async_pixel_transfer_manager.h @@ -32,7 +32,7 @@ class GLContext; namespace gpu { class AsyncPixelTransferDelegate; -struct AsyncMemoryParams; +class AsyncMemoryParams; struct AsyncTexImage2DParams; class AsyncPixelTransferCompletionObserver diff --git a/gpu/command_buffer/service/async_pixel_transfer_manager_egl.cc b/gpu/command_buffer/service/async_pixel_transfer_manager_egl.cc index 3f3acc5..32fa4c0 100644 --- a/gpu/command_buffer/service/async_pixel_transfer_manager_egl.cc +++ b/gpu/command_buffer/service/async_pixel_transfer_manager_egl.cc @@ -16,7 +16,6 @@ #include "base/synchronization/waitable_event.h" #include "base/threading/thread.h" #include "gpu/command_buffer/service/async_pixel_transfer_delegate.h" -#include "gpu/command_buffer/service/safe_shared_memory_pool.h" #include "ui/gl/gl_context.h" #include "ui/gl/gl_surface_egl.h" #include "ui/gl/scoped_binders.h" @@ -81,12 +80,9 @@ void SetGlParametersForEglImageTexture() { void PerformNotifyCompletion( AsyncMemoryParams mem_params, - ScopedSafeSharedMemory* safe_shared_memory, scoped_refptr<AsyncPixelTransferCompletionObserver> observer) { TRACE_EVENT0("gpu", "PerformNotifyCompletion"); - AsyncMemoryParams safe_mem_params = mem_params; - safe_mem_params.shared_memory = safe_shared_memory->shared_memory(); - observer->DidComplete(safe_mem_params); + observer->DidComplete(mem_params); } class TransferThread : public base::Thread { @@ -117,16 +113,10 @@ class TransferThread : public base::Thread { context_ = NULL; } - SafeSharedMemoryPool* safe_shared_memory_pool() { - return &safe_shared_memory_pool_; - } - private: scoped_refptr<gfx::GLContext> context_; scoped_refptr<gfx::GLSurface> surface_; - SafeSharedMemoryPool safe_shared_memory_pool_; - DISALLOW_COPY_AND_ASSIGN(TransferThread); }; @@ -137,10 +127,6 @@ base::MessageLoopProxy* transfer_message_loop_proxy() { return g_transfer_thread.Pointer()->message_loop_proxy().get(); } -SafeSharedMemoryPool* safe_shared_memory_pool() { - return g_transfer_thread.Pointer()->safe_shared_memory_pool(); -} - // Class which holds async pixel transfers state (EGLImage). // The EGLImage is accessed by either thread, but everything // else accessed only on the main thread. @@ -254,7 +240,6 @@ class TransferStateInternal void PerformAsyncTexImage2D( AsyncTexImage2DParams tex_params, AsyncMemoryParams mem_params, - ScopedSafeSharedMemory* safe_shared_memory, scoped_refptr<AsyncPixelTransferUploadStats> texture_upload_stats) { TRACE_EVENT2("gpu", "PerformAsyncTexImage", @@ -269,8 +254,7 @@ class TransferStateInternal return; } - void* data = - AsyncPixelTransferDelegate::GetAddress(safe_shared_memory, mem_params); + void* data = mem_params.GetDataAddress(); base::TimeTicks begin_time; if (texture_upload_stats.get()) @@ -317,7 +301,6 @@ class TransferStateInternal void PerformAsyncTexSubImage2D( AsyncTexSubImage2DParams tex_params, AsyncMemoryParams mem_params, - ScopedSafeSharedMemory* safe_shared_memory, scoped_refptr<AsyncPixelTransferUploadStats> texture_upload_stats) { TRACE_EVENT2("gpu", "PerformAsyncTexSubImage2D", @@ -329,8 +312,7 @@ class TransferStateInternal DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_); DCHECK_EQ(0, tex_params.level); - void* data = - AsyncPixelTransferDelegate::GetAddress(safe_shared_memory, mem_params); + void* data = mem_params.GetDataAddress(); base::TimeTicks begin_time; if (texture_upload_stats.get()) @@ -509,9 +491,6 @@ void AsyncPixelTransferDelegateEGL::AsyncTexImage2D( if (WorkAroundAsyncTexImage2D(tex_params, mem_params, bind_callback)) return; - DCHECK(mem_params.shared_memory); - DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size, - mem_params.shm_size); DCHECK(!state_->TransferIsInProgress()); DCHECK_EQ(state_->egl_image_, EGL_NO_IMAGE_KHR); DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target); @@ -533,9 +512,6 @@ void AsyncPixelTransferDelegateEGL::AsyncTexImage2D( state_, tex_params, mem_params, - base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(), - mem_params.shared_memory, - mem_params.shm_size)), shared_state_->texture_upload_stats)); DCHECK(CHECK_GL()); @@ -550,9 +526,6 @@ void AsyncPixelTransferDelegateEGL::AsyncTexSubImage2D( if (WorkAroundAsyncTexSubImage2D(tex_params, mem_params)) return; DCHECK(!state_->TransferIsInProgress()); - DCHECK(mem_params.shared_memory); - DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size, - mem_params.shm_size); DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target); DCHECK_EQ(tex_params.level, 0); @@ -571,9 +544,6 @@ void AsyncPixelTransferDelegateEGL::AsyncTexSubImage2D( state_, tex_params, mem_params, - base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(), - mem_params.shared_memory, - mem_params.shm_size)), shared_state_->texture_upload_stats)); DCHECK(CHECK_GL()); @@ -621,7 +591,7 @@ bool AsyncPixelTransferDelegateEGL::WorkAroundAsyncTexImage2D( // On imagination we allocate synchronously all the time, even // if the dimensions support fast uploads. This is for part a.) // above, so allocations occur on a different thread/context as uploads. - void* data = GetAddress(mem_params); + void* data = mem_params.GetDataAddress(); SetGlParametersForEglImageTexture(); { @@ -672,7 +642,7 @@ bool AsyncPixelTransferDelegateEGL::WorkAroundAsyncTexSubImage2D( DCHECK_EQ(state_->define_params_.format, tex_params.format); DCHECK_EQ(state_->define_params_.type, tex_params.type); - void* data = GetAddress(mem_params); + void* data = mem_params.GetDataAddress(); base::TimeTicks begin_time; if (shared_state_->texture_upload_stats.get()) begin_time = base::TimeTicks::HighResNow(); @@ -733,19 +703,12 @@ void AsyncPixelTransferManagerEGL::BindCompletedAsyncTransfers() { void AsyncPixelTransferManagerEGL::AsyncNotifyCompletion( const AsyncMemoryParams& mem_params, AsyncPixelTransferCompletionObserver* observer) { - DCHECK(mem_params.shared_memory); - DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size, - mem_params.shm_size); // Post a PerformNotifyCompletion task to the upload thread. This task // will run after all async transfers are complete. transfer_message_loop_proxy()->PostTask( FROM_HERE, base::Bind(&PerformNotifyCompletion, mem_params, - base::Owned( - new ScopedSafeSharedMemory(safe_shared_memory_pool(), - mem_params.shared_memory, - mem_params.shm_size)), make_scoped_refptr(observer))); } diff --git a/gpu/command_buffer/service/async_pixel_transfer_manager_idle.cc b/gpu/command_buffer/service/async_pixel_transfer_manager_idle.cc index dcd870d..58748dd 100644 --- a/gpu/command_buffer/service/async_pixel_transfer_manager_idle.cc +++ b/gpu/command_buffer/service/async_pixel_transfer_manager_idle.cc @@ -9,30 +9,19 @@ #include "base/debug/trace_event_synthetic_delay.h" #include "base/lazy_instance.h" #include "base/memory/weak_ptr.h" -#include "gpu/command_buffer/service/safe_shared_memory_pool.h" #include "ui/gl/scoped_binders.h" namespace gpu { namespace { -base::LazyInstance<SafeSharedMemoryPool> g_safe_shared_memory_pool = - LAZY_INSTANCE_INITIALIZER; - -SafeSharedMemoryPool* safe_shared_memory_pool() { - return g_safe_shared_memory_pool.Pointer(); -} - static uint64 g_next_pixel_transfer_state_id = 1; void PerformNotifyCompletion( AsyncMemoryParams mem_params, - ScopedSafeSharedMemory* safe_shared_memory, scoped_refptr<AsyncPixelTransferCompletionObserver> observer) { TRACE_EVENT0("gpu", "PerformNotifyCompletion"); - AsyncMemoryParams safe_mem_params = mem_params; - safe_mem_params.shared_memory = safe_shared_memory->shared_memory(); - observer->DidComplete(safe_mem_params); + observer->DidComplete(mem_params); } } // namespace @@ -61,15 +50,11 @@ class AsyncPixelTransferDelegateIdle virtual void WaitForTransferCompletion() OVERRIDE; private: - void PerformAsyncTexImage2D( - AsyncTexImage2DParams tex_params, - AsyncMemoryParams mem_params, - const base::Closure& bind_callback, - ScopedSafeSharedMemory* safe_shared_memory); - void PerformAsyncTexSubImage2D( - AsyncTexSubImage2DParams tex_params, - AsyncMemoryParams mem_params, - ScopedSafeSharedMemory* safe_shared_memory); + void PerformAsyncTexImage2D(AsyncTexImage2DParams tex_params, + AsyncMemoryParams mem_params, + const base::Closure& bind_callback); + void PerformAsyncTexSubImage2D(AsyncTexSubImage2DParams tex_params, + AsyncMemoryParams mem_params); uint64 id_; GLuint texture_id_; @@ -101,21 +86,14 @@ void AsyncPixelTransferDelegateIdle::AsyncTexImage2D( const base::Closure& bind_callback) { TRACE_EVENT_SYNTHETIC_DELAY_BEGIN("gpu.AsyncTexImage"); DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target); - DCHECK(mem_params.shared_memory); - DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size, - mem_params.shm_size); shared_state_->tasks.push_back(AsyncPixelTransferManagerIdle::Task( id_, - base::Bind( - &AsyncPixelTransferDelegateIdle::PerformAsyncTexImage2D, - AsWeakPtr(), - tex_params, - mem_params, - bind_callback, - base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(), - mem_params.shared_memory, - mem_params.shm_size))))); + base::Bind(&AsyncPixelTransferDelegateIdle::PerformAsyncTexImage2D, + AsWeakPtr(), + tex_params, + mem_params, + bind_callback))); transfer_in_progress_ = true; } @@ -125,20 +103,13 @@ void AsyncPixelTransferDelegateIdle::AsyncTexSubImage2D( const AsyncMemoryParams& mem_params) { TRACE_EVENT_SYNTHETIC_DELAY_BEGIN("gpu.AsyncTexImage"); DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target); - DCHECK(mem_params.shared_memory); - DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size, - mem_params.shm_size); shared_state_->tasks.push_back(AsyncPixelTransferManagerIdle::Task( id_, - base::Bind( - &AsyncPixelTransferDelegateIdle::PerformAsyncTexSubImage2D, - AsWeakPtr(), - tex_params, - mem_params, - base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(), - mem_params.shared_memory, - mem_params.shm_size))))); + base::Bind(&AsyncPixelTransferDelegateIdle::PerformAsyncTexSubImage2D, + AsWeakPtr(), + tex_params, + mem_params))); transfer_in_progress_ = true; } @@ -166,13 +137,12 @@ void AsyncPixelTransferDelegateIdle::WaitForTransferCompletion() { void AsyncPixelTransferDelegateIdle::PerformAsyncTexImage2D( AsyncTexImage2DParams tex_params, AsyncMemoryParams mem_params, - const base::Closure& bind_callback, - ScopedSafeSharedMemory* safe_shared_memory) { + const base::Closure& bind_callback) { TRACE_EVENT2("gpu", "PerformAsyncTexImage2D", "width", tex_params.width, "height", tex_params.height); - void* data = GetAddress(safe_shared_memory, mem_params); + void* data = mem_params.GetDataAddress(); base::TimeTicks begin_time(base::TimeTicks::HighResNow()); gfx::ScopedTextureBinder texture_binder(tex_params.target, texture_id_); @@ -203,13 +173,12 @@ void AsyncPixelTransferDelegateIdle::PerformAsyncTexImage2D( void AsyncPixelTransferDelegateIdle::PerformAsyncTexSubImage2D( AsyncTexSubImage2DParams tex_params, - AsyncMemoryParams mem_params, - ScopedSafeSharedMemory* safe_shared_memory) { + AsyncMemoryParams mem_params) { TRACE_EVENT2("gpu", "PerformAsyncTexSubImage2D", "width", tex_params.width, "height", tex_params.height); - void* data = GetAddress(safe_shared_memory, mem_params); + void* data = mem_params.GetDataAddress(); base::TimeTicks begin_time(base::TimeTicks::HighResNow()); gfx::ScopedTextureBinder texture_binder(tex_params.target, texture_id_); @@ -301,9 +270,6 @@ void AsyncPixelTransferManagerIdle::AsyncNotifyCompletion( base::Bind( &PerformNotifyCompletion, mem_params, - base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(), - mem_params.shared_memory, - mem_params.shm_size)), make_scoped_refptr(observer)))); } diff --git a/gpu/command_buffer/service/async_pixel_transfer_manager_share_group.cc b/gpu/command_buffer/service/async_pixel_transfer_manager_share_group.cc index dcdab1c..e670dc7 100644 --- a/gpu/command_buffer/service/async_pixel_transfer_manager_share_group.cc +++ b/gpu/command_buffer/service/async_pixel_transfer_manager_share_group.cc @@ -19,7 +19,6 @@ #include "base/threading/thread.h" #include "base/threading/thread_checker.h" #include "gpu/command_buffer/service/async_pixel_transfer_delegate.h" -#include "gpu/command_buffer/service/safe_shared_memory_pool.h" #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_context.h" #include "ui/gl/gl_surface.h" @@ -34,12 +33,9 @@ const char kAsyncTransferThreadName[] = "AsyncTransferThread"; void PerformNotifyCompletion( AsyncMemoryParams mem_params, - ScopedSafeSharedMemory* safe_shared_memory, scoped_refptr<AsyncPixelTransferCompletionObserver> observer) { TRACE_EVENT0("gpu", "PerformNotifyCompletion"); - AsyncMemoryParams safe_mem_params = mem_params; - safe_mem_params.shared_memory = safe_shared_memory->shared_memory(); - observer->DidComplete(safe_mem_params); + observer->DidComplete(mem_params); } // TODO(backer): Factor out common thread scheduling logic from the EGL and @@ -80,16 +76,11 @@ class TransferThread : public base::Thread { context_ = NULL; } - SafeSharedMemoryPool* safe_shared_memory_pool() { - return &safe_shared_memory_pool_; - } - private: bool initialized_; scoped_refptr<gfx::GLSurface> surface_; scoped_refptr<gfx::GLContext> context_; - SafeSharedMemoryPool safe_shared_memory_pool_; void InitializeOnTransferThread(gfx::GLContext* parent_context, base::WaitableEvent* caller_wait) { @@ -136,10 +127,6 @@ base::MessageLoopProxy* transfer_message_loop_proxy() { return g_transfer_thread.Pointer()->message_loop_proxy().get(); } -SafeSharedMemoryPool* safe_shared_memory_pool() { - return g_transfer_thread.Pointer()->safe_shared_memory_pool(); -} - class PendingTask : public base::RefCountedThreadSafe<PendingTask> { public: explicit PendingTask(const base::Closure& task) @@ -258,11 +245,6 @@ class TransferStateInternal this, tex_params, mem_params, - // Duplicate the shared memory so there is no way we can get - // a use-after-free of the raw pixels. - base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(), - mem_params.shared_memory, - mem_params.shm_size)), texture_upload_stats)); transfer_message_loop_proxy()->PostTask( FROM_HERE, @@ -284,9 +266,6 @@ class TransferStateInternal this, tex_params, mem_params, - base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(), - mem_params.shared_memory, - mem_params.shm_size)), texture_upload_stats)); transfer_message_loop_proxy()->PostTask( FROM_HERE, @@ -303,7 +282,6 @@ class TransferStateInternal void PerformAsyncTexImage2D( AsyncTexImage2DParams tex_params, AsyncMemoryParams mem_params, - ScopedSafeSharedMemory* safe_shared_memory, scoped_refptr<AsyncPixelTransferUploadStats> texture_upload_stats) { TRACE_EVENT2("gpu", "PerformAsyncTexImage", @@ -317,8 +295,7 @@ class TransferStateInternal if (texture_upload_stats.get()) begin_time = base::TimeTicks::HighResNow(); - void* data = - AsyncPixelTransferDelegate::GetAddress(safe_shared_memory, mem_params); + void* data = mem_params.GetDataAddress(); { TRACE_EVENT0("gpu", "glTexImage2D"); @@ -343,7 +320,6 @@ class TransferStateInternal void PerformAsyncTexSubImage2D( AsyncTexSubImage2DParams tex_params, AsyncMemoryParams mem_params, - ScopedSafeSharedMemory* safe_shared_memory, scoped_refptr<AsyncPixelTransferUploadStats> texture_upload_stats) { TRACE_EVENT2("gpu", "PerformAsyncTexSubImage2D", @@ -357,9 +333,7 @@ class TransferStateInternal if (texture_upload_stats.get()) begin_time = base::TimeTicks::HighResNow(); - void* data = - AsyncPixelTransferDelegate::GetAddress(safe_shared_memory, mem_params); - + void* data = mem_params.GetDataAddress(); { TRACE_EVENT0("gpu", "glTexSubImage2D"); glTexSubImage2D(GL_TEXTURE_2D, @@ -467,9 +441,6 @@ void AsyncPixelTransferDelegateShareGroup::AsyncTexImage2D( const AsyncTexImage2DParams& tex_params, const AsyncMemoryParams& mem_params, const base::Closure& bind_callback) { - DCHECK(mem_params.shared_memory); - DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size, - mem_params.shm_size); DCHECK(!state_->TransferIsInProgress()); DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target); DCHECK_EQ(tex_params.level, 0); @@ -488,9 +459,6 @@ void AsyncPixelTransferDelegateShareGroup::AsyncTexSubImage2D( "width", tex_params.width, "height", tex_params.height); DCHECK(!state_->TransferIsInProgress()); - DCHECK(mem_params.shared_memory); - DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size, - mem_params.shm_size); DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target); DCHECK_EQ(tex_params.level, 0); @@ -539,19 +507,12 @@ void AsyncPixelTransferManagerShareGroup::BindCompletedAsyncTransfers() { void AsyncPixelTransferManagerShareGroup::AsyncNotifyCompletion( const AsyncMemoryParams& mem_params, AsyncPixelTransferCompletionObserver* observer) { - DCHECK(mem_params.shared_memory); - DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size, - mem_params.shm_size); // Post a PerformNotifyCompletion task to the upload thread. This task // will run after all async transfers are complete. transfer_message_loop_proxy()->PostTask( FROM_HERE, base::Bind(&PerformNotifyCompletion, mem_params, - base::Owned( - new ScopedSafeSharedMemory(safe_shared_memory_pool(), - mem_params.shared_memory, - mem_params.shm_size)), make_scoped_refptr(observer))); } diff --git a/gpu/command_buffer/service/async_pixel_transfer_manager_sync.cc b/gpu/command_buffer/service/async_pixel_transfer_manager_sync.cc index ffe5584..69e3c34 100644 --- a/gpu/command_buffer/service/async_pixel_transfer_manager_sync.cc +++ b/gpu/command_buffer/service/async_pixel_transfer_manager_sync.cc @@ -46,7 +46,7 @@ void AsyncPixelTransferDelegateSync::AsyncTexImage2D( const base::Closure& bind_callback) { // Save the define params to return later during deferred // binding of the transfer texture. - void* data = GetAddress(mem_params); + void* data = mem_params.GetDataAddress(); base::TimeTicks begin_time(base::TimeTicks::HighResNow()); glTexImage2D( tex_params.target, @@ -68,7 +68,7 @@ void AsyncPixelTransferDelegateSync::AsyncTexImage2D( void AsyncPixelTransferDelegateSync::AsyncTexSubImage2D( const AsyncTexSubImage2DParams& tex_params, const AsyncMemoryParams& mem_params) { - void* data = GetAddress(mem_params); + void* data = mem_params.GetDataAddress(); base::TimeTicks begin_time(base::TimeTicks::HighResNow()); glTexSubImage2D( tex_params.target, diff --git a/gpu/command_buffer/service/common_decoder.cc b/gpu/command_buffer/service/common_decoder.cc index 1462289..06cf3a4 100644 --- a/gpu/command_buffer/service/common_decoder.cc +++ b/gpu/command_buffer/service/common_decoder.cc @@ -61,17 +61,13 @@ CommonDecoder::CommonDecoder() : engine_(NULL) {} CommonDecoder::~CommonDecoder() {} void* CommonDecoder::GetAddressAndCheckSize(unsigned int shm_id, - unsigned int offset, - unsigned int size) { + unsigned int data_offset, + unsigned int data_size) { CHECK(engine_); scoped_refptr<gpu::Buffer> buffer = engine_->GetSharedMemoryBuffer(shm_id); if (!buffer) return NULL; - unsigned int end = offset + size; - if (end > buffer->size() || end < offset) { - return NULL; - } - return static_cast<int8*>(buffer->memory()) + offset; + return buffer->GetDataAddress(data_offset, data_size); } scoped_refptr<gpu::Buffer> CommonDecoder::GetSharedMemoryBuffer( diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 427227c..e6a1270 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -10392,20 +10392,12 @@ error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM( return error::kNoError; } - // We know the memory/size is safe, so get the real shared memory since - // it might need to be duped to prevent use-after-free of the memory. - scoped_refptr<gpu::Buffer> buffer = GetSharedMemoryBuffer(c.pixels_shm_id); - base::SharedMemory* shared_memory = buffer->shared_memory(); - uint32 shm_size = buffer->size(); - uint32 shm_data_offset = c.pixels_shm_offset; - uint32 shm_data_size = pixels_size; - // Setup the parameters. AsyncTexImage2DParams tex_params = { target, level, static_cast<GLenum>(internal_format), width, height, border, format, type}; - AsyncMemoryParams mem_params = { - shared_memory, shm_size, shm_data_offset, shm_data_size}; + AsyncMemoryParams mem_params( + GetSharedMemoryBuffer(c.pixels_shm_id), c.pixels_shm_offset, pixels_size); // Set up the async state if needed, and make the texture // immutable so the async state stays valid. The level info @@ -10482,19 +10474,11 @@ error::Error GLES2DecoderImpl::HandleAsyncTexSubImage2DCHROMIUM( } } - // We know the memory/size is safe, so get the real shared memory since - // it might need to be duped to prevent use-after-free of the memory. - scoped_refptr<gpu::Buffer> buffer = GetSharedMemoryBuffer(c.data_shm_id); - base::SharedMemory* shared_memory = buffer->shared_memory(); - uint32 shm_size = buffer->size(); - uint32 shm_data_offset = c.data_shm_offset; - uint32 shm_data_size = data_size; - // Setup the parameters. AsyncTexSubImage2DParams tex_params = {target, level, xoffset, yoffset, width, height, format, type}; - AsyncMemoryParams mem_params = {shared_memory, shm_size, - shm_data_offset, shm_data_size}; + AsyncMemoryParams mem_params( + GetSharedMemoryBuffer(c.data_shm_id), c.data_shm_offset, data_size); AsyncPixelTransferDelegate* delegate = async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref); if (!delegate) { diff --git a/gpu/command_buffer/service/query_manager.cc b/gpu/command_buffer/service/query_manager.cc index 2c30186..9f1d3a7 100644 --- a/gpu/command_buffer/service/query_manager.cc +++ b/gpu/command_buffer/service/query_manager.cc @@ -36,12 +36,9 @@ class AsyncPixelTransferCompletionObserverImpl virtual void DidComplete(const AsyncMemoryParams& mem_params) OVERRIDE { base::AutoLock locked(lock_); if (!cancelled_) { - DCHECK(mem_params.shared_memory); - DCHECK(mem_params.shared_memory->memory()); - void* data = static_cast<int8*>(mem_params.shared_memory->memory()) + - mem_params.shm_data_offset; + DCHECK(mem_params.buffer()); + void* data = mem_params.GetDataAddress(); QuerySync* sync = static_cast<QuerySync*>(data); - base::subtle::Release_Store(&sync->process_count, submit_count_); } } @@ -86,20 +83,14 @@ bool AsyncPixelTransfersCompletedQuery::Begin() { bool AsyncPixelTransfersCompletedQuery::End( base::subtle::Atomic32 submit_count) { - AsyncMemoryParams mem_params; // Get the real shared memory since it might need to be duped to prevent // use-after-free of the memory. scoped_refptr<Buffer> buffer = manager()->decoder()->GetSharedMemoryBuffer(shm_id()); if (!buffer) return false; - mem_params.shared_memory = buffer->shared_memory(); - mem_params.shm_size = buffer->size(); - mem_params.shm_data_offset = shm_offset(); - mem_params.shm_data_size = sizeof(QuerySync); - base::CheckedNumeric<uint32> end = mem_params.shm_data_offset; - end += mem_params.shm_data_size; - if (!end.IsValid() || end.ValueOrDie() > mem_params.shm_size) + AsyncMemoryParams mem_params(buffer, shm_offset(), sizeof(QuerySync)); + if (!mem_params.GetDataAddress()) return false; observer_ = new AsyncPixelTransferCompletionObserverImpl(submit_count); diff --git a/gpu/command_buffer/service/safe_shared_memory_pool.cc b/gpu/command_buffer/service/safe_shared_memory_pool.cc deleted file mode 100644 index 9ba5390..0000000 --- a/gpu/command_buffer/service/safe_shared_memory_pool.cc +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright (c) 2012 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 "gpu/command_buffer/service/safe_shared_memory_pool.h" - -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/process/process_handle.h" -#include "build/build_config.h" - -using base::SharedMemory; -using base::SharedMemoryHandle; - -namespace gpu { - -ScopedSafeSharedMemory::ScopedSafeSharedMemory(SafeSharedMemoryPool* pool, - base::SharedMemory* memory, - size_t shm_size) { - DCHECK(pool); - DCHECK(memory); - DCHECK(memory->memory()); - pool_ = pool; - original_handle_ = memory->handle(); - safe_shared_memory_ = pool->AcquireSafeSharedMemory(memory, shm_size); - CHECK(safe_shared_memory_); -} - -ScopedSafeSharedMemory::~ScopedSafeSharedMemory() { - // Release the handle. The pool will delete the SharedMemory - // object when it is no longer referenced. - pool_->ReleaseSafeSharedMemory(original_handle_); -} - -base::SharedMemory* ScopedSafeSharedMemory::shared_memory() { - return safe_shared_memory_; -} - -SafeSharedMemoryPool::SafeSharedMemoryPool() - : handles_acquired_(0), - handles_consumed_(0), - address_space_consumed_(0), - max_handles_acquired_(0), - max_handles_consumed_(0), - max_address_space_consumed_(0) { -} - -SafeSharedMemoryPool::~SafeSharedMemoryPool() { -} - -base::SharedMemory* SafeSharedMemoryPool:: - AcquireSafeSharedMemory(base::SharedMemory* shared_memory, - size_t shm_size) { - DCHECK(shared_memory); - DCHECK(shared_memory->memory()); - base::AutoLock scoped_lock(lock_); - - // Adjust stats. - handles_acquired_++; - max_handles_acquired_ = std::max(max_handles_acquired_, - handles_acquired_); - - MemoryMap::iterator it = memory_.find(shared_memory->handle()); - // If we don't already have it, duplicated it. - if (it == memory_.end()) { - // Duplicate a new shared memory and track it. - TrackedMemory tracker; - tracker.safe_shared_memory = DuplicateSharedMemory(shared_memory, shm_size); - tracker.reference_count = 1; - tracker.shm_size = shm_size; - memory_[shared_memory->handle()] = tracker; - - // Adjust stats. - handles_consumed_++; - address_space_consumed_ += shm_size; - max_handles_consumed_ = std::max(max_handles_consumed_, - handles_consumed_); - max_address_space_consumed_ = std::max(max_address_space_consumed_, - address_space_consumed_); - return tracker.safe_shared_memory; - } - - // Otherwise, add a reference and return the existing one. - DCHECK(it->second.reference_count); - DCHECK(it->second.safe_shared_memory); - DCHECK(it->second.safe_shared_memory->memory()); - it->second.reference_count++; - return it->second.safe_shared_memory; -} - -void SafeSharedMemoryPool:: - ReleaseSafeSharedMemory(const base::SharedMemoryHandle& handle) { - base::AutoLock scoped_lock(lock_); - - // Adjust stats. - DCHECK_GT(handles_acquired_, 0); - handles_acquired_--; - - MemoryMap::iterator it = memory_.find(handle); - CHECK(it != memory_.end()); - CHECK(it->second.reference_count); - CHECK(it->second.safe_shared_memory); - if (--it->second.reference_count == 0) { - // Adjust stats. - DCHECK_GT(handles_consumed_, 0); - handles_consumed_--; - DCHECK_LE(it->second.shm_size, address_space_consumed_); - address_space_consumed_ -= it->second.shm_size; - // Delete the safe memory and remove it. - delete it->second.safe_shared_memory; - memory_.erase(it); - } -} - -SharedMemory* SafeSharedMemoryPool::DuplicateSharedMemory( - SharedMemory* shared_memory, size_t size) { - // Duplicate the handle. - SharedMemoryHandle duped_shared_memory_handle; - if (!shared_memory->ShareToProcess( - base::GetCurrentProcessHandle(), - &duped_shared_memory_handle)) { - PLOG(ERROR) << "Failed SharedMemory::ShareToProcess"; - LOG(ERROR) << "Total handles acquired " << handles_acquired_; - LOG(ERROR) << "Total handles open " << handles_consumed_; - LOG(ERROR) << "Total address space " << address_space_consumed_; - LOG(ERROR) << "Max handles acquired " << max_handles_acquired_; - LOG(ERROR) << "Max handles open " << max_handles_consumed_; - LOG(ERROR) << "Max address space " << max_address_space_consumed_; - CHECK(false); // Diagnosing a crash. - return NULL; - } - scoped_ptr<SharedMemory> duped_shared_memory( - new SharedMemory(duped_shared_memory_handle, false)); - // Map the shared memory into this process. This validates the size. - if (!duped_shared_memory->Map(size)) { - PLOG(ERROR) << "Failed SharedMemory::Map(" << size << ")"; - LOG(ERROR) << "Total handles acquired " << handles_acquired_; - LOG(ERROR) << "Total handles open " << handles_consumed_; - LOG(ERROR) << "Total address space " << address_space_consumed_; - LOG(ERROR) << "Max handles acquired " << max_handles_acquired_; - LOG(ERROR) << "Max handles open " << max_handles_consumed_; - LOG(ERROR) << "Max address space " << max_address_space_consumed_; - CHECK(false); // Diagnosing a crash. - return NULL; - } - return duped_shared_memory.release(); -} - -} // namespace gpu diff --git a/gpu/command_buffer/service/safe_shared_memory_pool.h b/gpu/command_buffer/service/safe_shared_memory_pool.h deleted file mode 100644 index fed17ff..0000000 --- a/gpu/command_buffer/service/safe_shared_memory_pool.h +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (c) 2011 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 GPU_COMMAND_BUFFER_SERVICE_SAFE_SHARED_MEMORY_POOL_H_ -#define GPU_COMMAND_BUFFER_SERVICE_SAFE_SHARED_MEMORY_POOL_H_ - -#include <map> - -#include "base/basictypes.h" -#include "base/memory/shared_memory.h" -#include "base/synchronization/lock.h" -#include "build/build_config.h" - -namespace gpu { -class SafeSharedMemoryPool; - -// These classes exist to help protect against deletion of shared -// memory that is being used on a worker thread. It's mainly a -// security measure to prevent use-after-free in the browser, due -// to a misbehaving client. That said, this should be removed -// in favor of higher-level reference counting of an appropriate -// opaque 'memory blob' data-structure. - -class ScopedSafeSharedMemory { - public: - base::SharedMemory* shared_memory(); - ScopedSafeSharedMemory(SafeSharedMemoryPool* pool, - base::SharedMemory* memory, - size_t shm_size); - ~ScopedSafeSharedMemory(); - private: - base::SharedMemory* safe_shared_memory_; - base::SharedMemoryHandle original_handle_; - SafeSharedMemoryPool* pool_; - - DISALLOW_COPY_AND_ASSIGN(ScopedSafeSharedMemory); -}; - -class SafeSharedMemoryPool { - public: - SafeSharedMemoryPool(); - virtual ~SafeSharedMemoryPool(); - - private: - friend class ScopedSafeSharedMemory; - - // Acquires and release shared memory. The acquired shared memory - // is guaranteed to live until it is released. - base::SharedMemory* AcquireSafeSharedMemory(base::SharedMemory*, size_t size); - void ReleaseSafeSharedMemory(const base::SharedMemoryHandle&); - - // Utility function to duplicate shared memory. - base::SharedMemory* DuplicateSharedMemory(base::SharedMemory*, size_t size); - - // Track all SharedMemory's that we have already duplicated. - struct TrackedMemory { - base::SharedMemory* safe_shared_memory; - size_t shm_size; - int reference_count; - }; - - typedef std::map<base::SharedMemoryHandle, TrackedMemory> MemoryMap; - MemoryMap memory_; - - // Track usage to diagnose crashes. - int handles_acquired_; - int handles_consumed_; - size_t address_space_consumed_; - int max_handles_acquired_; - int max_handles_consumed_; - size_t max_address_space_consumed_; - - base::Lock lock_; - - DISALLOW_COPY_AND_ASSIGN(SafeSharedMemoryPool); -}; - -} // namespace gfx - -#endif // GPU_COMMAND_BUFFER_SERVICE_SAFE_SHARED_MEMORY_POOL_H_ - diff --git a/gpu/command_buffer_service.gypi b/gpu/command_buffer_service.gypi index 89689cf..cd4662d 100644 --- a/gpu/command_buffer_service.gypi +++ b/gpu/command_buffer_service.gypi @@ -111,8 +111,6 @@ 'command_buffer/service/renderbuffer_manager.cc', 'command_buffer/service/program_cache.h', 'command_buffer/service/program_cache.cc', - 'command_buffer/service/safe_shared_memory_pool.h', - 'command_buffer/service/safe_shared_memory_pool.cc', 'command_buffer/service/shader_manager.h', 'command_buffer/service/shader_manager.cc', 'command_buffer/service/shader_translator.h', |