From b07ea69aba68d08745bb1cda7f75cb60a5b46077 Mon Sep 17 00:00:00 2001 From: lvfei Date: Tue, 7 May 2024 20:21:59 +0800 Subject: [PATCH 1/2] Fix CVE-2020-26971 --- CVE-2020-26971.patch | 311 +++++++++++++++++++++++++++++++++++++++++++ firefox.spec | 9 +- 2 files changed, 318 insertions(+), 2 deletions(-) create mode 100644 CVE-2020-26971.patch diff --git a/CVE-2020-26971.patch b/CVE-2020-26971.patch new file mode 100644 index 0000000..8aa70eb --- /dev/null +++ b/CVE-2020-26971.patch @@ -0,0 +1,311 @@ +From f3b438abf346c7f49b16f800a3af7ff9d1a4edcc Mon Sep 17 00:00:00 2001 +From: lvfei +Date: Tue, 7 May 2024 20:05:03 +0800 +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; // Switch to float, because there's no perfect solution anyway. ++ ++ const auto zero2f = fvec2{0, 0}; ++ const auto srcSizef = AsVec(srcSize).StaticCast(); ++ const auto dstSizef = AsVec(dstSize).StaticCast(); ++ ++ const auto srcP0f = srcP0.StaticCast(); ++ const auto srcP1f = srcP1.StaticCast(); ++ const auto dstP0f = dstP0.StaticCast(); ++ const auto dstP1f = dstP1.StaticCast(); ++ ++ 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(); ++ srcP1 = (srcQ1Constrained + 0.5).StaticCast(); ++ dstP0 = (dstQ0 + 0.5).StaticCast(); ++ dstP1 = (dstQ1 + 0.5).StaticCast(); ++ }(); ++ ++ 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 ++template + 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 ++ U StaticCast() const { ++ return {static_cast(x), static_cast(y)}; ++ } + }; + +-template ++template ++avec2 MinExtents(const avec2& a, const avec2& b) { ++ return {std::min(a.x, b.x), std::min(a.y, b.y)}; ++} ++ ++template ++avec2 MaxExtents(const avec2& a, const avec2& b) { ++ return {std::max(a.x, b.x), std::max(a.y, b.y)}; ++} ++ ++// - ++ ++template + struct avec3 { ++ using T = _T; + T x = T(); + T y = T(); + T z = T(); +@@ -454,6 +500,7 @@ typedef avec3 ivec3; + typedef avec2 uvec2; + typedef avec3 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 + diff --git a/firefox.spec b/firefox.spec index ba0547d..4fd4134 100644 --- a/firefox.spec +++ b/firefox.spec @@ -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 - 79.0-20 +- Fix CVE-2020-26971 + * Wed Apr 24 2024 lvfei - 79.0-19 -- Fif CVE-2020-26950 +- Fix CVE-2020-26950 * Fri Apr 19 2024 lvfei - 79.0-18 - Fix CVE-2023-44488 -- Gitee From f4020d5b7fa1e1f2ec1c2a858f785169db217994 Mon Sep 17 00:00:00 2001 From: lvfei Date: Tue, 7 May 2024 12:26:18 +0000 Subject: [PATCH 2/2] update CVE-2020-26971.patch. Signed-off-by: lvfei --- CVE-2020-26971.patch | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CVE-2020-26971.patch b/CVE-2020-26971.patch index 8aa70eb..8e3383e 100644 --- a/CVE-2020-26971.patch +++ b/CVE-2020-26971.patch @@ -1,6 +1,6 @@ From f3b438abf346c7f49b16f800a3af7ff9d1a4edcc Mon Sep 17 00:00:00 2001 -From: lvfei -Date: Tue, 7 May 2024 20:05:03 +0800 +From: Jeff Gilbert +Date: Mon, 23 Nov 2020 19:54:41 +0000 (2020-11-24) Subject: [PATCH] CVE-2020-26971 --- -- Gitee