diff options
author | Shahbaz Youssefi <syoussefi@chromium.org> | 2023-12-05 13:36:53 -0500 |
---|---|---|
committer | Michael BrĂ¼ning <michael.bruning@qt.io> | 2024-01-22 10:33:06 +0000 |
commit | aac73f3a715655476ce5b347a9614d1ca0ba9b93 (patch) | |
tree | 9160c2815f123efdf669ee4dbb4824920600e6e5 | |
parent | c8088aea77818f87d42f709ddcb743b907c38e9c (diff) |
[Backport] CVE-2024-0222: Use after free in ANGLE
Manual cherry-pick of patch originally reviewed on
https://chromium-review.googlesource.com/c/angle/angle/+/5143829:
M120: Vulkan: Don't crash when glCopyTexImage2D redefines itself
The Vulkan backend marks a level being redefined as such before doing
the copy. If a single-level texture was being redefined, it releases it
so it can be immediately reallocated. If the source of the copy is the
same texture, this causes a crash.
This can be properly supported by using a temp image to do the copy, but
that is not implemented in this change.
Bug: chromium:1501798
Change-Id: I3a902b1e9eec41afd385d9c75a8c95dc986070a8
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/5143829
Reviewed-by: Cody Northrop <cnorthrop@google.com>
Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/532069
Reviewed-by: Michal Klocek <michal.klocek@qt.io>
-rw-r--r-- | chromium/third_party/angle/src/libANGLE/renderer/vulkan/TextureVk.cpp | 23 |
1 files changed, 22 insertions, 1 deletions
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/TextureVk.cpp b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/TextureVk.cpp index 1950375b9b1..a098da4bfd3 100644 --- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/TextureVk.cpp +++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/TextureVk.cpp @@ -466,8 +466,28 @@ angle::Result TextureVk::copyImage(const gl::Context *context, gl::GetInternalFormatInfo(internalFormat, GL_UNSIGNED_BYTE); const vk::Format &vkFormat = renderer->getFormat(internalFormatInfo.sizedInternalFormat); + // The texture level being redefined might be the same as the one bound to the framebuffer. + // This _could_ be supported by using a temp image before redefining the level (and potentially + // discarding the image). However, this is currently unimplemented. + FramebufferVk *framebufferVk = vk::GetImpl(source); + RenderTargetVk *colorReadRT = framebufferVk->getColorReadRenderTarget(); + vk::ImageHelper *srcImage = &colorReadRT->getImageForCopy(); + const bool isCubeMap = index.getType() == gl::TextureType::CubeMap; + gl::LevelIndex levelIndex(getNativeImageIndex(index).getLevelIndex()); + const uint32_t layerIndex = index.hasLayer() ? index.getLayerIndex() : 0; + const uint32_t redefinedFace = isCubeMap ? layerIndex : 0; + const uint32_t sourceFace = isCubeMap ? colorReadRT->getLayerIndex() : 0; + const bool isSelfCopy = mImage == srcImage && levelIndex == colorReadRT->getLevelIndex() && + redefinedFace == sourceFace; + ANGLE_TRY(redefineLevel(context, index, vkFormat, newImageSize)); + if (isSelfCopy) + { + UNIMPLEMENTED(); + return angle::Result::Continue; + } + return copySubImageImpl(context, index, gl::Offset(0, 0, 0), sourceArea, internalFormatInfo, source); } @@ -1393,7 +1413,8 @@ angle::Result TextureVk::redefineLevel(const gl::Context *context, mImage->getLevelCount() == 1 && mImage->getBaseLevel() == levelIndexGL; // If incompatible, and redefining the single-level image, release it so it can be - // recreated immediately. This is an optimization to avoid an extra copy. + // recreated immediately. This is needed so that the texture can be reallocated with + // the correct format/size. if (!isCompatibleRedefinition && isUpdateToSingleLevelImage) { releaseImage(contextVk); |