Fix CVE-2020-26971
This commit is contained in:
parent
d4cf889c2f
commit
6170c4fb7f
311
CVE-2020-26971.patch
Normal file
311
CVE-2020-26971.patch
Normal file
@ -0,0 +1,311 @@
|
||||
From f3b438abf346c7f49b16f800a3af7ff9d1a4edcc Mon Sep 17 00:00:00 2001
|
||||
From: Jeff Gilbert <jgilbert@mozilla.com>
|
||||
Date: Mon, 23 Nov 2020 19:54:41 +0000 (2020-11-24)
|
||||
Subject: [PATCH] CVE-2020-26971
|
||||
|
||||
---
|
||||
dom/canvas/WebGLFramebuffer.cpp | 129 ++++++++++++++----
|
||||
dom/canvas/WebGLTypes.h | 51 ++++++-
|
||||
.../test/webgl-conf/generated-mochitest.ini | 1 -
|
||||
.../test/webgl-conf/mochitest-errata.ini | 2 -
|
||||
4 files changed, 154 insertions(+), 29 deletions(-)
|
||||
|
||||
diff --git a/dom/canvas/WebGLFramebuffer.cpp b/dom/canvas/WebGLFramebuffer.cpp
|
||||
index 155ef0277e..53be7b4570 100644
|
||||
--- a/dom/canvas/WebGLFramebuffer.cpp
|
||||
+++ b/dom/canvas/WebGLFramebuffer.cpp
|
||||
@@ -1263,11 +1263,16 @@ static void GetBackbufferFormats(const WebGLContext* webgl,
|
||||
}
|
||||
|
||||
/*static*/
|
||||
-void WebGLFramebuffer::BlitFramebuffer(WebGLContext* webgl, GLint srcX0,
|
||||
- GLint srcY0, GLint srcX1, GLint srcY1,
|
||||
- GLint dstX0, GLint dstY0, GLint dstX1,
|
||||
- GLint dstY1, GLbitfield mask,
|
||||
- GLenum filter) {
|
||||
+void WebGLFramebuffer::BlitFramebuffer(WebGLContext* webgl, GLint _srcX0,
|
||||
+ GLint _srcY0, GLint _srcX1, GLint _srcY1,
|
||||
+ GLint _dstX0, GLint _dstY0, GLint _dstX1,
|
||||
+ GLint _dstY1, GLbitfield mask,
|
||||
+ GLenum filter) {
|
||||
+ auto srcP0 = ivec2{_srcX0, _srcY0};
|
||||
+ auto srcP1 = ivec2{_srcX1, _srcY1};
|
||||
+ auto dstP0 = ivec2{_dstX0, _dstY0};
|
||||
+ auto dstP1 = ivec2{_dstX1, _dstY1};
|
||||
+
|
||||
const GLbitfield depthAndStencilBits =
|
||||
LOCAL_GL_DEPTH_BUFFER_BIT | LOCAL_GL_STENCIL_BUFFER_BIT;
|
||||
if (bool(mask & depthAndStencilBits) && filter == LOCAL_GL_LINEAR) {
|
||||
@@ -1420,8 +1425,8 @@ void WebGLFramebuffer::BlitFramebuffer(WebGLContext* webgl, GLint srcX0,
|
||||
return;
|
||||
}
|
||||
|
||||
- if (dstX0 != srcX0 || dstX1 != srcX1 || dstY0 != srcY0 || dstY1 != srcY1) {
|
||||
- webgl->ErrorInvalidOperation(
|
||||
+ if (srcP0 != dstP0 || srcP1 != dstP1) {
|
||||
+ webgl->ErrorInvalidOperation(
|
||||
"If the source is multisampled, then the"
|
||||
" source and dest regions must match exactly.");
|
||||
return;
|
||||
@@ -1510,11 +1515,83 @@ void WebGLFramebuffer::BlitFramebuffer(WebGLContext* webgl, GLint srcX0,
|
||||
}
|
||||
|
||||
// -
|
||||
+ // Mutually constrain src and dst rects for eldritch blits.
|
||||
+
|
||||
+ [&]{
|
||||
+ using fvec2 = avec2<float>; // Switch to float, because there's no perfect solution anyway.
|
||||
+
|
||||
+ const auto zero2f = fvec2{0, 0};
|
||||
+ const auto srcSizef = AsVec(srcSize).StaticCast<fvec2>();
|
||||
+ const auto dstSizef = AsVec(dstSize).StaticCast<fvec2>();
|
||||
+
|
||||
+ const auto srcP0f = srcP0.StaticCast<fvec2>();
|
||||
+ const auto srcP1f = srcP1.StaticCast<fvec2>();
|
||||
+ const auto dstP0f = dstP0.StaticCast<fvec2>();
|
||||
+ const auto dstP1f = dstP1.StaticCast<fvec2>();
|
||||
+
|
||||
+ const auto srcRectDiff = srcP1f - srcP0f;
|
||||
+ const auto dstRectDiff = dstP1f - dstP0f;
|
||||
+
|
||||
+ // Skip if zero-sized.
|
||||
+ if (!srcRectDiff.x || !srcRectDiff.y || !dstRectDiff.x || !dstRectDiff.y) {
|
||||
+ srcP0 = srcP1 = dstP0 = dstP1 = {0,0};
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ // Clamp the rect points
|
||||
+ const auto srcQ0 = srcP0f.ClampMinMax(zero2f, srcSizef);
|
||||
+ const auto srcQ1 = srcP1f.ClampMinMax(zero2f, srcSizef);
|
||||
+
|
||||
+ // Normalized to the [0,1] abstact copy rect
|
||||
+ const auto srcQ0Norm = (srcQ0 - srcP0f) / srcRectDiff;
|
||||
+ const auto srcQ1Norm = (srcQ1 - srcP0f) / srcRectDiff;
|
||||
+
|
||||
+ // Map into dst
|
||||
+ const auto srcQ0InDst = dstP0f + srcQ0Norm * dstRectDiff;
|
||||
+ const auto srcQ1InDst = dstP0f + srcQ1Norm * dstRectDiff;
|
||||
+
|
||||
+ // Clamp the rect points
|
||||
+ const auto dstQ0 = srcQ0InDst.ClampMinMax(zero2f, dstSizef);
|
||||
+ const auto dstQ1 = srcQ1InDst.ClampMinMax(zero2f, dstSizef);
|
||||
+
|
||||
+ // Alright, time to go back to src!
|
||||
+ // Normalized to the [0,1] abstact copy rect
|
||||
+ const auto dstQ0Norm = (dstQ0 - dstP0f) / dstRectDiff;
|
||||
+ const auto dstQ1Norm = (dstQ1 - dstP0f) / dstRectDiff;
|
||||
+
|
||||
+ // Map into src
|
||||
+ const auto dstQ0InSrc = srcP0f + dstQ0Norm * srcRectDiff;
|
||||
+ const auto dstQ1InSrc = srcP0f + dstQ1Norm * srcRectDiff;
|
||||
+
|
||||
+ const auto srcQ0Constrained = dstQ0InSrc.ClampMinMax(zero2f, srcSizef);
|
||||
+ const auto srcQ1Constrained = dstQ1InSrc.ClampMinMax(zero2f, srcSizef);
|
||||
+
|
||||
+ // Round, don't floor:
|
||||
+ srcP0 = (srcQ0Constrained + 0.5).StaticCast<ivec2>();
|
||||
+ srcP1 = (srcQ1Constrained + 0.5).StaticCast<ivec2>();
|
||||
+ dstP0 = (dstQ0 + 0.5).StaticCast<ivec2>();
|
||||
+ dstP1 = (dstQ1 + 0.5).StaticCast<ivec2>();
|
||||
+ }();
|
||||
+
|
||||
+ bool inBounds = true;
|
||||
+ inBounds &= ( srcP0 == srcP0.Clamp({0,0}, AsVec(srcSize)) );
|
||||
+ inBounds &= ( srcP1 == srcP1.Clamp({0,0}, AsVec(srcSize)) );
|
||||
+ inBounds &= ( dstP0 == dstP0.Clamp({0,0}, AsVec(dstSize)) );
|
||||
+ inBounds &= ( dstP1 == dstP1.Clamp({0,0}, AsVec(dstSize)) );
|
||||
+ if (!inBounds) {
|
||||
+ webgl->ErrorImplementationBug("Subrects still not within src and dst after constraining.");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ // -
|
||||
+ // Execute as constrained
|
||||
+
|
||||
|
||||
const auto& gl = webgl->gl;
|
||||
const ScopedDrawCallWrapper wrapper(*webgl);
|
||||
- gl->fBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1,
|
||||
- mask, filter);
|
||||
+
|
||||
+ gl->fBlitFramebuffer(srcP0.x, srcP0.y, srcP1.x, srcP1.y, dstP0.x, dstP0.y,
|
||||
+ dstP1.x, dstP1.y, mask, filter);
|
||||
|
||||
// -
|
||||
|
||||
@@ -1557,13 +1634,14 @@ void WebGLFramebuffer::BlitFramebuffer(WebGLContext* webgl, GLint srcX0,
|
||||
|
||||
if (srcColorFormat->isSRGB) {
|
||||
// srgb -> linear
|
||||
- gl->fBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, srcX0, srcY0, srcX1,
|
||||
- srcY1, LOCAL_GL_COLOR_BUFFER_BIT,
|
||||
- LOCAL_GL_NEAREST);
|
||||
+ gl->fBlitFramebuffer(srcP0.x, srcP0.y, srcP1.x, srcP1.y, srcP0.x,
|
||||
+ srcP0.y, srcP1.x, srcP1.y,
|
||||
+ LOCAL_GL_COLOR_BUFFER_BIT, LOCAL_GL_NEAREST);
|
||||
} else {
|
||||
// linear -> srgb
|
||||
- gl->fBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1,
|
||||
- dstY1, LOCAL_GL_COLOR_BUFFER_BIT, filter);
|
||||
+ gl->fBlitFramebuffer(srcP0.x, srcP0.y, srcP1.x, srcP1.y, dstP0.x,
|
||||
+ dstP0.y, dstP1.x, dstP1.y,
|
||||
+ LOCAL_GL_COLOR_BUFFER_BIT, filter);
|
||||
}
|
||||
|
||||
const auto& blitHelper = *gl->BlitHelper();
|
||||
@@ -1577,13 +1655,14 @@ void WebGLFramebuffer::BlitFramebuffer(WebGLContext* webgl, GLint srcX0,
|
||||
|
||||
if (srcColorFormat->isSRGB) {
|
||||
// srgb -> linear
|
||||
- gl->fBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1,
|
||||
- dstY1, LOCAL_GL_COLOR_BUFFER_BIT, filter);
|
||||
+ gl->fBlitFramebuffer(srcP0.x, srcP0.y, srcP1.x, srcP1.y, dstP0.x,
|
||||
+ dstP0.y, dstP1.x, dstP1.y,
|
||||
+ LOCAL_GL_COLOR_BUFFER_BIT, filter);
|
||||
} else {
|
||||
// linear -> srgb
|
||||
- gl->fBlitFramebuffer(dstX0, dstY0, dstX1, dstY1, dstX0, dstY0, dstX1,
|
||||
- dstY1, LOCAL_GL_COLOR_BUFFER_BIT,
|
||||
- LOCAL_GL_NEAREST);
|
||||
+ gl->fBlitFramebuffer(dstP0.x, dstP0.y, dstP1.x, dstP1.y, dstP0.x,
|
||||
+ dstP0.y, dstP1.x, dstP1.y,
|
||||
+ LOCAL_GL_COLOR_BUFFER_BIT, LOCAL_GL_NEAREST);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1598,13 +1677,15 @@ void WebGLFramebuffer::BlitFramebuffer(WebGLContext* webgl, GLint srcX0,
|
||||
if (webgl->mRasterizerDiscardEnabled) {
|
||||
gl->fDisable(LOCAL_GL_RASTERIZER_DISCARD);
|
||||
}
|
||||
- const WebGLContext::ScissorRect dstRect = {
|
||||
- std::min(dstX0, dstX1), std::min(dstY0, dstY1), abs(dstX1 - dstX0),
|
||||
- abs(dstY1 - dstY0)};
|
||||
+ const auto dstRectMin = MinExtents(dstP0, dstP1);
|
||||
+ const auto dstRectMax = MaxExtents(dstP0, dstP1);
|
||||
+ const auto dstRectSize = dstRectMax - dstRectMin;
|
||||
+ const WebGLContext::ScissorRect dstRect = {dstRectMin.x, dstRectMin.y,
|
||||
+ dstRectSize.x, dstRectSize.y};
|
||||
+
|
||||
dstRect.Apply(*gl);
|
||||
gl->fClearColor(0, 0, 0, 1);
|
||||
-
|
||||
- webgl->DoColorMask(0x8);
|
||||
+ webgl->DoColorMask(1 << 3);
|
||||
gl->fClear(LOCAL_GL_COLOR_BUFFER_BIT);
|
||||
|
||||
if (!webgl->mScissorTestEnabled) {
|
||||
diff --git a/dom/canvas/WebGLTypes.h b/dom/canvas/WebGLTypes.h
|
||||
index f04184e289..38006ab37a 100644
|
||||
--- a/dom/canvas/WebGLTypes.h
|
||||
+++ b/dom/canvas/WebGLTypes.h
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "GLDefs.h"
|
||||
#include "mozilla/Casting.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
+#include "mozilla/MathAlgorithms.h"
|
||||
#include "mozilla/Range.h"
|
||||
#include "mozilla/RefCounted.h"
|
||||
#include "mozilla/gfx/Point.h"
|
||||
@@ -391,8 +392,9 @@ struct WebGLContextOptions {
|
||||
|
||||
// -
|
||||
|
||||
-template <typename T>
|
||||
+template <typename _T>
|
||||
struct avec2 {
|
||||
+ using T = _T;
|
||||
T x = T();
|
||||
T y = T();
|
||||
|
||||
@@ -418,10 +420,54 @@ struct avec2 {
|
||||
|
||||
bool operator==(const avec2& rhs) const { return x == rhs.x && y == rhs.y; }
|
||||
bool operator!=(const avec2& rhs) const { return !(*this == rhs); }
|
||||
+
|
||||
+#define _(OP) \
|
||||
+ avec2 operator OP(const avec2& rhs) const { \
|
||||
+ return {x OP rhs.x, y OP rhs.y}; \
|
||||
+ } \
|
||||
+ avec2 operator OP(const T rhs) const { return {x OP rhs, y OP rhs}; }
|
||||
+
|
||||
+ _(+)
|
||||
+ _(-)
|
||||
+ _(*)
|
||||
+ _(/)
|
||||
+
|
||||
+#undef _
|
||||
+
|
||||
+ avec2 Clamp(const avec2& min, const avec2& max) const {
|
||||
+ return {mozilla::Clamp(x, min.x, max.x), mozilla::Clamp(y, min.y, max.y)};
|
||||
+ }
|
||||
+
|
||||
+ // mozilla::Clamp doesn't work on floats, so be clear that this is a min+max
|
||||
+ // helper.
|
||||
+ avec2 ClampMinMax(const avec2& min, const avec2& max) const {
|
||||
+ const auto ClampScalar = [](const T v, const T min, const T max) {
|
||||
+ return std::max(min, std::min(v, max));
|
||||
+ };
|
||||
+ return {ClampScalar(x, min.x, max.x), ClampScalar(y, min.y, max.y)};
|
||||
+ }
|
||||
+
|
||||
+ template <typename U>
|
||||
+ U StaticCast() const {
|
||||
+ return {static_cast<typename U::T>(x), static_cast<typename U::T>(y)};
|
||||
+ }
|
||||
};
|
||||
|
||||
-template <typename T>
|
||||
+template<typename T>
|
||||
+avec2<T> MinExtents(const avec2<T>& a, const avec2<T>& b) {
|
||||
+ return {std::min(a.x, b.x), std::min(a.y, b.y)};
|
||||
+}
|
||||
+
|
||||
+template<typename T>
|
||||
+avec2<T> MaxExtents(const avec2<T>& a, const avec2<T>& b) {
|
||||
+ return {std::max(a.x, b.x), std::max(a.y, b.y)};
|
||||
+}
|
||||
+
|
||||
+// -
|
||||
+
|
||||
+template <typename _T>
|
||||
struct avec3 {
|
||||
+ using T = _T;
|
||||
T x = T();
|
||||
T y = T();
|
||||
T z = T();
|
||||
@@ -454,6 +500,7 @@ typedef avec3<int32_t> ivec3;
|
||||
typedef avec2<uint32_t> uvec2;
|
||||
typedef avec3<uint32_t> uvec3;
|
||||
|
||||
+inline ivec2 AsVec(const gfx::IntSize& s) { return {s.width, s.height}; }
|
||||
// -
|
||||
|
||||
namespace webgl {
|
||||
diff --git a/dom/canvas/test/webgl-conf/generated-mochitest.ini b/dom/canvas/test/webgl-conf/generated-mochitest.ini
|
||||
index 0d47a180bd..246f83c465 100644
|
||||
--- a/dom/canvas/test/webgl-conf/generated-mochitest.ini
|
||||
+++ b/dom/canvas/test/webgl-conf/generated-mochitest.ini
|
||||
@@ -5328,7 +5328,6 @@ subsuite = webgl2-core
|
||||
fail-if = (os == 'linux')
|
||||
[generated/test_2_conformance2__rendering__blitframebuffer-outside-readbuffer.html]
|
||||
subsuite = webgl2-core
|
||||
-fail-if = (os == 'linux') || (os == 'mac')
|
||||
[generated/test_2_conformance2__rendering__blitframebuffer-r11f-g11f-b10f.html]
|
||||
subsuite = webgl2-core
|
||||
[generated/test_2_conformance2__rendering__blitframebuffer-resolve-to-back-buffer.html]
|
||||
diff --git a/dom/canvas/test/webgl-conf/mochitest-errata.ini b/dom/canvas/test/webgl-conf/mochitest-errata.ini
|
||||
index 2ef5365c9e..903e721b02 100644
|
||||
--- a/dom/canvas/test/webgl-conf/mochitest-errata.ini
|
||||
+++ b/dom/canvas/test/webgl-conf/mochitest-errata.ini
|
||||
@@ -335,8 +335,6 @@ skip-if = (os == 'android')
|
||||
skip-if = (os == 'win') || (os == 'mac')
|
||||
[generated/test_2_conformance2__glsl3__tricky-loop-conditions.html]
|
||||
fail-if = (os == 'win')
|
||||
-[generated/test_2_conformance2__rendering__blitframebuffer-outside-readbuffer.html]
|
||||
-fail-if = (os == 'linux') || (os == 'mac')
|
||||
[generated/test_2_conformance2__textures__misc__tex-srgb-mipmap.html]
|
||||
fail-if = (os == 'mac')
|
||||
[generated/test_2_conformance2__textures__video__tex-3d-r11f_g11f_b10f-rgb-float.html]
|
||||
--
|
||||
2.27.0
|
||||
|
||||
@ -88,7 +88,7 @@
|
||||
Summary: Mozilla Firefox Web browser
|
||||
Name: firefox
|
||||
Version: 79.0
|
||||
Release: 19
|
||||
Release: 20
|
||||
URL: https://www.mozilla.org/firefox/
|
||||
License: MPLv1.1 or GPLv2+ or LGPLv2+
|
||||
Source0: https://archive.mozilla.org/pub/firefox/releases/%{version}/source/firefox-%{version}.source.tar.xz
|
||||
@ -198,6 +198,7 @@ Patch654: CVE-2022-22755.patch
|
||||
Patch655: CVE-2022-1802.patch
|
||||
Patch656: CVE-2023-44488.patch
|
||||
Patch657: CVE-2020-26950.patch
|
||||
Patch658: CVE-2020-26971.patch
|
||||
|
||||
%if %{?system_nss}
|
||||
BuildRequires: pkgconfig(nspr) >= %{nspr_version} pkgconfig(nss) >= %{nss_version}
|
||||
@ -390,6 +391,7 @@ tar -xf %{SOURCE3}
|
||||
%patch655 -p1
|
||||
%patch656 -p1
|
||||
%patch657 -p1
|
||||
%patch658 -p1
|
||||
|
||||
%{__rm} -f .mozconfig
|
||||
%{__cp} %{SOURCE10} .mozconfig
|
||||
@ -838,8 +840,11 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Tue May 07 2024 lvfei <lvfei@kylinos.cn> - 79.0-20
|
||||
- Fix CVE-2020-26971
|
||||
|
||||
* Wed Apr 24 2024 lvfei <lvfei@kylinos.cn> - 79.0-19
|
||||
- Fif CVE-2020-26950
|
||||
- Fix CVE-2020-26950
|
||||
|
||||
* Fri Apr 19 2024 lvfei <lvfei@kylinos.cn> - 79.0-18
|
||||
- Fix CVE-2023-44488
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user