diff --git a/CVE-2020-15969.patch b/CVE-2020-15969.patch new file mode 100644 index 0000000000000000000000000000000000000000..9266f40053077cb3d4dc03629bd517be4166ad74 --- /dev/null +++ b/CVE-2020-15969.patch @@ -0,0 +1,51 @@ +# HG changeset patch +# User Dan Minor +# Date 1600897949 0 +# Wed Sep 23 21:52:29 2020 +0000 +# Node ID ed2a659e965f27943d9b0c15d6e78d14e1ce9cb2 +# Parent 7b2de9e57a768d949b569ac83fe5d58147e731b5 +Bug 1666570 - Cherrypick ffed0925f27d404173c1e3e750d818f432d2c019 from usrsctp; r=drno + +Differential Revision: https://phabricator.services.mozilla.com/D91047 + +diff -r 7b2de9e57a76 -r ed2a659e965f netwerk/sctp/src/netinet/sctp_indata.c +--- a/netwerk/sctp/src/netinet/sctp_indata.c Wed Sep 23 19:42:19 2020 +0000 ++++ b/netwerk/sctp/src/netinet/sctp_indata.c Wed Sep 23 21:52:29 2020 +0000 +@@ -1664,6 +1664,7 @@ sctp_process_a_data_chunk(struct sctp_tc + /* Process a data chunk */ + /* struct sctp_tmit_chunk *chk; */ + struct sctp_tmit_chunk *chk; ++ struct sctp_stream_in *strm; + uint32_t tsn, fsn, gap, mid; + struct mbuf *dmbuf; + int the_len; +@@ -2296,12 +2297,13 @@ finish_express_del: + /* All can be removed */ + TAILQ_FOREACH_SAFE(control, &asoc->pending_reply_queue, next, ncontrol) { + TAILQ_REMOVE(&asoc->pending_reply_queue, control, next); ++ strm = &asoc->strmin[control->sinfo_stream]; + sctp_queue_data_to_stream(stcb, asoc, control, abort_flag, &need_reasm_check); + if (*abort_flag) { + return (0); + } + if (need_reasm_check) { +- (void)sctp_deliver_reasm_check(stcb, asoc, &asoc->strmin[control->sinfo_stream], SCTP_READ_LOCK_NOT_HELD); ++ (void)sctp_deliver_reasm_check(stcb, asoc, strm, SCTP_READ_LOCK_NOT_HELD); + need_reasm_check = 0; + } + } +@@ -2316,12 +2318,13 @@ finish_express_del: + * control->sinfo_tsn > liste->tsn + */ + TAILQ_REMOVE(&asoc->pending_reply_queue, control, next); ++ strm = &asoc->strmin[control->sinfo_stream]; + sctp_queue_data_to_stream(stcb, asoc, control, abort_flag, &need_reasm_check); + if (*abort_flag) { + return (0); + } + if (need_reasm_check) { +- (void)sctp_deliver_reasm_check(stcb, asoc, &asoc->strmin[control->sinfo_stream], SCTP_READ_LOCK_NOT_HELD); ++ (void)sctp_deliver_reasm_check(stcb, asoc, strm, SCTP_READ_LOCK_NOT_HELD); + need_reasm_check = 0; + } + } diff --git a/CVE-2020-15999.patch b/CVE-2020-15999.patch new file mode 100644 index 0000000000000000000000000000000000000000..754bd385b52bcf234dbc169c1e02ca70d3d10635 --- /dev/null +++ b/CVE-2020-15999.patch @@ -0,0 +1,45 @@ +# HG changeset patch +# User Werner Lemberg +# Date 1603223819 0 +# Tue Oct 20 19:56:59 2020 +0000 +# Node ID 5c356dd9b0f31f612ce90b1f35b14d8cdb0b4ecb +# Parent a2ed93bf78d53309eb234b72ce0bf60ad93a3ac3 +Bug 1672223 - [sfnt] Fix heap buffer overflow. r=jfkthame + +This is CVE-2020-15999. + +* src/sfnt/pngshim.c (Load_SBit_Png): Test bitmap size earlier. + +Differential Revision: https://phabricator.services.mozilla.com/D94153 + +diff -r a2ed93bf78d5 -r 5c356dd9b0f3 modules/freetype2/src/sfnt/pngshim.c +--- a/modules/freetype2/src/sfnt/pngshim.c Tue Oct 20 21:14:51 2020 +0000 ++++ b/modules/freetype2/src/sfnt/pngshim.c Tue Oct 20 19:56:59 2020 +0000 +@@ -328,6 +328,13 @@ + + if ( populate_map_and_metrics ) + { ++ /* reject too large bitmaps similarly to the rasterizer */ ++ if ( imgHeight > 0x7FFF || imgWidth > 0x7FFF ) ++ { ++ error = FT_THROW( Array_Too_Large ); ++ goto DestroyExit; ++ } ++ + metrics->width = (FT_UShort)imgWidth; + metrics->height = (FT_UShort)imgHeight; + +@@ -336,13 +343,6 @@ + map->pixel_mode = FT_PIXEL_MODE_BGRA; + map->pitch = (int)( map->width * 4 ); + map->num_grays = 256; +- +- /* reject too large bitmaps similarly to the rasterizer */ +- if ( map->rows > 0x7FFF || map->width > 0x7FFF ) +- { +- error = FT_THROW( Array_Too_Large ); +- goto DestroyExit; +- } + } + + /* convert palette/gray image to rgb */ diff --git a/CVE-2020-16012.patch b/CVE-2020-16012.patch new file mode 100644 index 0000000000000000000000000000000000000000..ba7ad9adacb6951b136674d4615d049f8531e6aa --- /dev/null +++ b/CVE-2020-16012.patch @@ -0,0 +1,406 @@ +# HG changeset patch +# User Lee Salzman +# Date 1601995009 0 +# Tue Oct 06 14:36:49 2020 +0000 +# Node ID 48c0f5033c286bd515b6f16e0905ff4ca94faf98 +# Parent 5bc02423412647e3ee9a0681b38e418a10901601 +Bug 1642028 - cherry-pick Skia blitting cleanups. r=jrmuizel + +Differential Revision: https://phabricator.services.mozilla.com/D92476 + +diff -r 5bc024234126 -r 48c0f5033c28 gfx/skia/skia/src/opts/SkBlitRow_opts.h +--- a/gfx/skia/skia/src/opts/SkBlitRow_opts.h Tue Oct 06 16:58:11 2020 +0000 ++++ b/gfx/skia/skia/src/opts/SkBlitRow_opts.h Tue Oct 06 14:36:49 2020 +0000 +@@ -58,37 +58,114 @@ + + return _mm256_add_epi32(src, _mm256_or_si256(rb, ga)); + } ++#endif + +-#elif SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2 ++#if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2 + #include + + static inline __m128i SkPMSrcOver_SSE2(const __m128i& src, const __m128i& dst) { +- auto SkAlphaMulQ_SSE2 = [](const __m128i& c, const __m128i& scale) { +- const __m128i mask = _mm_set1_epi32(0xFF00FF); +- __m128i s = _mm_or_si128(_mm_slli_epi32(scale, 16), scale); ++ __m128i scale = _mm_sub_epi32(_mm_set1_epi32(256), ++ _mm_srli_epi32(src, 24)); ++ __m128i scale_x2 = _mm_or_si128(_mm_slli_epi32(scale, 16), scale); ++ ++ __m128i rb = _mm_and_si128(_mm_set1_epi32(0x00ff00ff), dst); ++ rb = _mm_mullo_epi16(rb, scale_x2); ++ rb = _mm_srli_epi16(rb, 8); + +- // uint32_t rb = ((c & mask) * scale) >> 8 +- __m128i rb = _mm_and_si128(mask, c); +- rb = _mm_mullo_epi16(rb, s); +- rb = _mm_srli_epi16(rb, 8); ++ __m128i ga = _mm_srli_epi16(dst, 8); ++ ga = _mm_mullo_epi16(ga, scale_x2); ++ ga = _mm_andnot_si128(_mm_set1_epi32(0x00ff00ff), ga); ++ ++ return _mm_add_epi32(src, _mm_or_si128(rb, ga)); ++ } ++#endif + +- // uint32_t ag = ((c >> 8) & mask) * scale +- __m128i ag = _mm_srli_epi16(c, 8); +- ag = _mm_mullo_epi16(ag, s); +- +- // (rb & mask) | (ag & ~mask) +- ag = _mm_andnot_si128(mask, ag); +- return _mm_or_si128(rb, ag); ++#if defined(SK_ARM_HAS_NEON) ++ #include ++ // SkMulDiv255Round() applied to each lane. ++ static inline uint8x8_t SkMulDiv255Round_neon8(uint8x8_t x, uint8x8_t y) { ++ uint16x8_t prod = vmull_u8(x, y); ++ return vraddhn_u16(prod, vrshrq_n_u16(prod, 8)); ++ } ++ static inline uint8x8x4_t SkPMSrcOver_neon8(uint8x8x4_t dst, uint8x8x4_t src) { ++ uint8x8_t nalphas = vmvn_u8(src.val[3]); // 256 - alpha ++ return { ++ vadd_u8(src.val[0], SkMulDiv255Round_neon8(nalphas, dst.val[0])), ++ vadd_u8(src.val[1], SkMulDiv255Round_neon8(nalphas, dst.val[1])), ++ vadd_u8(src.val[2], SkMulDiv255Round_neon8(nalphas, dst.val[2])), ++ vadd_u8(src.val[3], SkMulDiv255Round_neon8(nalphas, dst.val[3])), + }; +- return _mm_add_epi32(src, +- SkAlphaMulQ_SSE2(dst, _mm_sub_epi32(_mm_set1_epi32(256), +- _mm_srli_epi32(src, 24)))); ++ } ++ // Variant assuming dst and src contain the color components of two consecutive pixels. ++ static inline uint8x8_t SkPMSrcOver_neon2(uint8x8_t dst, uint8x8_t src) { ++ const uint8x8_t alpha_indices = vcreate_u8(0x0707070703030303); ++ uint8x8_t nalphas = vmvn_u8(vtbl1_u8(src, alpha_indices)); ++ return vadd_u8(src, SkMulDiv255Round_neon8(nalphas, dst)); + } + #endif + + namespace SK_OPTS_NS { + ++/*not static*/ ++inline void blit_row_s32a_opaque(SkPMColor* dst, const SkPMColor* src, int len, U8CPU alpha) { ++ SkASSERT(alpha == 0xFF); ++ sk_msan_assert_initialized(src, src+len); ++ ++#if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_AVX2 ++ while (len >= 8) { ++ _mm256_storeu_si256((__m256i*)dst, ++ SkPMSrcOver_AVX2(_mm256_loadu_si256((const __m256i*)src), ++ _mm256_loadu_si256((const __m256i*)dst))); ++ src += 8; ++ dst += 8; ++ len -= 8; ++ } ++#endif ++ ++#if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2 ++ while (len >= 4) { ++ _mm_storeu_si128((__m128i*)dst, SkPMSrcOver_SSE2(_mm_loadu_si128((const __m128i*)src), ++ _mm_loadu_si128((const __m128i*)dst))); ++ src += 4; ++ dst += 4; ++ len -= 4; ++ } ++#endif ++ ++#if defined(SK_ARM_HAS_NEON) ++ while (len >= 8) { ++ vst4_u8((uint8_t*)dst, SkPMSrcOver_neon8(vld4_u8((const uint8_t*)dst), ++ vld4_u8((const uint8_t*)src))); ++ src += 8; ++ dst += 8; ++ len -= 8; ++ } ++ ++ while (len >= 2) { ++ vst1_u8((uint8_t*)dst, SkPMSrcOver_neon2(vld1_u8((const uint8_t*)dst), ++ vld1_u8((const uint8_t*)src))); ++ src += 2; ++ dst += 2; ++ len -= 2; ++ } ++ ++ if (len != 0) { ++ uint8x8_t result = SkPMSrcOver_neon2(vcreate_u8((uint64_t)*dst), ++ vcreate_u8((uint64_t)*src)); ++ vst1_lane_u32(dst, vreinterpret_u32_u8(result), 0); ++ } ++ return; ++#endif ++ ++ while (len --> 0) { ++ *dst = SkPMSrcOver(*src, *dst); ++ src++; ++ dst++; ++ } ++} ++ + // Blend constant color over count src pixels, writing into dst. ++/*not static*/ + inline void blit_row_color32(SkPMColor* dst, const SkPMColor* src, int count, SkPMColor color) { + constexpr int N = 4; // 8, 16 also reasonable choices + using U32 = skvx::Vec< N, uint32_t>; +@@ -120,259 +197,6 @@ + } + } + +-#if defined(SK_ARM_HAS_NEON) +- +-// Return a uint8x8_t value, r, computed as r[i] = SkMulDiv255Round(x[i], y[i]), where r[i], x[i], +-// y[i] are the i-th lanes of the corresponding NEON vectors. +-static inline uint8x8_t SkMulDiv255Round_neon8(uint8x8_t x, uint8x8_t y) { +- uint16x8_t prod = vmull_u8(x, y); +- return vraddhn_u16(prod, vrshrq_n_u16(prod, 8)); +-} +- +-// The implementations of SkPMSrcOver below perform alpha blending consistently with +-// SkMulDiv255Round. They compute the color components (numbers in the interval [0, 255]) as: +-// +-// result_i = src_i + rint(g(src_alpha, dst_i)) +-// +-// where g(x, y) = ((255.0 - x) * y) / 255.0 and rint rounds to the nearest integer. +- +-// In this variant of SkPMSrcOver each NEON register, dst.val[i], src.val[i], contains the value +-// of the same color component for 8 consecutive pixels. The result of this function follows the +-// same convention. +-static inline uint8x8x4_t SkPMSrcOver_neon8(uint8x8x4_t dst, uint8x8x4_t src) { +- uint8x8_t nalphas = vmvn_u8(src.val[3]); +- uint8x8x4_t result; +- result.val[0] = vadd_u8(src.val[0], SkMulDiv255Round_neon8(nalphas, dst.val[0])); +- result.val[1] = vadd_u8(src.val[1], SkMulDiv255Round_neon8(nalphas, dst.val[1])); +- result.val[2] = vadd_u8(src.val[2], SkMulDiv255Round_neon8(nalphas, dst.val[2])); +- result.val[3] = vadd_u8(src.val[3], SkMulDiv255Round_neon8(nalphas, dst.val[3])); +- return result; +-} +- +-// In this variant of SkPMSrcOver dst and src contain the color components of two consecutive +-// pixels. The return value follows the same convention. +-static inline uint8x8_t SkPMSrcOver_neon2(uint8x8_t dst, uint8x8_t src) { +- const uint8x8_t alpha_indices = vcreate_u8(0x0707070703030303); +- uint8x8_t nalphas = vmvn_u8(vtbl1_u8(src, alpha_indices)); +- return vadd_u8(src, SkMulDiv255Round_neon8(nalphas, dst)); +-} +- +-#endif +- +-/*not static*/ inline +-void blit_row_s32a_opaque(SkPMColor* dst, const SkPMColor* src, int len, U8CPU alpha) { +- SkASSERT(alpha == 0xFF); +- sk_msan_assert_initialized(src, src+len); +-// Require AVX2 because of AVX2 integer calculation intrinsics in SrcOver +-#if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_AVX2 +- while (len >= 32) { +- // Load 32 source pixels. +- auto s0 = _mm256_loadu_si256((const __m256i*)(src) + 0), +- s1 = _mm256_loadu_si256((const __m256i*)(src) + 1), +- s2 = _mm256_loadu_si256((const __m256i*)(src) + 2), +- s3 = _mm256_loadu_si256((const __m256i*)(src) + 3); +- +- const auto alphaMask = _mm256_set1_epi32(0xFF000000); +- +- auto ORed = _mm256_or_si256(s3, _mm256_or_si256(s2, _mm256_or_si256(s1, s0))); +- if (_mm256_testz_si256(ORed, alphaMask)) { +- // All 32 source pixels are transparent. Nothing to do. +- src += 32; +- dst += 32; +- len -= 32; +- continue; +- } +- +- auto d0 = (__m256i*)(dst) + 0, +- d1 = (__m256i*)(dst) + 1, +- d2 = (__m256i*)(dst) + 2, +- d3 = (__m256i*)(dst) + 3; +- +- auto ANDed = _mm256_and_si256(s3, _mm256_and_si256(s2, _mm256_and_si256(s1, s0))); +- if (_mm256_testc_si256(ANDed, alphaMask)) { +- // All 32 source pixels are opaque. SrcOver becomes Src. +- _mm256_storeu_si256(d0, s0); +- _mm256_storeu_si256(d1, s1); +- _mm256_storeu_si256(d2, s2); +- _mm256_storeu_si256(d3, s3); +- src += 32; +- dst += 32; +- len -= 32; +- continue; +- } +- +- // TODO: This math is wrong. +- // Do SrcOver. +- _mm256_storeu_si256(d0, SkPMSrcOver_AVX2(s0, _mm256_loadu_si256(d0))); +- _mm256_storeu_si256(d1, SkPMSrcOver_AVX2(s1, _mm256_loadu_si256(d1))); +- _mm256_storeu_si256(d2, SkPMSrcOver_AVX2(s2, _mm256_loadu_si256(d2))); +- _mm256_storeu_si256(d3, SkPMSrcOver_AVX2(s3, _mm256_loadu_si256(d3))); +- src += 32; +- dst += 32; +- len -= 32; +- } +- +-#elif SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE41 +- while (len >= 16) { +- // Load 16 source pixels. +- auto s0 = _mm_loadu_si128((const __m128i*)(src) + 0), +- s1 = _mm_loadu_si128((const __m128i*)(src) + 1), +- s2 = _mm_loadu_si128((const __m128i*)(src) + 2), +- s3 = _mm_loadu_si128((const __m128i*)(src) + 3); +- +- const auto alphaMask = _mm_set1_epi32(0xFF000000); +- +- auto ORed = _mm_or_si128(s3, _mm_or_si128(s2, _mm_or_si128(s1, s0))); +- if (_mm_testz_si128(ORed, alphaMask)) { +- // All 16 source pixels are transparent. Nothing to do. +- src += 16; +- dst += 16; +- len -= 16; +- continue; +- } +- +- auto d0 = (__m128i*)(dst) + 0, +- d1 = (__m128i*)(dst) + 1, +- d2 = (__m128i*)(dst) + 2, +- d3 = (__m128i*)(dst) + 3; +- +- auto ANDed = _mm_and_si128(s3, _mm_and_si128(s2, _mm_and_si128(s1, s0))); +- if (_mm_testc_si128(ANDed, alphaMask)) { +- // All 16 source pixels are opaque. SrcOver becomes Src. +- _mm_storeu_si128(d0, s0); +- _mm_storeu_si128(d1, s1); +- _mm_storeu_si128(d2, s2); +- _mm_storeu_si128(d3, s3); +- src += 16; +- dst += 16; +- len -= 16; +- continue; +- } +- +- // TODO: This math is wrong. +- // Do SrcOver. +- _mm_storeu_si128(d0, SkPMSrcOver_SSE2(s0, _mm_loadu_si128(d0))); +- _mm_storeu_si128(d1, SkPMSrcOver_SSE2(s1, _mm_loadu_si128(d1))); +- _mm_storeu_si128(d2, SkPMSrcOver_SSE2(s2, _mm_loadu_si128(d2))); +- _mm_storeu_si128(d3, SkPMSrcOver_SSE2(s3, _mm_loadu_si128(d3))); +- src += 16; +- dst += 16; +- len -= 16; +- } +- +-#elif SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2 +- while (len >= 16) { +- // Load 16 source pixels. +- auto s0 = _mm_loadu_si128((const __m128i*)(src) + 0), +- s1 = _mm_loadu_si128((const __m128i*)(src) + 1), +- s2 = _mm_loadu_si128((const __m128i*)(src) + 2), +- s3 = _mm_loadu_si128((const __m128i*)(src) + 3); +- +- const auto alphaMask = _mm_set1_epi32(0xFF000000); +- +- auto ORed = _mm_or_si128(s3, _mm_or_si128(s2, _mm_or_si128(s1, s0))); +- if (0xffff == _mm_movemask_epi8(_mm_cmpeq_epi8(_mm_and_si128(ORed, alphaMask), +- _mm_setzero_si128()))) { +- // All 16 source pixels are transparent. Nothing to do. +- src += 16; +- dst += 16; +- len -= 16; +- continue; +- } +- +- auto d0 = (__m128i*)(dst) + 0, +- d1 = (__m128i*)(dst) + 1, +- d2 = (__m128i*)(dst) + 2, +- d3 = (__m128i*)(dst) + 3; +- +- auto ANDed = _mm_and_si128(s3, _mm_and_si128(s2, _mm_and_si128(s1, s0))); +- if (0xffff == _mm_movemask_epi8(_mm_cmpeq_epi8(_mm_and_si128(ANDed, alphaMask), +- alphaMask))) { +- // All 16 source pixels are opaque. SrcOver becomes Src. +- _mm_storeu_si128(d0, s0); +- _mm_storeu_si128(d1, s1); +- _mm_storeu_si128(d2, s2); +- _mm_storeu_si128(d3, s3); +- src += 16; +- dst += 16; +- len -= 16; +- continue; +- } +- +- // TODO: This math is wrong. +- // Do SrcOver. +- _mm_storeu_si128(d0, SkPMSrcOver_SSE2(s0, _mm_loadu_si128(d0))); +- _mm_storeu_si128(d1, SkPMSrcOver_SSE2(s1, _mm_loadu_si128(d1))); +- _mm_storeu_si128(d2, SkPMSrcOver_SSE2(s2, _mm_loadu_si128(d2))); +- _mm_storeu_si128(d3, SkPMSrcOver_SSE2(s3, _mm_loadu_si128(d3))); +- +- src += 16; +- dst += 16; +- len -= 16; +- } +- +-#elif defined(SK_ARM_HAS_NEON) +- // Do 8-pixels at a time. A 16-pixels at a time version of this code was also tested, but it +- // underperformed on some of the platforms under test for inputs with frequent transitions of +- // alpha (corresponding to changes of the conditions [~]alpha_u64 == 0 below). It may be worth +- // revisiting the situation in the future. +- while (len >= 8) { +- // Load 8 pixels in 4 NEON registers. src_col.val[i] will contain the same color component +- // for 8 consecutive pixels (e.g. src_col.val[3] will contain all alpha components of 8 +- // pixels). +- uint8x8x4_t src_col = vld4_u8(reinterpret_cast(src)); +- src += 8; +- len -= 8; +- +- // We now detect 2 special cases: the first occurs when all alphas are zero (the 8 pixels +- // are all transparent), the second when all alphas are fully set (they are all opaque). +- uint8x8_t alphas = src_col.val[3]; +- uint64_t alphas_u64 = vget_lane_u64(vreinterpret_u64_u8(alphas), 0); +- if (alphas_u64 == 0) { +- // All pixels transparent. +- dst += 8; +- continue; +- } +- +- if (~alphas_u64 == 0) { +- // All pixels opaque. +- vst4_u8(reinterpret_cast(dst), src_col); +- dst += 8; +- continue; +- } +- +- uint8x8x4_t dst_col = vld4_u8(reinterpret_cast(dst)); +- vst4_u8(reinterpret_cast(dst), SkPMSrcOver_neon8(dst_col, src_col)); +- dst += 8; +- } +- +- // Deal with leftover pixels. +- for (; len >= 2; len -= 2, src += 2, dst += 2) { +- uint8x8_t src2 = vld1_u8(reinterpret_cast(src)); +- uint8x8_t dst2 = vld1_u8(reinterpret_cast(dst)); +- vst1_u8(reinterpret_cast(dst), SkPMSrcOver_neon2(dst2, src2)); +- } +- +- if (len != 0) { +- uint8x8_t result = SkPMSrcOver_neon2(vcreate_u8(*dst), vcreate_u8(*src)); +- vst1_lane_u32(dst, vreinterpret_u32_u8(result), 0); +- } +- return; +-#endif +- +- while (len-- > 0) { +- // This 0xFF000000 is not semantically necessary, but for compatibility +- // with chromium:611002 we need to keep it until we figure out where +- // the non-premultiplied src values (like 0x00FFFFFF) are coming from. +- // TODO(mtklein): sort this out and assert *src is premul here. +- if (*src & 0xFF000000) { +- *dst = (*src >= 0xFF000000) ? *src : SkPMSrcOver(*src, *dst); +- } +- src++; +- dst++; +- } +-} +- + } // SK_OPTS_NS + + #endif//SkBlitRow_opts_DEFINED diff --git a/CVE-2020-26951-1.patch b/CVE-2020-26951-1.patch new file mode 100644 index 0000000000000000000000000000000000000000..ccfbcb5c19aa613f1bbd1559cb9ff55d1a995c21 --- /dev/null +++ b/CVE-2020-26951-1.patch @@ -0,0 +1,102 @@ +# HG changeset patch +# User Henri Sivonen +# Date 1603457336 0 +# Fri Oct 23 12:48:56 2020 +0000 +# Node ID 9143f95d5ab3896f5461fa1666500f6fc1f9e73b +# Parent b067b0d3670b37daad95505b87bddca6bb113d11 +Bug 1667113. r=smaug + +Differential Revision: https://phabricator.services.mozilla.com/D93482 + +diff -r b067b0d3670b -r 9143f95d5ab3 browser/base/content/test/static/browser_parsable_css.js +--- a/browser/base/content/test/static/browser_parsable_css.js Fri Oct 23 12:48:52 2020 +0000 ++++ b/browser/base/content/test/static/browser_parsable_css.js Fri Oct 23 12:48:56 2020 +0000 +@@ -496,9 +496,9 @@ + checkWhitelist(propNameWhitelist); + + // Clean up to avoid leaks: +- iframe.remove(); + doc.head.innerHTML = ""; + doc = null; ++ iframe.remove(); + iframe = null; + win = null; + hiddenFrame.destroy(); +diff -r b067b0d3670b -r 9143f95d5ab3 dom/base/nsContentUtils.cpp +--- a/dom/base/nsContentUtils.cpp Fri Oct 23 12:48:52 2020 +0000 ++++ b/dom/base/nsContentUtils.cpp Fri Oct 23 12:48:56 2020 +0000 +@@ -4817,6 +4817,7 @@ + + nsIContent* target = aTargetNode; + ++ RefPtr inert; + RefPtr fragment; + // We sanitize if the fragment occurs in a system privileged + // context, an about: page, or if there are explicit sanitization flags. +@@ -4828,8 +4828,12 @@ + nodePrincipal->SchemeIs("about") || aFlags >= 0; + if (shouldSanitize) { + if (!AllowsUnsanitizedContentForAboutNewTab(nodePrincipal)) { +- fragment = new (aTargetNode->OwnerDoc()->NodeInfoManager()) +- DocumentFragment(aTargetNode->OwnerDoc()->NodeInfoManager()); ++ inert = nsContentUtils::CreateInertHTMLDocument(aTargetNode->OwnerDoc()); ++ if (!inert) { ++ return NS_ERROR_FAILURE; ++ } ++ fragment = new (inert->NodeInfoManager()) ++ DocumentFragment(inert->NodeInfoManager()); + target = fragment; + } + } +@@ -4908,22 +4908,7 @@ + MOZ_ASSERT(contentsink, "Sink doesn't QI to nsIContentSink!"); + sXMLFragmentParser->SetContentSink(contentsink); + +- sXMLFragmentSink->SetTargetDocument(aDocument); +- sXMLFragmentSink->SetPreventScriptExecution(aPreventScriptExecution); +- +- nsresult rv = sXMLFragmentParser->ParseFragment(aSourceBuffer, aTagStack); +- if (NS_FAILED(rv)) { +- // Drop the fragment parser and sink that might be in an inconsistent state +- NS_IF_RELEASE(sXMLFragmentParser); +- NS_IF_RELEASE(sXMLFragmentSink); +- return rv; +- } +- +- rv = sXMLFragmentSink->FinishFragmentParsing(aReturn); +- +- sXMLFragmentParser->Reset(); +- NS_ENSURE_SUCCESS(rv, rv); +- ++ RefPtr doc; + nsCOMPtr nodePrincipal = aDocument->NodePrincipal(); + + #ifdef DEBUG +@@ -4929,6 +4929,27 @@ + // an about: scheme principal. + bool shouldSanitize = nodePrincipal->IsSystemPrincipal() || + nodePrincipal->SchemeIs("about") || aFlags >= 0; ++ if (shouldSanitize) { ++ doc = nsContentUtils::CreateInertXMLDocument(aDocument); ++ } else { ++ doc = aDocument; ++ } ++ ++ sXMLFragmentSink->SetTargetDocument(doc); ++ sXMLFragmentSink->SetPreventScriptExecution(aPreventScriptExecution); ++ ++ nsresult rv = sXMLFragmentParser->ParseFragment(aSourceBuffer, aTagStack); ++ if (NS_FAILED(rv)) { ++ // Drop the fragment parser and sink that might be in an inconsistent state ++ NS_IF_RELEASE(sXMLFragmentParser); ++ NS_IF_RELEASE(sXMLFragmentSink); ++ return rv; ++ } ++ ++ rv = sXMLFragmentSink->FinishFragmentParsing(aReturn); ++ ++ sXMLFragmentParser->Reset(); ++ NS_ENSURE_SUCCESS(rv, rv); + + if (shouldSanitize) { + uint32_t sanitizationFlags = diff --git a/CVE-2020-26951-2.patch b/CVE-2020-26951-2.patch new file mode 100644 index 0000000000000000000000000000000000000000..89a4c489ec7070743f48094373f1337a7da4f1a7 --- /dev/null +++ b/CVE-2020-26951-2.patch @@ -0,0 +1,177 @@ +# HG changeset patch +# User Henri Sivonen +# Date 1605719930 0 +# Wed Nov 18 17:18:50 2020 +0000 +# Node ID 027514ba89006dfd5c346c307e46ed8f79e358c1 +# Parent 782446e715644da3ca8226d0c3413e3fafb69d6f +Bug 1667113 test - Test innerHTML sanitizer in chrome context. r=smaug + +Differential Revision: https://phabricator.services.mozilla.com/D93928 + +diff -r 782446e71564 -r 027514ba8900 dom/security/test/general/chrome.ini +--- a/dom/security/test/general/chrome.ini Wed Nov 18 17:18:56 2020 +0000 ++++ b/dom/security/test/general/chrome.ini Wed Nov 18 17:18:50 2020 +0000 +@@ -3,6 +3,8 @@ + favicon_bug1277803.ico + bug1277803.html + ++[test_innerhtml_sanitizer.html] ++[test_innerhtml_sanitizer.xhtml] + [test_bug1277803.xhtml] + skip-if = os == 'android' || verify + +diff -r 782446e71564 -r 027514ba8900 dom/security/test/general/test_innerhtml_sanitizer.html +--- /dev/null Thu Jan 01 00:00:00 1970 +0000 ++++ b/dom/security/test/general/test_innerhtml_sanitizer.html Wed Nov 18 17:18:50 2020 +0000 +@@ -0,0 +1,74 @@ ++ ++ ++ ++ ++ Test for Bug 1667113 ++ ++ ++ ++ ++Mozilla Bug 1667113 ++
++ ++ ++ +diff -r 782446e71564 -r 027514ba8900 dom/security/test/general/test_innerhtml_sanitizer.xhtml +--- /dev/null Thu Jan 01 00:00:00 1970 +0000 ++++ b/dom/security/test/general/test_innerhtml_sanitizer.xhtml Wed Nov 18 17:18:50 2020 +0000 +@@ -0,0 +1,73 @@ ++ ++ ++ ++ Test for Bug 1667113 ++ ++ ++ ++ ++Mozilla Bug 1667113 ++
++ ++ ++ diff --git a/CVE-2020-26953-pre.patch b/CVE-2020-26953-pre.patch new file mode 100644 index 0000000000000000000000000000000000000000..f7cd27b2cbc5a2b6c3b9876af46520e719e01692 --- /dev/null +++ b/CVE-2020-26953-pre.patch @@ -0,0 +1,85 @@ +# HG changeset patch +# User Alphan Chen +# Date 1593745253 0 +# Fri Jul 03 03:00:53 2020 +0000 +# Node ID aff172a1f77244bf24cfccc966c917bf801b5cbd +# Parent d69131a21feedc02c202912955ae015c74c4c8ec +Bug 1644484 - Handle the TypeError and InvalidStateError when calling FullScreen.cleanupDomFullscreen() from DOMFullscreenParent.didDestroy() r=Gijs + +Differential Revision: https://phabricator.services.mozilla.com/D81716 + +diff -r d69131a21fee -r aff172a1f772 browser/base/content/browser-fullScreenAndPointerLock.js +--- a/browser/base/content/browser-fullScreenAndPointerLock.js Fri Jul 03 01:30:12 2020 +0000 ++++ b/browser/base/content/browser-fullScreenAndPointerLock.js Fri Jul 03 03:00:53 2020 +0000 +@@ -345,7 +345,9 @@ + }, + + exitDomFullScreen() { +- document.exitFullscreen(); ++ if (document.fullscreen) { ++ document.exitFullscreen(); ++ } + }, + + handleEvent(event) { +@@ -508,8 +510,15 @@ + + /** + * Search for the first ancestor of aActor that lives in a different process. +- * If found, that ancestor is sent the message. Otherwise, the recipient should +- * be the actor of the request origin. ++ * If found, that ancestor is sent the message and return false. ++ * Otherwise, the recipient should be the actor of the request origin and return true ++ * from this function. ++ * ++ * The method will be called again as a result of targeted child process doing ++ * "FullScreen.enterDomFullscreen()" or "FullScreen.cleanupDomFullscreen()". ++ * The return value is used to postpone entering or exiting Full Screen in the parent ++ * until there is no ancestor anymore. ++ * + * + * @param {JSWindowActorParent} aActor + * The actor that called this function. +@@ -517,6 +526,10 @@ + * Message to be sent. + * + * @return {boolean} ++ * The return value is used to postpone entering or exiting Full Screen in the ++ * parent until there is no ancestor anymore. ++ * Return false if the message is send to the first ancestor of aActor that ++ * lives in a different process + * Return true if the message is sent to the request source + * or false otherwise. + */ +@@ -530,6 +543,9 @@ + let parentBC = childBC.parent; + + while (parentBC) { ++ if (!childBC.currentWindowGlobal || !parentBC.currentWindowGlobal) { ++ break; ++ } + let childPid = childBC.currentWindowGlobal.osPid; + let parentPid = parentBC.currentWindowGlobal.osPid; + +@@ -541,7 +557,7 @@ + } + } + +- if (parentBC) { ++ if (parentBC && parentBC.currentWindowGlobal) { + let parentActor = parentBC.currentWindowGlobal.getActor("DOMFullscreen"); + parentActor.sendAsyncMessage(aMessage, { + remoteFrameBC: childBC, +@@ -554,8 +570,10 @@ + // have entered or exited fullscreen at this point. + // So let's notify the process where the original request + // comes from. +- aActor.requestOrigin.sendAsyncMessage(aMessage, {}); +- aActor.requestOrigin = null; ++ if (!aActor.requestOrigin.hasBeenDestroyed()) { ++ aActor.requestOrigin.sendAsyncMessage(aMessage, {}); ++ aActor.requestOrigin = null; ++ } + return true; + }, + diff --git a/CVE-2020-26953.patch b/CVE-2020-26953.patch new file mode 100644 index 0000000000000000000000000000000000000000..4d171ae9c55a81f49f5608667b72de06025003f8 --- /dev/null +++ b/CVE-2020-26953.patch @@ -0,0 +1,231 @@ +# HG changeset patch +# User Steven MacLeod +# Date 1601937483 0 +# Mon Oct 05 22:38:03 2020 +0000 +# Node ID 3e884c48633fb4017402ef2c7053f8d947676dd5 +# Parent b4b7e943b93cdc77a479bd5484f7661985bdb7d4 +Bug 1656741, r=Gijs + +Differential Revision: https://phabricator.services.mozilla.com/D91760 + +diff -r b4b7e943b93c -r 3e884c48633f browser/actors/DOMFullscreenParent.jsm +--- a/browser/actors/DOMFullscreenParent.jsm Mon Oct 05 22:20:41 2020 +0000 ++++ b/browser/actors/DOMFullscreenParent.jsm Mon Oct 05 22:38:03 2020 +0000 +@@ -9,6 +9,8 @@ + const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm"); + + class DOMFullscreenParent extends JSWindowActorParent { ++ waitingForChildFullscreen = false; ++ + updateFullscreenWindowReference(aWindow) { + if (aWindow.document.documentElement.hasAttribute("inDOMFullscreen")) { + this._fullscreenWindow = aWindow; +@@ -23,6 +25,20 @@ + return; + } + ++ if (this.waitingForChildFullscreen) { ++ // We were killed while waiting for our DOMFullscreenChild ++ // to transition to fullscreen so we abort the entire ++ // fullscreen transition to prevent getting stuck in a ++ // partial fullscreen state. We need to go through the ++ // document since window.Fullscreen could be undefined ++ // at this point. ++ // ++ // This could reject if we're not currently in fullscreen ++ // so just ignore rejection. ++ window.document.exitFullscreen().catch(() => {}); ++ return; ++ } ++ + // Need to resume Chrome UI if the window is still in fullscreen UI + // to avoid the window stays in fullscreen problem. (See Bug 1620341) + if (window.document.documentElement.hasAttribute("inDOMFullscreen")) { +@@ -64,6 +80,7 @@ + break; + } + case "DOMFullscreen:Entered": { ++ this.waitingForChildFullscreen = false; + window.FullScreen.enterDomFullscreen(browser, this); + this.updateFullscreenWindowReference(window); + break; +diff -r b4b7e943b93c -r 3e884c48633f browser/base/content/browser-fullScreenAndPointerLock.js +--- a/browser/base/content/browser-fullScreenAndPointerLock.js Mon Oct 05 22:20:41 2020 +0000 ++++ b/browser/base/content/browser-fullScreenAndPointerLock.js Mon Oct 05 22:38:03 2020 +0000 +@@ -420,12 +420,27 @@ + // before the check is fine since we also check the activeness of + // the requesting document in content-side handling code. + if (this._isRemoteBrowser(aBrowser)) { +- if ( +- !this._sendMessageToTheRightContent(aActor, "DOMFullscreen:Entered") +- ) { ++ let [targetActor, inProcessBC] = this._getNextMsgRecipientActor(aActor); ++ if (!targetActor) { ++ // If there is no appropriate actor to send the message we have ++ // no way to complete the transition and should abort by exiting ++ // fullscreen. ++ this._abortEnterFullscreen(); ++ return; ++ } ++ targetActor.sendAsyncMessage("DOMFullscreen:Entered", { ++ remoteFrameBC: inProcessBC, ++ }); ++ ++ // Record that the actor is waiting for its child to enter ++ // fullscreen so that if it dies we can abort. ++ targetActor.waitingForChildFullscreen = true; ++ if (inProcessBC) { ++ // We aren't messaging the request origin yet, skip this time. + return; + } + } ++ + // If we've received a fullscreen notification, we have to ensure that the + // element that's requesting fullscreen belongs to the browser that's currently + // active. If not, we exit fullscreen since the "full-screen document" isn't +@@ -437,9 +452,7 @@ + // full-screen was made. Cancel full-screen. + Services.focus.activeWindow != window + ) { +- // This function is called synchronously in fullscreen change, so +- // we have to avoid calling exitFullscreen synchronously here. +- setTimeout(() => document.exitFullscreen(), 0); ++ this._abortEnterFullscreen(); + return; + } + +@@ -453,7 +466,6 @@ + this._logWarningPermissionPromptFS("promptCanceled"); + } + } +- + document.documentElement.setAttribute("inDOMFullscreen", true); + + if (gFindBarInitialized) { +@@ -488,9 +500,25 @@ + } + }, + ++ /** ++ * Clean up full screen, starting from the request origin's first ancestor ++ * frame that is OOP. ++ * ++ * If there are OOP ancestor frames, we notify the first of those and then bail to ++ * be called again in that process when it has dealt with the change. This is ++ * repeated until all ancestor processes have been updated. Once that has happened ++ * we remove our handlers and attributes and notify the request origin to complete ++ * the cleanup. ++ */ + cleanupDomFullscreen(aActor) { +- if (!this._sendMessageToTheRightContent(aActor, "DOMFullscreen:CleanUp")) { +- return; ++ let [target, inProcessBC] = this._getNextMsgRecipientActor(aActor); ++ if (target) { ++ target.sendAsyncMessage("DOMFullscreen:CleanUp", { ++ remoteFrameBC: inProcessBC, ++ }); ++ if (inProcessBC) { ++ return; ++ } + } + + PopupNotifications.panel.removeEventListener( +@@ -508,40 +536,43 @@ + document.documentElement.removeAttribute("inDOMFullscreen"); + }, + ++ _abortEnterFullscreen() { ++ // This function is called synchronously in fullscreen change, so ++ // we have to avoid calling exitFullscreen synchronously here. ++ setTimeout(() => document.exitFullscreen(), 0); ++ if (TelemetryStopwatch.running("FULLSCREEN_CHANGE_MS")) { ++ // Cancel the stopwatch for any fullscreen change to avoid ++ // errors if it is started again. ++ TelemetryStopwatch.cancel("FULLSCREEN_CHANGE_MS"); ++ } ++ }, ++ + /** + * Search for the first ancestor of aActor that lives in a different process. +- * If found, that ancestor is sent the message and return false. +- * Otherwise, the recipient should be the actor of the request origin and return true +- * from this function. +- * +- * The method will be called again as a result of targeted child process doing +- * "FullScreen.enterDomFullscreen()" or "FullScreen.cleanupDomFullscreen()". +- * The return value is used to postpone entering or exiting Full Screen in the parent +- * until there is no ancestor anymore. ++ * If found, that ancestor actor and the browsing context for its child which ++ * was in process are returned. Otherwise [request origin, null]. + * + * + * @param {JSWindowActorParent} aActor + * The actor that called this function. +- * @param {String} message +- * Message to be sent. + * +- * @return {boolean} +- * The return value is used to postpone entering or exiting Full Screen in the +- * parent until there is no ancestor anymore. +- * Return false if the message is send to the first ancestor of aActor that +- * lives in a different process +- * Return true if the message is sent to the request source +- * or false otherwise. ++ * @return {[JSWindowActorParent, BrowsingContext]} ++ * The parent actor which should be sent the next msg and the ++ * in process browsing context which is its child. Will be ++ * [null, null] if there is no OOP parent actor and request origin ++ * is unset. [null, null] is also returned if the intended actor or ++ * the calling actor has been destroyed. + */ +- _sendMessageToTheRightContent(aActor, aMessage) { ++ _getNextMsgRecipientActor(aActor) { + if (aActor.hasBeenDestroyed()) { +- // Just restore the chrome UI when the actor is dead. +- return true; ++ return [null, null]; + } + + let childBC = aActor.browsingContext; + let parentBC = childBC.parent; + ++ // Walk up the browsing context tree from aActor's browsing context ++ // to find the first ancestor browsing context that's in a different process. + while (parentBC) { + if (!childBC.currentWindowGlobal || !parentBC.currentWindowGlobal) { + break; +@@ -557,24 +588,20 @@ + } + } + ++ let target = null; ++ let inProcessBC = null; ++ + if (parentBC && parentBC.currentWindowGlobal) { +- let parentActor = parentBC.currentWindowGlobal.getActor("DOMFullscreen"); +- parentActor.sendAsyncMessage(aMessage, { +- remoteFrameBC: childBC, +- }); +- return false; ++ target = parentBC.currentWindowGlobal.getActor("DOMFullscreen"); ++ inProcessBC = childBC; ++ } else { ++ target = aActor.requestOrigin; + } + +- // All content frames living outside the process where +- // the element requesting fullscreen lives should +- // have entered or exited fullscreen at this point. +- // So let's notify the process where the original request +- // comes from. +- if (!aActor.requestOrigin.hasBeenDestroyed()) { +- aActor.requestOrigin.sendAsyncMessage(aMessage, {}); +- aActor.requestOrigin = null; ++ if (!target || target.hasBeenDestroyed()) { ++ return [null, null]; + } +- return true; ++ return [target, inProcessBC]; + }, + + _isRemoteBrowser(aBrowser) { diff --git a/CVE-2020-26956-1.patch b/CVE-2020-26956-1.patch new file mode 100644 index 0000000000000000000000000000000000000000..e88427e8aadfb773c0beea6c3d4ea41ac9d5abe5 --- /dev/null +++ b/CVE-2020-26956-1.patch @@ -0,0 +1,56 @@ +# HG changeset patch +# User Henri Sivonen +# Date 1603457329 0 +# Fri Oct 23 12:48:49 2020 +0000 +# Node ID 3476387362fb15c82f133f390afef719ad36de0a +# Parent fd45fcfd6261e9ed6cf83e54ad8286717f1b4762 +Bug 1666300 part 1 - Remove attributes from descendants when setting sanitized style. r=smaug + +Differential Revision: https://phabricator.services.mozilla.com/D93215 + +diff -r fd45fcfd6261 -r 3476387362fb dom/base/nsTreeSanitizer.cpp +--- a/dom/base/nsTreeSanitizer.cpp Fri Oct 23 13:04:19 2020 +0000 ++++ b/dom/base/nsTreeSanitizer.cpp Fri Oct 23 12:48:49 2020 +0000 +@@ -1341,6 +1341,7 @@ + nsAutoString sanitizedStyle; + SanitizeStyleSheet(styleText, sanitizedStyle, aRoot->OwnerDoc(), + node->GetBaseURI()); ++ RemoveAllAttributesFromDescendants(elt); + nsContentUtils::SetNodeTextContent(node, sanitizedStyle, true); + + if (!mOnlyConditionalCSS) { +@@ -1427,6 +1428,18 @@ + } + } + ++void nsTreeSanitizer::RemoveAllAttributesFromDescendants( ++ mozilla::dom::Element* aElement) { ++ nsIContent* node = aElement->GetFirstChild(); ++ while (node) { ++ if (node->IsElement()) { ++ mozilla::dom::Element* elt = node->AsElement(); ++ RemoveAllAttributes(elt); ++ } ++ node = node->GetNextNode(aElement); ++ } ++} ++ + void nsTreeSanitizer::LogMessage(const char* aMessage, Document* aDoc, + Element* aElement, nsAtom* aAttr) { + if (mLogRemovals) { +diff -r fd45fcfd6261 -r 3476387362fb dom/base/nsTreeSanitizer.h +--- a/dom/base/nsTreeSanitizer.h Fri Oct 23 13:04:19 2020 +0000 ++++ b/dom/base/nsTreeSanitizer.h Fri Oct 23 12:48:49 2020 +0000 +@@ -200,6 +200,12 @@ + void RemoveAllAttributes(mozilla::dom::Element* aElement); + + /** ++ * Removes all attributes from the descendants of an element but not from ++ * the element itself. ++ */ ++ void RemoveAllAttributesFromDescendants(mozilla::dom::Element* aElement); ++ ++ /** + * Log a Console Service message to indicate we removed something. + * If you pass an element and/or attribute, their information will + * be appended to the message. diff --git a/CVE-2020-26956-2.patch b/CVE-2020-26956-2.patch new file mode 100644 index 0000000000000000000000000000000000000000..639e796dc0c74b75e8b4aa37b3b3162a405d4e40 --- /dev/null +++ b/CVE-2020-26956-2.patch @@ -0,0 +1,171 @@ +# HG changeset patch +# User Henri Sivonen +# Date 1603457332 0 +# Fri Oct 23 12:48:52 2020 +0000 +# Node ID b067b0d3670b37daad95505b87bddca6bb113d11 +# Parent 3476387362fb15c82f133f390afef719ad36de0a +Bug 1666300 part 2 - Parse into an inert document. r=smaug + +Differential Revision: https://phabricator.services.mozilla.com/D93478 + +diff -r 3476387362fb -r b067b0d3670b dom/base/nsContentUtils.cpp +--- a/dom/base/nsContentUtils.cpp Fri Oct 23 12:48:49 2020 +0000 ++++ b/dom/base/nsContentUtils.cpp Fri Oct 23 12:48:52 2020 +0000 +@@ -4968,17 +4968,12 @@ + nsAString& aResultBuffer, + uint32_t aFlags, + uint32_t aWrapCol) { +- nsCOMPtr uri; +- NS_NewURI(getter_AddRefs(uri), "about:blank"); +- nsCOMPtr principal = +- NullPrincipal::CreateWithoutOriginAttributes(); +- RefPtr document; +- nsresult rv = NS_NewDOMDocument(getter_AddRefs(document), EmptyString(), +- EmptyString(), nullptr, uri, uri, principal, +- true, nullptr, DocumentFlavorHTML); +- NS_ENSURE_SUCCESS(rv, rv); +- +- rv = nsContentUtils::ParseDocumentHTML( ++ RefPtr document = nsContentUtils::CreateInertHTMLDocument(nullptr); ++ if (!document) { ++ return NS_ERROR_FAILURE; ++ } ++ ++ nsresult rv = nsContentUtils::ParseDocumentHTML( + aSourceBuffer, document, + !(aFlags & nsIDocumentEncoder::OutputNoScriptContent)); + NS_ENSURE_SUCCESS(rv, rv); +@@ -4994,6 +4989,58 @@ + } + + /* static */ ++already_AddRefed nsContentUtils::CreateInertXMLDocument( ++ const Document* aTemplate) { ++ return nsContentUtils::CreateInertDocument(aTemplate, DocumentFlavorXML); ++} ++ ++/* static */ ++already_AddRefed nsContentUtils::CreateInertHTMLDocument( ++ const Document* aTemplate) { ++ return nsContentUtils::CreateInertDocument(aTemplate, DocumentFlavorHTML); ++} ++ ++/* static */ ++already_AddRefed nsContentUtils::CreateInertDocument( ++ const Document* aTemplate, DocumentFlavor aFlavor) { ++ if (aTemplate) { ++ bool hasHad = true; ++ nsIScriptGlobalObject* sgo = aTemplate->GetScriptHandlingObject(hasHad); ++ NS_ENSURE_TRUE(sgo || !hasHad, nullptr); ++ ++ nsCOMPtr doc; ++ nsresult rv = NS_NewDOMDocument( ++ getter_AddRefs(doc), NS_LITERAL_STRING(""), NS_LITERAL_STRING(""), nullptr, ++ aTemplate->GetDocumentURI(), aTemplate->GetDocBaseURI(), ++ aTemplate->NodePrincipal(), true, sgo, aFlavor); ++ if (NS_FAILED(rv)) { ++ return nullptr; ++ } ++ return doc.forget(); ++ } ++ nsCOMPtr uri; ++ NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("about:blank")); ++ if (!uri) { ++ return nullptr; ++ } ++ ++ RefPtr nullPrincipal = ++ NullPrincipal::CreateWithoutOriginAttributes(); ++ if (!nullPrincipal) { ++ return nullptr; ++ } ++ ++ nsCOMPtr doc; ++ nsresult rv = ++ NS_NewDOMDocument(getter_AddRefs(doc), NS_LITERAL_STRING(""), NS_LITERAL_STRING(""), nullptr, uri, uri, ++ nullPrincipal, true, nullptr, aFlavor); ++ if (NS_FAILED(rv)) { ++ return nullptr; ++ } ++ return doc.forget(); ++} ++ ++/* static */ + nsresult nsContentUtils::SetNodeTextContent(nsIContent* aContent, + const nsAString& aValue, + bool aTryReuse) { +diff -r 3476387362fb -r b067b0d3670b dom/base/nsContentUtils.h +--- a/dom/base/nsContentUtils.h Fri Oct 23 12:48:49 2020 +0000 ++++ b/dom/base/nsContentUtils.h Fri Oct 23 12:48:52 2020 +0000 +@@ -1831,6 +1831,25 @@ + uint32_t aWrapCol); + + /** ++ * Creates a 'loaded-as-data' HTML document that takes that principal, ++ * script global, and URL from the argument, which may be null. ++ */ ++ static already_AddRefed CreateInertHTMLDocument( ++ const Document* aTemplate); ++ ++ /** ++ * Creates a 'loaded-as-data' XML document that takes that principal, ++ * script global, and URL from the argument, which may be null. ++ */ ++ static already_AddRefed CreateInertXMLDocument( ++ const Document* aTemplate); ++ ++ private: ++ static already_AddRefed CreateInertDocument( ++ const Document* aTemplate, DocumentFlavor aFlavor); ++ ++ public: ++ /** + * Sets the text contents of a node by replacing all existing children + * with a single text child. + * +diff -r 3476387362fb -r b067b0d3670b editor/libeditor/HTMLEditorDataTransfer.cpp +--- a/editor/libeditor/HTMLEditorDataTransfer.cpp Fri Oct 23 12:48:49 2020 +0000 ++++ b/editor/libeditor/HTMLEditorDataTransfer.cpp Fri Oct 23 12:48:52 2020 +0000 +@@ -3039,8 +3039,13 @@ + bool aTrustedInput) { + nsAutoScriptBlockerSuppressNodeRemoved autoBlocker; + +- RefPtr fragment = new (aTargetDocument->NodeInfoManager()) +- DocumentFragment(aTargetDocument->NodeInfoManager()); ++ nsCOMPtr doc = ++ nsContentUtils::CreateInertHTMLDocument(aTargetDocument); ++ if (!doc) { ++ return NS_ERROR_FAILURE; ++ } ++ RefPtr fragment = ++ new (doc->NodeInfoManager()) DocumentFragment(doc->NodeInfoManager()); + nsresult rv = nsContentUtils::ParseFragmentHTML( + aFragStr, fragment, + aContextLocalName ? aContextLocalName : nsGkAtoms::body, +diff -r 3476387362fb -r b067b0d3670b parser/html/nsParserUtils.cpp +--- a/parser/html/nsParserUtils.cpp Fri Oct 23 12:48:49 2020 +0000 ++++ b/parser/html/nsParserUtils.cpp Fri Oct 23 12:48:52 2020 +0000 +@@ -45,17 +45,13 @@ + NS_IMETHODIMP + nsParserUtils::Sanitize(const nsAString& aFromStr, uint32_t aFlags, + nsAString& aToStr) { +- nsCOMPtr uri; +- NS_NewURI(getter_AddRefs(uri), "about:blank"); +- nsCOMPtr principal = +- mozilla::NullPrincipal::CreateWithoutOriginAttributes(); +- RefPtr document; +- nsresult rv = NS_NewDOMDocument(getter_AddRefs(document), EmptyString(), +- EmptyString(), nullptr, uri, uri, principal, +- true, nullptr, DocumentFlavorHTML); +- NS_ENSURE_SUCCESS(rv, rv); ++ RefPtr document = nsContentUtils::CreateInertHTMLDocument(nullptr); + +- rv = nsContentUtils::ParseDocumentHTML(aFromStr, document, false); ++ if (!document) { ++ return NS_ERROR_FAILURE; ++ } ++ ++ nsresult rv = nsContentUtils::ParseDocumentHTML(aFromStr, document, false); + NS_ENSURE_SUCCESS(rv, rv); + + nsTreeSanitizer sanitizer(aFlags); diff --git a/CVE-2020-26956-3.patch b/CVE-2020-26956-3.patch new file mode 100644 index 0000000000000000000000000000000000000000..82c44124e4566841301b7c863fab9003d8b55c99 --- /dev/null +++ b/CVE-2020-26956-3.patch @@ -0,0 +1,99 @@ +# HG changeset patch +# User Henri Sivonen +# Date 1605719936 0 +# Wed Nov 18 17:18:56 2020 +0000 +# Node ID 782446e715644da3ca8226d0c3413e3fafb69d6f +# Parent 42be1816b3857a3962cd0ec4be551830b6639aee +Bug 1666300 test - Test SVG style sanitization on paste. r=smaug + +Differential Revision: https://phabricator.services.mozilla.com/D93634 + +diff -r 42be1816b385 -r 782446e71564 editor/libeditor/tests/file_sanitizer_on_paste.sjs +--- /dev/null Thu Jan 01 00:00:00 1970 +0000 ++++ b/editor/libeditor/tests/file_sanitizer_on_paste.sjs Wed Nov 18 17:18:56 2020 +0000 +@@ -0,0 +1,16 @@ ++function handleRequest(request, response) ++{ ++ if (request.queryString.indexOf("report") != -1) { ++ response.setHeader("Content-Type", "text/javascript", false); ++ if (getState("loaded") == "loaded") { ++ response.write("ok(false, 'There was an attempt to preload the image.');"); ++ } else { ++ response.write("ok(true, 'There was no attempt to preload the image.');"); ++ } ++ response.write("SimpleTest.finish();"); ++ } else { ++ setState("loaded", "loaded"); ++ response.setHeader("Content-Type", "image/svg", false); ++ response.write("Not supposed to load this"); ++ } ++} +diff -r 42be1816b385 -r 782446e71564 editor/libeditor/tests/mochitest.ini +--- a/editor/libeditor/tests/mochitest.ini Wed Dec 16 10:40:06 2020 +0200 ++++ b/editor/libeditor/tests/mochitest.ini Wed Nov 18 17:18:56 2020 +0000 +@@ -21,6 +21,7 @@ + file_bug966155.html + file_bug966552.html + file_select_all_without_body.html ++ file_sanitizer_on_paste.sjs + green.png + spellcheck.js + +@@ -305,3 +306,4 @@ + [test_selection_move_commands.html] + [test_pasteImgTextarea.html] + [test_execCommandPaste_noTarget.html] ++[test_sanitizer_on_paste.html] +diff -r 42be1816b385 -r 782446e71564 editor/libeditor/tests/test_sanitizer_on_paste.html +--- /dev/null Thu Jan 01 00:00:00 1970 +0000 ++++ b/editor/libeditor/tests/test_sanitizer_on_paste.html Wed Nov 18 17:18:56 2020 +0000 +@@ -0,0 +1,48 @@ ++ ++ ++ ++ ++ Test pasting table rows ++ ++ ++ ++ ++ ++ ++
Paste target
++ ++ +\ No newline at end of file diff --git a/CVE-2020-26957.patch b/CVE-2020-26957.patch new file mode 100644 index 0000000000000000000000000000000000000000..59a2fb1c406c58b1942780f3aaf896e1bf64ca02 --- /dev/null +++ b/CVE-2020-26957.patch @@ -0,0 +1,33 @@ +# HG changeset patch +# User Agi Sferro +# Date 1602608252 0 +# Tue Oct 13 16:57:32 2020 +0000 +# Node ID 1aa2dc4b280e4ac1d5d5742e1923d5d39c04c102 +# Parent 943130e5f28ed6ee3e6b8bbf0f9c9f60fb5a7053 +Bug 1667179 - Initialize OneCRL when GeckoView starts. r=snorp,jcj + +Differential Revision: https://phabricator.services.mozilla.com/D93250 + +diff -r 943130e5f28e -r 1aa2dc4b280e mobile/android/chrome/geckoview/geckoview.js +--- a/mobile/android/chrome/geckoview/geckoview.js Tue Oct 13 16:59:30 2020 +0000 ++++ b/mobile/android/chrome/geckoview/geckoview.js Tue Oct 13 16:57:32 2020 +0000 +@@ -18,6 +18,8 @@ + GeckoViewSettings: "resource://gre/modules/GeckoViewSettings.jsm", + GeckoViewUtils: "resource://gre/modules/GeckoViewUtils.jsm", + HistogramStopwatch: "resource://gre/modules/GeckoViewTelemetry.jsm", ++ RemoteSecuritySettings: ++ "resource://gre/modules/psm/RemoteSecuritySettings.jsm", + }); + + XPCOMUtils.defineLazyGetter(this, "WindowEventDispatcher", () => +@@ -610,6 +612,10 @@ + Services.obs.notifyObservers(window, "extensions-late-startup"); + }); + ++ InitLater(() => { ++ RemoteSecuritySettings.init(); ++ }); ++ + // This should always go last, since the idle tasks (except for the ones with + // timeouts) should execute in order. Note that this observer notification is + // not guaranteed to fire, since the window could close before we get here. diff --git a/CVE-2020-26958.patch b/CVE-2020-26958.patch new file mode 100644 index 0000000000000000000000000000000000000000..c99ce0474573b78b9f9adf5036d600d0f8782dc6 --- /dev/null +++ b/CVE-2020-26958.patch @@ -0,0 +1,768 @@ +# HG changeset patch +# User Andrew Sutherland +# Date 1603887323 0 +# Wed Oct 28 12:15:23 2020 +0000 +# Node ID 6873589e0ede3c11bc48243be67c3d51e214873f +# Parent e6a1286e25b70d36a1e251fb056596181565d839 +Bug 1669355 - Refactor MIME type warnings into base class. r=necko-reviewers,valentin + +Differential Revision: https://phabricator.services.mozilla.com/D93906 + +diff -r e6a1286e25b7 -r 6873589e0ede netwerk/protocol/http/HttpBaseChannel.cpp +--- a/netwerk/protocol/http/HttpBaseChannel.cpp 2020-07-21 06:49:41.000000000 +0800 ++++ b/netwerk/protocol/http/HttpBaseChannel.cpp 2021-01-06 11:26:44.608483314 +0800 +@@ -24,10 +24,12 @@ + #include "mozilla/NullPrincipal.h" + #include "mozilla/Services.h" + #include "mozilla/StaticPrefs_browser.h" ++#include "mozilla/StaticPrefs_security.h" + #include "mozilla/Telemetry.h" + #include "mozilla/Tokenizer.h" + #include "mozilla/dom/BrowsingContext.h" + #include "mozilla/dom/CanonicalBrowsingContext.h" ++#include "mozilla/dom/Document.h" + #include "mozilla/dom/Performance.h" + #include "mozilla/dom/PerformanceStorage.h" + #include "mozilla/dom/WindowGlobalParent.h" +@@ -2385,6 +2387,354 @@ nsresult HttpBaseChannel::ComputeCrossOr + return NS_OK; + } + ++enum class Report { Error, Warning }; ++ ++// Helper Function to report messages to the console when the loaded ++// script had a wrong MIME type. ++void ReportMimeTypeMismatch(HttpBaseChannel* aChannel, const char* aMessageName, ++ nsIURI* aURI, const nsACString& aContentType, ++ Report report) { ++ NS_ConvertUTF8toUTF16 spec(aURI->GetSpecOrDefault()); ++ NS_ConvertUTF8toUTF16 contentType(aContentType); ++ ++ aChannel->LogMimeTypeMismatch(nsCString(aMessageName), ++ report == Report::Warning, spec, contentType); ++} ++ ++// Check and potentially enforce X-Content-Type-Options: nosniff ++nsresult ProcessXCTO(HttpBaseChannel* aChannel, nsIURI* aURI, ++ nsHttpResponseHead* aResponseHead, ++ nsILoadInfo* aLoadInfo) { ++ if (!aURI || !aResponseHead || !aLoadInfo) { ++ // if there is no uri, no response head or no loadInfo, then there is ++ // nothing to do ++ return NS_OK; ++ } ++ ++ // 1) Query the XCTO header and check if 'nosniff' is the first value. ++ nsAutoCString contentTypeOptionsHeader; ++ if (!aResponseHead->GetContentTypeOptionsHeader(contentTypeOptionsHeader)) { ++ // if failed to get XCTO header, then there is nothing to do. ++ return NS_OK; ++ } ++ ++ // let's compare the header (ignoring case) ++ // e.g. "NoSniFF" -> "nosniff" ++ // if it's not 'nosniff' then there is nothing to do here ++ if (!contentTypeOptionsHeader.EqualsIgnoreCase("nosniff")) { ++ // since we are getting here, the XCTO header was sent; ++ // a non matching value most likely means a mistake happenend; ++ // e.g. sending 'nosnif' instead of 'nosniff', let's log a warning. ++ AutoTArray params; ++ CopyUTF8toUTF16(contentTypeOptionsHeader, *params.AppendElement()); ++ RefPtr doc; ++ aLoadInfo->GetLoadingDocument(getter_AddRefs(doc)); ++ nsContentUtils::ReportToConsole( ++ nsIScriptError::warningFlag, NS_LITERAL_CSTRING("XCTO"), doc, ++ nsContentUtils::eSECURITY_PROPERTIES, "XCTOHeaderValueMissing", params); ++ return NS_OK; ++ } ++ ++ // 2) Query the content type from the channel ++ nsAutoCString contentType; ++ aResponseHead->ContentType(contentType); ++ ++ // 3) Compare the expected MIME type with the actual type ++ if (aLoadInfo->GetExternalContentPolicyType() == ++ nsIContentPolicy::TYPE_STYLESHEET) { ++ if (contentType.EqualsLiteral(TEXT_CSS)) { ++ return NS_OK; ++ } ++ ReportMimeTypeMismatch(aChannel, "MimeTypeMismatch2", aURI, contentType, ++ Report::Error); ++ return NS_ERROR_CORRUPTED_CONTENT; ++ } ++ ++ if (aLoadInfo->GetExternalContentPolicyType() == ++ nsIContentPolicy::TYPE_SCRIPT) { ++ if (nsContentUtils::IsJavascriptMIMEType( ++ NS_ConvertUTF8toUTF16(contentType))) { ++ return NS_OK; ++ } ++ ReportMimeTypeMismatch(aChannel, "MimeTypeMismatch2", aURI, contentType, ++ Report::Error); ++ return NS_ERROR_CORRUPTED_CONTENT; ++ } ++ ++ auto policyType = aLoadInfo->GetExternalContentPolicyType(); ++ if ((policyType == nsIContentPolicy::TYPE_DOCUMENT || ++ policyType == nsIContentPolicy::TYPE_SUBDOCUMENT) && ++ gHttpHandler->IsDocumentNosniffEnabled()) { ++ // If the header XCTO nosniff is set for any browsing context, then ++ // we set the skipContentSniffing flag on the Loadinfo. Within ++ // GetMIMETypeFromContent we then bail early and do not do any sniffing. ++ aLoadInfo->SetSkipContentSniffing(true); ++ return NS_OK; ++ } ++ ++ return NS_OK; ++} ++ ++// Ensure that a load of type script has correct MIME type ++nsresult EnsureMIMEOfScript(HttpBaseChannel* aChannel, nsIURI* aURI, ++ nsHttpResponseHead* aResponseHead, ++ nsILoadInfo* aLoadInfo) { ++ if (!aURI || !aResponseHead || !aLoadInfo) { ++ // if there is no uri, no response head or no loadInfo, then there is ++ // nothing to do ++ return NS_OK; ++ } ++ ++ if (aLoadInfo->GetExternalContentPolicyType() != ++ nsIContentPolicy::TYPE_SCRIPT) { ++ // if this is not a script load, then there is nothing to do ++ return NS_OK; ++ } ++ ++ nsAutoCString contentType; ++ aResponseHead->ContentType(contentType); ++ NS_ConvertUTF8toUTF16 typeString(contentType); ++ ++ if (nsContentUtils::IsJavascriptMIMEType(typeString)) { ++ // script load has type script ++ AccumulateCategorical( ++ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::javaScript); ++ return NS_OK; ++ } ++ ++ switch (aLoadInfo->InternalContentPolicyType()) { ++ case nsIContentPolicy::TYPE_SCRIPT: ++ case nsIContentPolicy::TYPE_INTERNAL_SCRIPT: ++ case nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD: ++ case nsIContentPolicy::TYPE_INTERNAL_MODULE: ++ case nsIContentPolicy::TYPE_INTERNAL_MODULE_PRELOAD: ++ AccumulateCategorical( ++ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::script_load); ++ break; ++ case nsIContentPolicy::TYPE_INTERNAL_WORKER: ++ case nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER: ++ AccumulateCategorical( ++ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::worker_load); ++ break; ++ case nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER: ++ AccumulateCategorical( ++ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::serviceworker_load); ++ break; ++ case nsIContentPolicy::TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS: ++ AccumulateCategorical( ++ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::importScript_load); ++ break; ++ case nsIContentPolicy::TYPE_INTERNAL_AUDIOWORKLET: ++ case nsIContentPolicy::TYPE_INTERNAL_PAINTWORKLET: ++ AccumulateCategorical( ++ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::worklet_load); ++ break; ++ default: ++ MOZ_ASSERT_UNREACHABLE("unexpected script type"); ++ break; ++ } ++ ++ bool isPrivateWin = aLoadInfo->GetOriginAttributes().mPrivateBrowsingId > 0; ++ bool isSameOrigin = false; ++ aLoadInfo->GetLoadingPrincipal()->IsSameOrigin(aURI, isPrivateWin, ++ &isSameOrigin); ++ if (isSameOrigin) { ++ // same origin ++ AccumulateCategorical( ++ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::same_origin); ++ } else { ++ bool cors = false; ++ nsAutoCString corsOrigin; ++ nsresult rv = aResponseHead->GetHeader( ++ nsHttp::ResolveAtom("Access-Control-Allow-Origin"), corsOrigin); ++ if (NS_SUCCEEDED(rv)) { ++ if (corsOrigin.Equals("*")) { ++ cors = true; ++ } else { ++ nsCOMPtr corsOriginURI; ++ rv = NS_NewURI(getter_AddRefs(corsOriginURI), corsOrigin); ++ if (NS_SUCCEEDED(rv)) { ++ bool isPrivateWin = ++ aLoadInfo->GetOriginAttributes().mPrivateBrowsingId > 0; ++ bool isSameOrigin = false; ++ aLoadInfo->GetLoadingPrincipal()->IsSameOrigin( ++ corsOriginURI, isPrivateWin, &isSameOrigin); ++ if (isSameOrigin) { ++ cors = true; ++ } ++ } ++ } ++ } ++ if (cors) { ++ // cors origin ++ AccumulateCategorical( ++ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::CORS_origin); ++ } else { ++ // cross origin ++ AccumulateCategorical( ++ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::cross_origin); ++ } ++ } ++ ++ bool block = false; ++ if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("image/"))) { ++ // script load has type image ++ AccumulateCategorical( ++ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::image); ++ block = true; ++ } else if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("audio/"))) { ++ // script load has type audio ++ AccumulateCategorical( ++ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::audio); ++ block = true; ++ } else if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("video/"))) { ++ // script load has type video ++ AccumulateCategorical( ++ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::video); ++ block = true; ++ } else if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("text/csv"))) { ++ // script load has type text/csv ++ AccumulateCategorical( ++ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::text_csv); ++ block = true; ++ } ++ ++ if (block) { ++ // Do not block the load if the feature is not enabled. ++ if (!StaticPrefs::security_block_script_with_wrong_mime()) { ++ return NS_OK; ++ } ++ ++ ReportMimeTypeMismatch(aChannel, "BlockScriptWithWrongMimeType2", aURI, ++ contentType, Report::Error); ++ return NS_ERROR_CORRUPTED_CONTENT; ++ } ++ ++ if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("text/plain"))) { ++ // script load has type text/plain ++ AccumulateCategorical( ++ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::text_plain); ++ } else if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("text/xml"))) { ++ // script load has type text/xml ++ AccumulateCategorical( ++ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::text_xml); ++ } else if (StringBeginsWith(contentType, ++ NS_LITERAL_CSTRING("application/octet-stream"))) { ++ // script load has type application/octet-stream ++ AccumulateCategorical( ++ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::app_octet_stream); ++ } else if (StringBeginsWith(contentType, ++ NS_LITERAL_CSTRING("application/xml"))) { ++ // script load has type application/xml ++ AccumulateCategorical( ++ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::app_xml); ++ } else if (StringBeginsWith(contentType, ++ NS_LITERAL_CSTRING("application/json"))) { ++ // script load has type application/json ++ AccumulateCategorical( ++ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::app_json); ++ } else if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("text/json"))) { ++ // script load has type text/json ++ AccumulateCategorical( ++ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::text_json); ++ } else if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("text/html"))) { ++ // script load has type text/html ++ AccumulateCategorical( ++ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::text_html); ++ } else if (contentType.IsEmpty()) { ++ // script load has no type ++ AccumulateCategorical( ++ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::empty); ++ } else { ++ // script load has unknown type ++ AccumulateCategorical( ++ Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::unknown); ++ } ++ ++ // We restrict importScripts() in worker code to JavaScript MIME types. ++ nsContentPolicyType internalType = aLoadInfo->InternalContentPolicyType(); ++ if (internalType == nsIContentPolicy::TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS) { ++ // Do not block the load if the feature is not enabled. ++ if (!StaticPrefs::security_block_importScripts_with_wrong_mime()) { ++ return NS_OK; ++ } ++ ++ ReportMimeTypeMismatch(aChannel, "BlockImportScriptsWithWrongMimeType", ++ aURI, contentType, Report::Error); ++ return NS_ERROR_CORRUPTED_CONTENT; ++ } ++ ++ if (internalType == nsIContentPolicy::TYPE_INTERNAL_WORKER || ++ internalType == nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER) { ++ // Do not block the load if the feature is not enabled. ++ if (!StaticPrefs::security_block_Worker_with_wrong_mime()) { ++ return NS_OK; ++ } ++ ++ ReportMimeTypeMismatch(aChannel, "BlockWorkerWithWrongMimeType", aURI, ++ contentType, Report::Error); ++ return NS_ERROR_CORRUPTED_CONTENT; ++ } ++ ++ // ES6 modules require a strict MIME type check. ++ if (internalType == nsIContentPolicy::TYPE_INTERNAL_MODULE || ++ internalType == nsIContentPolicy::TYPE_INTERNAL_MODULE_PRELOAD) { ++ ReportMimeTypeMismatch(aChannel, "BlockModuleWithWrongMimeType", aURI, ++ contentType, Report::Error); ++ return NS_ERROR_CORRUPTED_CONTENT; ++ } ++ ++ return NS_OK; ++} ++ ++// Warn when a load of type script uses a wrong MIME type and ++// wasn't blocked by EnsureMIMEOfScript or ProcessXCTO. ++void WarnWrongMIMEOfScript(HttpBaseChannel* aChannel, nsIURI* aURI, ++ nsHttpResponseHead* aResponseHead, ++ nsILoadInfo* aLoadInfo) { ++ if (!aURI || !aResponseHead || !aLoadInfo) { ++ // If there is no uri, no response head or no loadInfo, then there is ++ // nothing to do. ++ return; ++ } ++ ++ if (aLoadInfo->GetExternalContentPolicyType() != ++ nsIContentPolicy::TYPE_SCRIPT) { ++ // If this is not a script load, then there is nothing to do. ++ return; ++ } ++ ++ bool succeeded; ++ MOZ_ALWAYS_SUCCEEDS(aChannel->GetRequestSucceeded(&succeeded)); ++ if (!succeeded) { ++ // Do not warn for failed loads: HTTP error pages are usually in HTML. ++ return; ++ } ++ ++ nsAutoCString contentType; ++ aResponseHead->ContentType(contentType); ++ NS_ConvertUTF8toUTF16 typeString(contentType); ++ if (!nsContentUtils::IsJavascriptMIMEType(typeString)) { ++ ReportMimeTypeMismatch(aChannel, "WarnScriptWithWrongMimeType", aURI, ++ contentType, Report::Warning); ++ } ++} ++ ++nsresult HttpBaseChannel::ValidateMIMEType() { ++ nsresult rv = EnsureMIMEOfScript(this, mURI, mResponseHead.get(), mLoadInfo); ++ if (NS_FAILED(rv)) { ++ return rv; ++ } ++ ++ rv = ProcessXCTO(this, mURI, mResponseHead.get(), mLoadInfo); ++ if (NS_FAILED(rv)) { ++ return rv; ++ } ++ ++ WarnWrongMIMEOfScript(this, mURI, mResponseHead.get(), mLoadInfo); ++ return NS_OK; ++} ++ + NS_IMETHODIMP + HttpBaseChannel::SetCookie(const nsACString& aCookieHeader) { + if (mLoadFlags & LOAD_ANONYMOUS) return NS_OK; +diff -r e6a1286e25b7 -r 6873589e0ede netwerk/protocol/http/HttpBaseChannel.h +--- a/netwerk/protocol/http/HttpBaseChannel.h 2020-07-21 04:53:32.000000000 +0800 ++++ b/netwerk/protocol/http/HttpBaseChannel.h 2021-01-06 10:53:17.326264473 +0800 +@@ -610,6 +610,8 @@ class HttpBaseChannel : public nsHashPro + + nsresult ComputeCrossOriginOpenerPolicyMismatch(); + ++ nsresult ValidateMIMEType(); ++ + friend class PrivateBrowsingChannel; + friend class InterceptFailedOnStop; + +diff -r e6a1286e25b7 -r 6873589e0ede netwerk/protocol/http/InterceptedHttpChannel.cpp +--- a/netwerk/protocol/http/InterceptedHttpChannel.cpp 2020-07-21 06:49:41.000000000 +0800 ++++ b/netwerk/protocol/http/InterceptedHttpChannel.cpp 2021-01-06 10:53:17.326264473 +0800 +@@ -1046,6 +1046,12 @@ InterceptedHttpChannel::OnStartRequest(n + Cancel(mStatus); + } + ++ rv = ValidateMIMEType(); ++ if (NS_FAILED(rv)) { ++ mStatus = rv; ++ Cancel(mStatus); ++ } ++ + mOnStartRequestCalled = true; + if (mListener) { + return mListener->OnStartRequest(this); +diff -r e6a1286e25b7 -r 6873589e0ede netwerk/protocol/http/nsHttpChannel.cpp +--- a/netwerk/protocol/http/nsHttpChannel.cpp 2021-01-06 10:53:17.330264533 +0800 ++++ b/netwerk/protocol/http/nsHttpChannel.cpp 2021-01-06 11:10:19.257650688 +0800 +@@ -1485,339 +1485,6 @@ HttpTrafficCategory nsHttpChannel::Creat + NS_UsePrivateBrowsing(this), isSystemPrincipal, isThirdParty, cos, tc); + } + +-enum class Report { Error, Warning }; +- +-// Helper Function to report messages to the console when the loaded +-// script had a wrong MIME type. +-void ReportMimeTypeMismatch(nsHttpChannel* aChannel, const char* aMessageName, +- nsIURI* aURI, const nsACString& aContentType, +- Report report) { +- NS_ConvertUTF8toUTF16 spec(aURI->GetSpecOrDefault()); +- NS_ConvertUTF8toUTF16 contentType(aContentType); +- +- aChannel->LogMimeTypeMismatch(nsCString(aMessageName), +- report == Report::Warning, spec, contentType); +-} +- +-// Check and potentially enforce X-Content-Type-Options: nosniff +-nsresult ProcessXCTO(nsHttpChannel* aChannel, nsIURI* aURI, +- nsHttpResponseHead* aResponseHead, +- nsILoadInfo* aLoadInfo) { +- if (!aURI || !aResponseHead || !aLoadInfo) { +- // if there is no uri, no response head or no loadInfo, then there is +- // nothing to do +- return NS_OK; +- } +- +- // 1) Query the XCTO header and check if 'nosniff' is the first value. +- nsAutoCString contentTypeOptionsHeader; +- if (!aResponseHead->GetContentTypeOptionsHeader(contentTypeOptionsHeader)) { +- // if failed to get XCTO header, then there is nothing to do. +- return NS_OK; +- } +- +- // let's compare the header (ignoring case) +- // e.g. "NoSniFF" -> "nosniff" +- // if it's not 'nosniff' then there is nothing to do here +- if (!contentTypeOptionsHeader.EqualsIgnoreCase("nosniff")) { +- // since we are getting here, the XCTO header was sent; +- // a non matching value most likely means a mistake happenend; +- // e.g. sending 'nosnif' instead of 'nosniff', let's log a warning. +- AutoTArray params; +- CopyUTF8toUTF16(contentTypeOptionsHeader, *params.AppendElement()); +- RefPtr doc; +- aLoadInfo->GetLoadingDocument(getter_AddRefs(doc)); +- nsContentUtils::ReportToConsole( +- nsIScriptError::warningFlag, NS_LITERAL_CSTRING("XCTO"), doc, +- nsContentUtils::eSECURITY_PROPERTIES, "XCTOHeaderValueMissing", params); +- return NS_OK; +- } +- +- // 2) Query the content type from the channel +- nsAutoCString contentType; +- aResponseHead->ContentType(contentType); +- +- // 3) Compare the expected MIME type with the actual type +- if (aLoadInfo->GetExternalContentPolicyType() == +- nsIContentPolicy::TYPE_STYLESHEET) { +- if (contentType.EqualsLiteral(TEXT_CSS)) { +- return NS_OK; +- } +- ReportMimeTypeMismatch(aChannel, "MimeTypeMismatch2", aURI, contentType, +- Report::Error); +- return NS_ERROR_CORRUPTED_CONTENT; +- } +- +- if (aLoadInfo->GetExternalContentPolicyType() == +- nsIContentPolicy::TYPE_SCRIPT) { +- if (nsContentUtils::IsJavascriptMIMEType( +- NS_ConvertUTF8toUTF16(contentType))) { +- return NS_OK; +- } +- ReportMimeTypeMismatch(aChannel, "MimeTypeMismatch2", aURI, contentType, +- Report::Error); +- return NS_ERROR_CORRUPTED_CONTENT; +- } +- +- auto policyType = aLoadInfo->GetExternalContentPolicyType(); +- if ((policyType == nsIContentPolicy::TYPE_DOCUMENT || +- policyType == nsIContentPolicy::TYPE_SUBDOCUMENT) && +- gHttpHandler->IsDocumentNosniffEnabled()) { +- // If the header XCTO nosniff is set for any browsing context, then +- // we set the skipContentSniffing flag on the Loadinfo. Within +- // GetMIMETypeFromContent we then bail early and do not do any sniffing. +- aLoadInfo->SetSkipContentSniffing(true); +- return NS_OK; +- } +- +- return NS_OK; +-} +- +-// Ensure that a load of type script has correct MIME type +-nsresult EnsureMIMEOfScript(nsHttpChannel* aChannel, nsIURI* aURI, +- nsHttpResponseHead* aResponseHead, +- nsILoadInfo* aLoadInfo) { +- if (!aURI || !aResponseHead || !aLoadInfo) { +- // if there is no uri, no response head or no loadInfo, then there is +- // nothing to do +- return NS_OK; +- } +- +- if (aLoadInfo->GetExternalContentPolicyType() != +- nsIContentPolicy::TYPE_SCRIPT) { +- // if this is not a script load, then there is nothing to do +- return NS_OK; +- } +- +- nsAutoCString contentType; +- aResponseHead->ContentType(contentType); +- NS_ConvertUTF8toUTF16 typeString(contentType); +- +- if (nsContentUtils::IsJavascriptMIMEType(typeString)) { +- // script load has type script +- AccumulateCategorical( +- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::javaScript); +- return NS_OK; +- } +- +- switch (aLoadInfo->InternalContentPolicyType()) { +- case nsIContentPolicy::TYPE_SCRIPT: +- case nsIContentPolicy::TYPE_INTERNAL_SCRIPT: +- case nsIContentPolicy::TYPE_INTERNAL_SCRIPT_PRELOAD: +- case nsIContentPolicy::TYPE_INTERNAL_MODULE: +- case nsIContentPolicy::TYPE_INTERNAL_MODULE_PRELOAD: +- AccumulateCategorical( +- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::script_load); +- break; +- case nsIContentPolicy::TYPE_INTERNAL_WORKER: +- case nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER: +- AccumulateCategorical( +- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::worker_load); +- break; +- case nsIContentPolicy::TYPE_INTERNAL_SERVICE_WORKER: +- AccumulateCategorical( +- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::serviceworker_load); +- break; +- case nsIContentPolicy::TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS: +- AccumulateCategorical( +- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::importScript_load); +- break; +- case nsIContentPolicy::TYPE_INTERNAL_AUDIOWORKLET: +- case nsIContentPolicy::TYPE_INTERNAL_PAINTWORKLET: +- AccumulateCategorical( +- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::worklet_load); +- break; +- default: +- MOZ_ASSERT_UNREACHABLE("unexpected script type"); +- break; +- } +- +- bool isPrivateWin = aLoadInfo->GetOriginAttributes().mPrivateBrowsingId > 0; +- bool isSameOrigin = false; +- aLoadInfo->GetLoadingPrincipal()->IsSameOrigin(aURI, isPrivateWin, +- &isSameOrigin); +- if (isSameOrigin) { +- // same origin +- AccumulateCategorical( +- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::same_origin); +- } else { +- bool cors = false; +- nsAutoCString corsOrigin; +- nsresult rv = aResponseHead->GetHeader( +- nsHttp::ResolveAtom("Access-Control-Allow-Origin"), corsOrigin); +- if (NS_SUCCEEDED(rv)) { +- if (corsOrigin.Equals("*")) { +- cors = true; +- } else { +- nsCOMPtr corsOriginURI; +- rv = NS_NewURI(getter_AddRefs(corsOriginURI), corsOrigin); +- if (NS_SUCCEEDED(rv)) { +- bool isPrivateWin = +- aLoadInfo->GetOriginAttributes().mPrivateBrowsingId > 0; +- bool isSameOrigin = false; +- aLoadInfo->GetLoadingPrincipal()->IsSameOrigin( +- corsOriginURI, isPrivateWin, &isSameOrigin); +- if (isSameOrigin) { +- cors = true; +- } +- } +- } +- } +- if (cors) { +- // cors origin +- AccumulateCategorical( +- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::CORS_origin); +- } else { +- // cross origin +- AccumulateCategorical( +- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::cross_origin); +- } +- } +- +- bool block = false; +- if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("image/"))) { +- // script load has type image +- AccumulateCategorical( +- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::image); +- block = true; +- } else if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("audio/"))) { +- // script load has type audio +- AccumulateCategorical( +- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::audio); +- block = true; +- } else if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("video/"))) { +- // script load has type video +- AccumulateCategorical( +- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::video); +- block = true; +- } else if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("text/csv"))) { +- // script load has type text/csv +- AccumulateCategorical( +- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::text_csv); +- block = true; +- } +- +- if (block) { +- // Do not block the load if the feature is not enabled. +- if (!StaticPrefs::security_block_script_with_wrong_mime()) { +- return NS_OK; +- } +- +- ReportMimeTypeMismatch(aChannel, "BlockScriptWithWrongMimeType2", aURI, +- contentType, Report::Error); +- return NS_ERROR_CORRUPTED_CONTENT; +- } +- +- if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("text/plain"))) { +- // script load has type text/plain +- AccumulateCategorical( +- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::text_plain); +- } else if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("text/xml"))) { +- // script load has type text/xml +- AccumulateCategorical( +- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::text_xml); +- } else if (StringBeginsWith(contentType, +- NS_LITERAL_CSTRING("application/octet-stream"))) { +- // script load has type application/octet-stream +- AccumulateCategorical( +- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::app_octet_stream); +- } else if (StringBeginsWith(contentType, +- NS_LITERAL_CSTRING("application/xml"))) { +- // script load has type application/xml +- AccumulateCategorical( +- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::app_xml); +- } else if (StringBeginsWith(contentType, +- NS_LITERAL_CSTRING("application/json"))) { +- // script load has type application/json +- AccumulateCategorical( +- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::app_json); +- } else if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("text/json"))) { +- // script load has type text/json +- AccumulateCategorical( +- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::text_json); +- } else if (StringBeginsWith(contentType, NS_LITERAL_CSTRING("text/html"))) { +- // script load has type text/html +- AccumulateCategorical( +- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::text_html); +- } else if (contentType.IsEmpty()) { +- // script load has no type +- AccumulateCategorical( +- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::empty); +- } else { +- // script load has unknown type +- AccumulateCategorical( +- Telemetry::LABELS_SCRIPT_BLOCK_INCORRECT_MIME_3::unknown); +- } +- +- // We restrict importScripts() in worker code to JavaScript MIME types. +- nsContentPolicyType internalType = aLoadInfo->InternalContentPolicyType(); +- if (internalType == nsIContentPolicy::TYPE_INTERNAL_WORKER_IMPORT_SCRIPTS) { +- // Do not block the load if the feature is not enabled. +- if (!StaticPrefs::security_block_importScripts_with_wrong_mime()) { +- return NS_OK; +- } +- +- ReportMimeTypeMismatch(aChannel, "BlockImportScriptsWithWrongMimeType", +- aURI, contentType, Report::Error); +- return NS_ERROR_CORRUPTED_CONTENT; +- } +- +- if (internalType == nsIContentPolicy::TYPE_INTERNAL_WORKER || +- internalType == nsIContentPolicy::TYPE_INTERNAL_SHARED_WORKER) { +- // Do not block the load if the feature is not enabled. +- if (!StaticPrefs::security_block_Worker_with_wrong_mime()) { +- return NS_OK; +- } +- +- ReportMimeTypeMismatch(aChannel, "BlockWorkerWithWrongMimeType", aURI, +- contentType, Report::Error); +- return NS_ERROR_CORRUPTED_CONTENT; +- } +- +- // ES6 modules require a strict MIME type check. +- if (internalType == nsIContentPolicy::TYPE_INTERNAL_MODULE || +- internalType == nsIContentPolicy::TYPE_INTERNAL_MODULE_PRELOAD) { +- ReportMimeTypeMismatch(aChannel, "BlockModuleWithWrongMimeType", aURI, +- contentType, Report::Error); +- return NS_ERROR_CORRUPTED_CONTENT; +- } +- +- return NS_OK; +-} +- +-// Warn when a load of type script uses a wrong MIME type and +-// wasn't blocked by EnsureMIMEOfScript or ProcessXCTO. +-void WarnWrongMIMEOfScript(nsHttpChannel* aChannel, nsIURI* aURI, +- nsHttpResponseHead* aResponseHead, +- nsILoadInfo* aLoadInfo) { +- if (!aURI || !aResponseHead || !aLoadInfo) { +- // If there is no uri, no response head or no loadInfo, then there is +- // nothing to do. +- return; +- } +- +- if (aLoadInfo->GetExternalContentPolicyType() != +- nsIContentPolicy::TYPE_SCRIPT) { +- // If this is not a script load, then there is nothing to do. +- return; +- } +- +- bool succeeded; +- MOZ_ALWAYS_SUCCEEDS(aChannel->GetRequestSucceeded(&succeeded)); +- if (!succeeded) { +- // Do not warn for failed loads: HTTP error pages are usually in HTML. +- return; +- } +- +- nsAutoCString contentType; +- aResponseHead->ContentType(contentType); +- NS_ConvertUTF8toUTF16 typeString(contentType); +- if (!nsContentUtils::IsJavascriptMIMEType(typeString)) { +- ReportMimeTypeMismatch(aChannel, "WarnScriptWithWrongMimeType", aURI, +- contentType, Report::Warning); +- } +-} +- + void nsHttpChannel::SetCachedContentType() { + if (!mResponseHead) { + return; +@@ -1913,14 +1580,9 @@ nsresult nsHttpChannel::CallOnStartReque + mOnStartRequestCalled = true; + }); + +- nsresult rv = EnsureMIMEOfScript(this, mURI, mResponseHead.get(), mLoadInfo); +- NS_ENSURE_SUCCESS(rv, rv); +- +- rv = ProcessXCTO(this, mURI, mResponseHead.get(), mLoadInfo); ++ nsresult rv = ValidateMIMEType(); + NS_ENSURE_SUCCESS(rv, rv); + +- WarnWrongMIMEOfScript(this, mURI, mResponseHead.get(), mLoadInfo); +- + // Allow consumers to override our content type + if (mLoadFlags & LOAD_CALL_CONTENT_SNIFFERS) { + // NOTE: We can have both a txn pump and a cache pump when the cache diff --git a/CVE-2020-26959.patch b/CVE-2020-26959.patch new file mode 100644 index 0000000000000000000000000000000000000000..a1d612f0135863d5ae6deb82b29e0ef09250486b --- /dev/null +++ b/CVE-2020-26959.patch @@ -0,0 +1,63 @@ +# HG changeset patch +# User Luca Greco +# Date 1603810809 0 +# Tue Oct 27 15:00:09 2020 +0000 +# Node ID 8de8cd3371e801d408650f102df04252c846f33d +# Parent 5058a78c1008f0917866aa09abff7430bcefa085 +Bug 1669466 - Change WebRequestService singleton to a StaticRefPtr. r=glandium,mixedpuppy + +Differential Revision: https://phabricator.services.mozilla.com/D94692 + +diff -r 5058a78c1008 -r 8de8cd3371e8 toolkit/components/extensions/webrequest/WebRequestService.cpp +--- a/toolkit/components/extensions/webrequest/WebRequestService.cpp Tue Oct 27 15:07:07 2020 +0000 ++++ b/toolkit/components/extensions/webrequest/WebRequestService.cpp Tue Oct 27 15:00:09 2020 +0000 +@@ -13,22 +13,14 @@ + using namespace mozilla::dom; + using namespace mozilla::extensions; + +-static WebRequestService* sWeakWebRequestService; +- +-WebRequestService::~WebRequestService() { sWeakWebRequestService = nullptr; } ++static StaticRefPtr sWebRequestService; + + /* static */ WebRequestService& WebRequestService::GetSingleton() { +- static RefPtr instance; +- if (!sWeakWebRequestService) { +- instance = new WebRequestService(); +- ClearOnShutdown(&instance); +- +- // A separate weak instance that we keep a reference to as long as the +- // original service is alive, even after our strong reference is cleared to +- // allow the service to be destroyed. +- sWeakWebRequestService = instance; ++ if (!sWebRequestService) { ++ sWebRequestService = new WebRequestService(); ++ ClearOnShutdown(&sWebRequestService); + } +- return *sWeakWebRequestService; ++ return *sWebRequestService; + } + + UniquePtr WebRequestService::RegisterChannel( +@@ -56,7 +48,7 @@ + : mChannelId(aChannel->Id()), mChannel(aChannel) {} + + WebRequestChannelEntry::~WebRequestChannelEntry() { +- if (sWeakWebRequestService) { +- sWeakWebRequestService->mChannelEntries.Remove(mChannelId); ++ if (sWebRequestService) { ++ sWebRequestService->mChannelEntries.Remove(mChannelId); + } + } +diff -r 5058a78c1008 -r 8de8cd3371e8 toolkit/components/extensions/webrequest/WebRequestService.h +--- a/toolkit/components/extensions/webrequest/WebRequestService.h Tue Oct 27 15:07:07 2020 +0000 ++++ b/toolkit/components/extensions/webrequest/WebRequestService.h Tue Oct 27 15:00:09 2020 +0000 +@@ -64,7 +64,7 @@ + dom::ContentParent* aContentParent); + + private: +- ~WebRequestService(); ++ ~WebRequestService() = default; + + friend ChannelEntry; + diff --git a/CVE-2020-26960-1.patch b/CVE-2020-26960-1.patch new file mode 100644 index 0000000000000000000000000000000000000000..3e45bf07699b42f8e0dc90d9d396c1a5e52945a6 --- /dev/null +++ b/CVE-2020-26960-1.patch @@ -0,0 +1,49 @@ +# HG changeset patch +# User Jon Coppeard +# Date 1603288236 0 +# Wed Oct 21 13:50:36 2020 +0000 +# Node ID 7e223284a9225c66b590aaad671c7448d1ff0b57 +# Parent dfcb025567da9e33bf724520e0146fef3d776d5f +Bug 1670358 - Don't use realloc for shrinking nsTArrays and similar when RelocationStrategy::allowRealloc is false r=sg + +My original patch handled the grow case but not the shrink case. When the +current and new allocation sizes are in different size classes jemalloc's +realloc will move the allocation when shrinking, not just truncate the existing +one. + +Differential Revision: https://phabricator.services.mozilla.com/D93654 + +diff -r dfcb025567da -r 7e223284a922 xpcom/ds/nsTArray-inl.h +--- a/xpcom/ds/nsTArray-inl.h Thu Oct 22 07:36:15 2020 +0000 ++++ b/xpcom/ds/nsTArray-inl.h Wed Oct 21 13:50:36 2020 +0000 +@@ -259,10 +259,27 @@ + } + + size_type size = sizeof(Header) + length * aElemSize; +- void* ptr = nsTArrayFallibleAllocator::Realloc(mHdr, size); +- if (!ptr) { +- return; ++ void* ptr; ++ ++ if (!RelocationStrategy::allowRealloc) { ++ // Malloc() and copy. ++ ptr = static_cast(nsTArrayFallibleAllocator::Malloc(size)); ++ if (!ptr) { ++ return; ++ } ++ ++ RelocationStrategy::RelocateNonOverlappingRegionWithHeader( ++ ptr, mHdr, Length(), aElemSize); ++ ++ nsTArrayFallibleAllocator::Free(mHdr); ++ } else { ++ // Realloc() existing data. ++ ptr = nsTArrayFallibleAllocator::Realloc(mHdr, size); ++ if (!ptr) { ++ return; ++ } + } ++ + mHdr = static_cast(ptr); + mHdr->mCapacity = length; + } diff --git a/CVE-2020-26960-2.patch b/CVE-2020-26960-2.patch new file mode 100644 index 0000000000000000000000000000000000000000..7158a75695f314175a69b7d6e761ef4cda61d6c6 --- /dev/null +++ b/CVE-2020-26960-2.patch @@ -0,0 +1,136 @@ +# HG changeset patch +# User Jon Coppeard +# Date 1603288237 0 +# Wed Oct 21 13:50:37 2020 +0000 +# Node ID 8a8d7fdc7038fb360d7c50f5943ccafd7f0bb829 +# Parent 7e223284a9225c66b590aaad671c7448d1ff0b57 +Bug 1670358 - Add test for shrinking nsTArrays of JS::Heap r=sg + +Depends on D93654 + +Differential Revision: https://phabricator.services.mozilla.com/D94270 + +diff -r 7e223284a922 -r 8a8d7fdc7038 xpcom/tests/gtest/TestGCPostBarriers.cpp +--- a/xpcom/tests/gtest/TestGCPostBarriers.cpp Wed Oct 21 13:50:36 2020 +0000 ++++ b/xpcom/tests/gtest/TestGCPostBarriers.cpp Wed Oct 21 13:50:37 2020 +0000 +@@ -9,6 +9,8 @@ + * implemented for nsTArrays that contain JavaScript Values. + */ + ++#include "mozilla/UniquePtr.h" ++ + #include "jsapi.h" + #include "nsTArray.h" + +@@ -37,11 +39,13 @@ + const size_t InitialElements = ElementCount / 10; + + template +-static void RunTest(JSContext* cx, ArrayT* array) { ++static void TestGrow(JSContext* cx) { + JS_GC(cx); + ++ auto array = MakeUnique(); + ASSERT_TRUE(array != nullptr); +- JS_AddExtraGCRootsTracer(cx, TraceArray, array); ++ ++ JS_AddExtraGCRootsTracer(cx, TraceArray, array.get()); + + /* + * Create the array and fill it with new JS objects. With GGC these will be +@@ -66,7 +70,8 @@ + /* + * Sanity check that our array contains what we expect. + */ +- for (size_t i = 0; i < ElementCount; ++i) { ++ ASSERT_EQ(array->Length(), ElementCount); ++ for (size_t i = 0; i < array->Length(); i++) { + RootedObject obj(cx, array->ElementAt(i)); + ASSERT_TRUE(JS::ObjectIsTenured(obj)); + ASSERT_TRUE(JS_GetProperty(cx, obj, property, &value)); +@@ -74,7 +79,54 @@ + ASSERT_EQ(static_cast(i), value.toInt32()); + } + +- JS_RemoveExtraGCRootsTracer(cx, TraceArray, array); ++ JS_RemoveExtraGCRootsTracer(cx, TraceArray, array.get()); ++} ++ ++template ++static void TestShrink(JSContext* cx) { ++ JS_GC(cx); ++ ++ auto array = MakeUnique(); ++ ASSERT_TRUE(array != nullptr); ++ ++ JS_AddExtraGCRootsTracer(cx, TraceArray, array.get()); ++ ++ /* ++ * Create the array and fill it with new JS objects. With GGC these will be ++ * allocated in the nursery. ++ */ ++ RootedValue value(cx); ++ const char* property = "foo"; ++ for (size_t i = 0; i < ElementCount; ++i) { ++ RootedObject obj(cx, JS_NewPlainObject(cx)); ++ ASSERT_FALSE(JS::ObjectIsTenured(obj)); ++ value = Int32Value(i); ++ ASSERT_TRUE(JS_SetProperty(cx, obj, property, value)); ++ ASSERT_TRUE(array->AppendElement(obj, fallible)); ++ } ++ ++ /* Shrink and compact the array */ ++ array->RemoveElementsAt(InitialElements, ElementCount - InitialElements); ++ array->Compact(); ++ ++ JS_GC(cx); ++ ++ ASSERT_EQ(array->Length(), InitialElements); ++ for (size_t i = 0; i < array->Length(); i++) { ++ RootedObject obj(cx, array->ElementAt(i)); ++ ASSERT_TRUE(JS::ObjectIsTenured(obj)); ++ ASSERT_TRUE(JS_GetProperty(cx, obj, property, &value)); ++ ASSERT_TRUE(value.isInt32()); ++ ASSERT_EQ(static_cast(i), value.toInt32()); ++ } ++ ++ JS_RemoveExtraGCRootsTracer(cx, TraceArray, array.get()); ++} ++ ++template ++static void TestArrayType(JSContext* cx) { ++ TestGrow(cx); ++ TestShrink(cx); + } + + static void CreateGlobalAndRunTest(JSContext* cx) { +@@ -89,25 +141,11 @@ + + JS::Realm* oldRealm = JS::EnterRealm(cx, global); + +- typedef Heap ElementT; +- +- { +- nsTArray* array = new nsTArray(InitialElements); +- RunTest(cx, array); +- delete array; +- } ++ using ElementT = Heap; + +- { +- FallibleTArray* array = +- new FallibleTArray(InitialElements); +- RunTest(cx, array); +- delete array; +- } +- +- { +- AutoTArray array; +- RunTest(cx, &array); +- } ++ TestArrayType>(cx); ++ TestArrayType>(cx); ++ TestArrayType>(cx); + + JS::LeaveRealm(cx, oldRealm); + } diff --git a/CVE-2020-26961-1.patch b/CVE-2020-26961-1.patch new file mode 100644 index 0000000000000000000000000000000000000000..638b5a355d677c5cb13fa5fa59d73d4156ac7d82 --- /dev/null +++ b/CVE-2020-26961-1.patch @@ -0,0 +1,58 @@ +# HG changeset patch +# User Valentin Gosu +# Date 1604497734 0 +# Wed Nov 04 13:48:54 2020 +0000 +# Node ID 179e399ac08119ef3da61766c73f265679a6cf51 +# Parent 6810172b5a5861dbf847848d0a34f13787c1a6ba +Bug 1672528 - Check IPv4-mapped IPv6 addresses for being local r=dragana,necko-reviewers + +Differential Revision: https://phabricator.services.mozilla.com/D95414 + +diff -r 6810172b5a58 -r 179e399ac081 netwerk/dns/DNS.cpp +--- a/netwerk/dns/DNS.cpp Wed Nov 04 17:16:26 2020 +0000 ++++ b/netwerk/dns/DNS.cpp Wed Nov 04 13:48:54 2020 +0000 +@@ -183,27 +183,37 @@ bool IsIPAddrV4Mapped(const NetAddr* add + return false; + } + ++static bool isLocalIPv4(uint32_t networkEndianIP) { ++ uint32_t addr32 = ntohl(networkEndianIP); ++ if (addr32 >> 24 == 0x0A || // 10/8 prefix (RFC 1918). ++ addr32 >> 20 == 0xAC1 || // 172.16/12 prefix (RFC 1918). ++ addr32 >> 16 == 0xC0A8 || // 192.168/16 prefix (RFC 1918). ++ addr32 >> 16 == 0xA9FE) { // 169.254/16 prefix (Link Local). ++ return true; ++ } ++ return false; ++} ++ + bool IsIPAddrLocal(const NetAddr* addr) { + MOZ_ASSERT(addr); + + // IPv4 RFC1918 and Link Local Addresses. + if (addr->raw.family == AF_INET) { +- uint32_t addr32 = ntohl(addr->inet.ip); +- if (addr32 >> 24 == 0x0A || // 10/8 prefix (RFC 1918). +- addr32 >> 20 == 0xAC1 || // 172.16/12 prefix (RFC 1918). +- addr32 >> 16 == 0xC0A8 || // 192.168/16 prefix (RFC 1918). +- addr32 >> 16 == 0xA9FE) { // 169.254/16 prefix (Link Local). +- return true; +- } ++ return isLocalIPv4(addr->inet.ip); + } + // IPv6 Unique and Link Local Addresses. ++ // or mapped IPv4 address + if (addr->raw.family == AF_INET6) { + uint16_t addr16 = ntohs(addr->inet6.ip.u16[0]); + if (addr16 >> 9 == 0xfc >> 1 || // fc00::/7 Unique Local Address. + addr16 >> 6 == 0xfe80 >> 6) { // fe80::/10 Link Local Address. + return true; + } ++ if (IPv6ADDR_IS_V4MAPPED(&addr->inet6.ip)) { ++ return isLocalIPv4(IPv6ADDR_V4MAPPED_TO_IPADDR(&addr->inet6.ip)); ++ } + } ++ + // Not an IPv4/6 local address. + return false; + } diff --git a/CVE-2020-26961-2.patch b/CVE-2020-26961-2.patch new file mode 100644 index 0000000000000000000000000000000000000000..6844985fd32f35bbf1990fb8062bda54b868a25f --- /dev/null +++ b/CVE-2020-26961-2.patch @@ -0,0 +1,47 @@ +# HG changeset patch +# User Valentin Gosu +# Date 1604497736 0 +# Wed Nov 04 13:48:56 2020 +0000 +# Node ID b18b9e52050cb671b57c011daa4a173fe46aec5a +# Parent 179e399ac08119ef3da61766c73f265679a6cf51 +Bug 1672528 - Test r=necko-reviewers,dragana + +Depends on D95414 + +Differential Revision: https://phabricator.services.mozilla.com/D95415 + +diff -r 179e399ac081 -r b18b9e52050c netwerk/test/unit/test_trr.js +--- a/netwerk/test/unit/test_trr.js Wed Nov 04 13:48:54 2020 +0000 ++++ b/netwerk/test/unit/test_trr.js Wed Nov 04 13:48:56 2020 +0000 +@@ -556,6 +556,19 @@ + !Components.isSuccessCode(inStatus), + `${inStatus} should be an error code` + ); ++ Services.prefs.setCharPref( ++ "network.trr.uri", ++ `https://foo.example.com:${h2Port}/doh?responseIP=::ffff:192.168.0.1` ++ ); ++ [, , inStatus] = await new DNSListener( ++ "rfc1918-ipv6.example.com", ++ undefined, ++ false ++ ); ++ Assert.ok( ++ !Components.isSuccessCode(inStatus), ++ `${inStatus} should be an error code` ++ ); + }); + + // verify RFC1918 address from the server is fine when told so +@@ -568,6 +581,11 @@ + ); + Services.prefs.setBoolPref("network.trr.allow-rfc1918", true); + await new DNSListener("rfc1918.example.com", "192.168.0.1"); ++ Services.prefs.setCharPref( ++ "network.trr.uri", ++ `https://foo.example.com:${h2Port}/doh?responseIP=::ffff:192.168.0.1` ++ ); ++ await new DNSListener("rfc1918-ipv6.example.com", "::ffff:192.168.0.1"); + }); + + // use GET and disable ECS (makes a larger request) diff --git a/CVE-2020-26963-1.patch b/CVE-2020-26963-1.patch new file mode 100644 index 0000000000000000000000000000000000000000..cb55845514b17ea5467e7a149cefb34912120691 --- /dev/null +++ b/CVE-2020-26963-1.patch @@ -0,0 +1,371 @@ +# HG changeset patch +# User pbz +# Date 1600689290 0 +# Mon Sep 21 11:54:50 2020 +0000 +# Node ID efcefed227f304781326e7c8a52633559a79b6adlist oniguruma.spec +# Parent 32d03662a363850006f648c22e825b3e886b29bc +Bug 1314912 - Rate limit calls to History and Location interfaces. r=smaug9.0-3 + +This adds a rate limit to methods and setters of the History and Location +for non-system callers. +The rate limit is counted per BrowsingContext and can be controlled by prefs. + +This patch is based on the original rate limit patch by :freesamael. + +Differential Revision: https://phabricator.services.mozilla.com/D90136 + +diff -r 32d03662a363 -r efcefed227f3 docshell/base/BrowsingContext.cpp +--- a/docshell/base/BrowsingContext.cpp 2020-07-21 06:49:37.000000000 +0800 ++++ b/docshell/base/BrowsingContext.cpp 2021-01-06 10:22:57.966851379 +0800 +@@ -2459,6 +2459,56 @@ bool BrowsingContext::CanSet(FieldIndex< + return GetBrowserId() == 0 && IsTop() && Children().IsEmpty(); + } + ++nsresult BrowsingContext::CheckLocationChangeRateLimit(CallerType aCallerType) { ++ // We only rate limit non system callers ++ if (aCallerType == CallerType::System) { ++ return NS_OK; ++ } ++ ++ // Fetch rate limiting preferences ++ uint32_t limitCount = ++ StaticPrefs::dom_navigation_locationChangeRateLimit_count(); ++ uint32_t timeSpanSeconds = ++ StaticPrefs::dom_navigation_locationChangeRateLimit_timespan(); ++ ++ // Disable throttling if either of the preferences is set to 0. ++ if (limitCount == 0 || timeSpanSeconds == 0) { ++ return NS_OK; ++ } ++ ++ TimeDuration throttleSpan = TimeDuration::FromSeconds(timeSpanSeconds); ++ ++ if (mLocationChangeRateLimitSpanStart.IsNull() || ++ ((TimeStamp::Now() - mLocationChangeRateLimitSpanStart) > throttleSpan)) { ++ // Initial call or timespan exceeded, reset counter and timespan. ++ mLocationChangeRateLimitSpanStart = TimeStamp::Now(); ++ mLocationChangeRateLimitCount = 1; ++ return NS_OK; ++ } ++ ++ if (mLocationChangeRateLimitCount >= limitCount) { ++ // Rate limit reached ++ ++ Document* doc = GetDocument(); ++ if (doc) { ++ nsContentUtils::ReportToConsole(nsIScriptError::errorFlag,NS_LITERAL_CSTRING("DOM"), doc, ++ nsContentUtils::eDOM_PROPERTIES, ++ "LocChangeFloodingPrevented"); ++ } ++ ++ return NS_ERROR_DOM_SECURITY_ERR; ++ } ++ ++ mLocationChangeRateLimitCount++; ++ return NS_OK; ++} ++ ++void BrowsingContext::ResetLocationChangeRateLimit() { ++ // Resetting the timestamp object will cause the check function to ++ // init again and reset the rate limit. ++ mLocationChangeRateLimitSpanStart = TimeStamp(); ++} ++ + } // namespace dom + + namespace ipc { +diff -r 32d03662a363 -r efcefed227f3 docshell/base/BrowsingContext.h +--- a/docshell/base/BrowsingContext.h 2020-07-21 06:49:37.000000000 +0800 ++++ b/docshell/base/BrowsingContext.h 2021-01-06 10:22:57.954851198 +0800 +@@ -652,6 +652,16 @@ class BrowsingContext : public nsILoadCo + + bool CrossOriginIsolated(); + ++ // Checks if we reached the rate limit for calls to Location and History API. ++ // The rate limit is controlled by the ++ // "dom.navigation.locationChangeRateLimit" prefs. ++ // Rate limit applies per BrowsingContext. ++ // Returns NS_OK if we are below the rate limit and increments the counter. ++ // Returns NS_ERROR_DOM_SECURITY_ERR if limit is reached. ++ nsresult CheckLocationChangeRateLimit(CallerType aCallerType); ++ ++ void ResetLocationChangeRateLimit(); ++ + protected: + virtual ~BrowsingContext(); + BrowsingContext(WindowContext* aParentWindow, BrowsingContextGroup* aGroup, +@@ -932,6 +942,11 @@ class BrowsingContext : public nsILoadCo + + RefPtr mSessionStorageManager; + RefPtr mChildSessionHistory; ++ ++ // Counter and time span for rate limiting Location and History API calls. ++ // Used by CheckLocationChangeRateLimit. Do not apply cross-process. ++ uint32_t mLocationChangeRateLimitCount; ++ mozilla::TimeStamp mLocationChangeRateLimitSpanStart; + }; + + /** +diff -r 32d03662a363 -r efcefed227f3 docshell/shistory/ChildSHistory.cpp +--- a/docshell/shistory/ChildSHistory.cpp 2020-07-21 06:49:37.000000000 +0800 ++++ b/docshell/shistory/ChildSHistory.cpp 2021-01-06 10:22:58.058852764 +0800 +@@ -105,7 +105,14 @@ void ChildSHistory::Go(int32_t aOffset, + } + } + +-void ChildSHistory::AsyncGo(int32_t aOffset, bool aRequireUserInteraction) { ++void ChildSHistory::AsyncGo(int32_t aOffset, bool aRequireUserInteraction, ++ CallerType aCallerType, ErrorResult& aRv) { ++ nsresult rv = mBrowsingContext->CheckLocationChangeRateLimit(aCallerType); ++ if (NS_FAILED(rv)) { ++ aRv.Throw(rv); ++ return; ++ } ++ + if (!CanGo(aOffset)) { + return; + } +diff -r 32d03662a363 -r efcefed227f3 docshell/shistory/ChildSHistory.h +--- a/docshell/shistory/ChildSHistory.h 2020-07-21 06:49:37.000000000 +0800 ++++ b/docshell/shistory/ChildSHistory.h 2021-01-06 10:22:58.058852764 +0800 +@@ -64,8 +64,8 @@ class ChildSHistory : public nsISupports + */ + bool CanGo(int32_t aOffset); + void Go(int32_t aOffset, bool aRequireUserInteraction, ErrorResult& aRv); +- void AsyncGo(int32_t aOffset, bool aRequireUserInteraction); +- ++ void AsyncGo(int32_t aOffset, bool aRequireUserInteraction, ++ CallerType aCallerType, ErrorResult& aRv); + void RemovePendingHistoryNavigations(); + + /** +diff -r 32d03662a363 -r efcefed227f3 dom/base/LocationBase.cpp +--- a/dom/base/LocationBase.cpp 2020-07-21 04:53:13.000000000 +0800 ++++ b/dom/base/LocationBase.cpp 2021-01-06 10:22:46.030671698 +0800 +@@ -116,6 +116,16 @@ void LocationBase::SetURI(nsIURI* aURI, + return; + } + ++ CallerType callerType = aSubjectPrincipal.IsSystemPrincipal() ++ ? CallerType::System ++ : CallerType::NonSystem; ++ ++ nsresult rv = bc->CheckLocationChangeRateLimit(callerType); ++ if (NS_FAILED(rv)) { ++ aRv.Throw(rv); ++ return; ++ } ++ + RefPtr loadState = + CheckURL(aURI, aSubjectPrincipal, aRv); + if (aRv.Failed()) { +@@ -141,7 +151,7 @@ void LocationBase::SetURI(nsIURI* aURI, + loadState->SetLoadFlags(nsIWebNavigation::LOAD_FLAGS_NONE); + loadState->SetFirstParty(true); + +- nsresult rv = bc->LoadURI(loadState); ++ rv = bc->LoadURI(loadState); + if (NS_WARN_IF(NS_FAILED(rv))) { + aRv.Throw(rv); + } +diff -r 32d03662a363 -r efcefed227f3 dom/base/nsHistory.cpp +--- a/dom/base/nsHistory.cpp 2020-07-21 06:49:37.000000000 +0800 ++++ b/dom/base/nsHistory.cpp 2021-01-06 10:22:46.030671698 +0800 +@@ -135,7 +135,7 @@ void nsHistory::GetState(JSContext* aCx, + aResult.setNull(); + } + +-void nsHistory::Go(int32_t aDelta, ErrorResult& aRv) { ++void nsHistory::Go(int32_t aDelta, CallerType aCallerType, ErrorResult& aRv) { + nsCOMPtr win(do_QueryReferent(mInnerWindow)); + if (!win || !win->HasActiveDocument()) { + return aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); +@@ -157,15 +157,17 @@ void nsHistory::Go(int32_t aDelta, Error + + // Ignore the return value from Go(), since returning errors from Go() can + // lead to exceptions and a possible leak of history length ++ // AsyncGo throws if we hit the location change rate limit. + if (StaticPrefs::dom_window_history_async()) { +- session_history->AsyncGo(aDelta, /* aRequireUserInteraction = */ false); ++ session_history->AsyncGo(aDelta, /* aRequireUserInteraction = */ false, ++ aCallerType, aRv); + } else { + session_history->Go(aDelta, /* aRequireUserInteraction = */ false, + IgnoreErrors()); + } + } + +-void nsHistory::Back(ErrorResult& aRv) { ++void nsHistory::Back(CallerType aCallerType, ErrorResult& aRv) { + nsCOMPtr win(do_QueryReferent(mInnerWindow)); + if (!win || !win->HasActiveDocument()) { + aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); +@@ -181,13 +183,14 @@ void nsHistory::Back(ErrorResult& aRv) { + } + + if (StaticPrefs::dom_window_history_async()) { +- sHistory->AsyncGo(-1, /* aRequireUserInteraction = */ false); ++ sHistory->AsyncGo(-1, /* aRequireUserInteraction = */ false, aCallerType, ++ aRv); + } else { + sHistory->Go(-1, /* aRequireUserInteraction = */ false, IgnoreErrors()); + } + } + +-void nsHistory::Forward(ErrorResult& aRv) { ++void nsHistory::Forward(CallerType aCallerType, ErrorResult& aRv) { + nsCOMPtr win(do_QueryReferent(mInnerWindow)); + if (!win || !win->HasActiveDocument()) { + aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); +@@ -203,7 +206,8 @@ void nsHistory::Forward(ErrorResult& aRv + } + + if (StaticPrefs::dom_window_history_async()) { +- sHistory->AsyncGo(1, /* aRequireUserInteraction = */ false); ++ sHistory->AsyncGo(1, /* aRequireUserInteraction = */ false, aCallerType, ++ aRv); + } else { + sHistory->Go(1, /* aRequireUserInteraction = */ false, IgnoreErrors()); + } +@@ -211,19 +215,20 @@ void nsHistory::Forward(ErrorResult& aRv + + void nsHistory::PushState(JSContext* aCx, JS::Handle aData, + const nsAString& aTitle, const nsAString& aUrl, +- ErrorResult& aRv) { +- PushOrReplaceState(aCx, aData, aTitle, aUrl, aRv, false); ++ CallerType aCallerType, ErrorResult& aRv) { ++ PushOrReplaceState(aCx, aData, aTitle, aUrl, aCallerType, aRv, false); + } + + void nsHistory::ReplaceState(JSContext* aCx, JS::Handle aData, + const nsAString& aTitle, const nsAString& aUrl, +- ErrorResult& aRv) { +- PushOrReplaceState(aCx, aData, aTitle, aUrl, aRv, true); ++ CallerType aCallerType, ErrorResult& aRv) { ++ PushOrReplaceState(aCx, aData, aTitle, aUrl, aCallerType, aRv, true); + } + + void nsHistory::PushOrReplaceState(JSContext* aCx, JS::Handle aData, + const nsAString& aTitle, +- const nsAString& aUrl, ErrorResult& aRv, ++ const nsAString& aUrl, ++ CallerType aCallerType, ErrorResult& aRv, + bool aReplace) { + nsCOMPtr win(do_QueryReferent(mInnerWindow)); + if (!win) { +@@ -238,6 +243,15 @@ void nsHistory::PushOrReplaceState(JSCon + return; + } + ++ BrowsingContext* bc = win->GetBrowsingContext(); ++ if (bc) { ++ nsresult rv = bc->CheckLocationChangeRateLimit(aCallerType); ++ if (NS_FAILED(rv)) { ++ aRv.Throw(rv); ++ return; ++ } ++ } ++ + // AddState might run scripts, so we need to hold a strong reference to the + // docShell here to keep it from going away. + nsCOMPtr docShell = win->GetDocShell(); +diff -r 32d03662a363 -r efcefed227f3 dom/base/nsHistory.h +--- a/dom/base/nsHistory.h 2020-07-21 04:53:13.000000000 +0800 ++++ b/dom/base/nsHistory.h 2021-01-06 10:22:46.030671698 +0800 +@@ -42,14 +42,17 @@ class nsHistory final : public nsISuppor + mozilla::ErrorResult& aRv); + void GetState(JSContext* aCx, JS::MutableHandle aResult, + mozilla::ErrorResult& aRv) const; +- void Go(int32_t aDelta, mozilla::ErrorResult& aRv); +- void Back(mozilla::ErrorResult& aRv); +- void Forward(mozilla::ErrorResult& aRv); ++ void Go(int32_t aDelta, mozilla::dom::CallerType aCallerType, ++ mozilla::ErrorResult& aRv); ++ void Back(mozilla::dom::CallerType aCallerType, mozilla::ErrorResult& aRv); ++ void Forward(mozilla::dom::CallerType aCallerType, mozilla::ErrorResult& aRv); + void PushState(JSContext* aCx, JS::Handle aData, + const nsAString& aTitle, const nsAString& aUrl, ++ mozilla::dom::CallerType aCallerType, + mozilla::ErrorResult& aRv); + void ReplaceState(JSContext* aCx, JS::Handle aData, + const nsAString& aTitle, const nsAString& aUrl, ++ mozilla::dom::CallerType aCallerType, + mozilla::ErrorResult& aRv); + + protected: +@@ -59,6 +62,7 @@ class nsHistory final : public nsISuppor + + void PushOrReplaceState(JSContext* aCx, JS::Handle aData, + const nsAString& aTitle, const nsAString& aUrl, ++ mozilla::dom::CallerType aCallerType, + mozilla::ErrorResult& aRv, bool aReplace); + + already_AddRefed GetSessionHistory() const; +diff -r 32d03662a363 -r efcefed227f3 dom/chrome-webidl/BrowsingContext.webidl +--- a/dom/chrome-webidl/BrowsingContext.webidl 2020-07-21 06:49:37.000000000 +0800 ++++ b/dom/chrome-webidl/BrowsingContext.webidl 2021-01-06 10:22:42.362616481 +0800 +@@ -120,6 +120,9 @@ interface BrowsingContext { + * under the new browser element. + */ + attribute unsigned long long browserId; ++ ++ // Resets the location change rate limit. Used for testing. ++ void resetLocationChangeRateLimit(); + }; + + BrowsingContext includes LoadContextMixin; +diff -r 32d03662a363 -r efcefed227f3 dom/locales/en-US/chrome/dom/dom.properties +--- a/dom/locales/en-US/chrome/dom/dom.properties 2020-07-21 06:49:37.000000000 +0800 ++++ b/dom/locales/en-US/chrome/dom/dom.properties 2021-01-06 10:22:42.418617324 +0800 +@@ -393,3 +393,5 @@ UnknownProtocolNavigationPrevented=Preve + PostMessageSharedMemoryObjectToCrossOriginWarning=Cannot post message containing a shared memory object to a cross-origin window. + # LOCALIZATION NOTE: %S is the URL of the resource in question + UnusedLinkPreloadPending=The resource at ā€œ%Sā€ preloaded with link preload was not used within a few seconds. Make sure all attributes of the preload tag are set correctly. ++# LOCALIZATION NOTE: Do not translate "Location" and "History". ++LocChangeFloodingPrevented=Too many calls to Location or History APIs within a short timeframe. +diff -r 32d03662a363 -r efcefed227f3 dom/webidl/History.webidl +--- a/dom/webidl/History.webidl 2020-07-21 04:53:19.000000000 +0800 ++++ b/dom/webidl/History.webidl 2021-01-06 10:22:42.298615518 +0800 +@@ -21,14 +21,14 @@ interface History { + attribute ScrollRestoration scrollRestoration; + [Throws] + readonly attribute any state; +- [Throws] ++ [Throws, NeedsCallerType] + void go(optional long delta = 0); +- [Throws] ++ [Throws, NeedsCallerType] + void back(); +- [Throws] ++ [Throws, NeedsCallerType] + void forward(); +- [Throws] ++ [Throws, NeedsCallerType] + void pushState(any data, DOMString title, optional DOMString? url = null); +- [Throws] ++ [Throws, NeedsCallerType] + void replaceState(any data, DOMString title, optional DOMString? url = null); + }; +diff -r 32d03662a363 -r efcefed227f3 modules/libpref/init/StaticPrefList.yaml +--- a/modules/libpref/init/StaticPrefList.yaml 2021-01-06 10:25:09.272827991 +0800 ++++ b/modules/libpref/init/StaticPrefList.yaml 2021-01-06 10:22:36.458527604 +0800 +@@ -2181,6 +2181,19 @@ + value: true + mirror: always + ++# Limit of location change caused by content scripts in a time span per ++# BrowsingContext. This includes calls to History and Location APIs. ++- name: dom.navigation.locationChangeRateLimit.count ++ type: uint32_t ++ value: 200 ++ mirror: always ++ ++# Time span in seconds for location change rate limit. ++- name: dom.navigation.locationChangeRateLimit.timespan ++ type: uint32_t ++ value: 10 ++ mirror: always ++ + # Network Information API + - name: dom.netinfo.enabled + type: RelaxedAtomicBool diff --git a/CVE-2020-26963-2.patch b/CVE-2020-26963-2.patch new file mode 100644 index 0000000000000000000000000000000000000000..90a3ba5467949a0723576a9492499aa12dd30e82 --- /dev/null +++ b/CVE-2020-26963-2.patch @@ -0,0 +1,118 @@ +# HG changeset patch +# User pbz +# Date 1600689297 0 +# Mon Sep 21 11:54:57 2020 +0000 +# Node ID ff5164e4aec8cd7a86df0b5f97842fb1f6f765a6 +# Parent efcefed227f304781326e7c8a52633559a79b6ad +Bug 1314912 - Added test for location change rate limit. r=smaug + +Differential Revision: https://phabricator.services.mozilla.com/D90137 + +diff -r efcefed227f3 -r ff5164e4aec8 docshell/test/navigation/mochitest.ini +--- a/docshell/test/navigation/mochitest.ini Mon Sep 21 11:54:50 2020 +0000 ++++ b/docshell/test/navigation/mochitest.ini Mon Sep 21 11:54:57 2020 +0000 +@@ -97,3 +97,4 @@ + [test_triggeringprincipal_parent_iframe_window_open.html] + [test_triggeringprincipal_iframe_iframe_window_open.html] + [test_contentpolicy_block_window.html] ++[test_rate_limit_location_change.html] +diff -r efcefed227f3 -r ff5164e4aec8 docshell/test/navigation/test_rate_limit_location_change.html +--- /dev/null Thu Jan 01 00:00:00 1970 +0000 ++++ b/docshell/test/navigation/test_rate_limit_location_change.html Mon Sep 21 11:54:57 2020 +0000 +@@ -0,0 +1,96 @@ ++ ++ ++ ++ ++ ++ Test for Bug 1314912 ++ ++ ++ ++ ++ ++Mozilla Bug 1314912 ++

++ ++
++
++ ++ diff --git a/CVE-2020-26965.patch b/CVE-2020-26965.patch new file mode 100644 index 0000000000000000000000000000000000000000..12f4d5b8745ab4b3835fca074285fb55db822340 --- /dev/null +++ b/CVE-2020-26965.patch @@ -0,0 +1,28 @@ +# HG changeset patch +# User Makoto Kato +# Date 1601537039 0 +# Thu Oct 01 07:23:59 2020 +0000 +# Node ID 3b746525d6472490b44e55e4766078372e0380c3 +# Parent e6b1234900b328782dd4f93b34222bf49b470ac2 +Bug 1661617 - Use password hint for software keyboard. r=masayuki + +Differential Revision: https://phabricator.services.mozilla.com/D91237 + +diff -r e6b1234900b3 -r 3b746525d647 dom/events/IMEStateManager.cpp +--- a/dom/events/IMEStateManager.cpp Thu Oct 08 05:39:33 2020 +0000 ++++ b/dom/events/IMEStateManager.cpp Thu Oct 01 07:23:59 2020 +0000 +@@ -1260,7 +1260,13 @@ + } + + if (aContent->IsHTMLElement(nsGkAtoms::input)) { +- HTMLInputElement::FromNode(aContent)->GetType(context.mHTMLInputType); ++ HTMLInputElement* inputElement = HTMLInputElement::FromNode(aContent); ++ if (inputElement->HasBeenTypePassword() && aState.IsEditable()) { ++ context.mHTMLInputType.AssignLiteral("password"); ++ } else { ++ inputElement->GetType(context.mHTMLInputType); ++ } ++ + GetActionHint(*aContent, context.mActionHint); + } else if (aContent->IsHTMLElement(nsGkAtoms::textarea)) { + context.mHTMLInputType.Assign(nsGkAtoms::textarea->GetUTF16String()); diff --git a/CVE-2020-26966.patch b/CVE-2020-26966.patch new file mode 100644 index 0000000000000000000000000000000000000000..859a814c500f784064c61f6f6dbcf163faa848c9 --- /dev/null +++ b/CVE-2020-26966.patch @@ -0,0 +1,312 @@ +# HG changeset patch +# User Valentin Gosu +# Date 1604045785 0 +# Fri Oct 30 08:16:25 2020 +0000 +# Node ID 0344d5a76b7db85d4f6d5f5f34649b9111eb6094 +# Parent 3e57839bffd2ea7c3b53a9f7ccd75fd308afd801 +Bug 1663571 - Resolve single label DNS queries using DnsQuery_A r=necko-reviewers,dragana + +Differential Revision: https://phabricator.services.mozilla.com/D91117 + +diff -r 3e57839bffd2 -r 0344d5a76b7d modules/libpref/init/StaticPrefList.yaml +--- a/modules/libpref/init/StaticPrefList.yaml Fri Oct 30 10:19:14 2020 +0000 ++++ b/modules/libpref/init/StaticPrefList.yaml Fri Oct 30 08:16:25 2020 +0000 +@@ -7978,6 +7978,14 @@ + value: 2000 + mirror: always + ++# When true on Windows DNS resolutions for single label domains ++# (domains that don't contain a dot) will be resolved using the DnsQuery ++# API instead of PR_GetAddrInfoByName ++- name: network.dns.dns_query_single_label ++ type: RelaxedAtomicBool ++ value: true ++ mirror: always ++ + # Whether the SOCKS proxy should be in charge of DNS resolution. + - name: network.proxy.socks_remote_dns + type: bool +diff -r 3e57839bffd2 -r 0344d5a76b7d netwerk/dns/GetAddrInfo.cpp +--- a/netwerk/dns/GetAddrInfo.cpp Fri Oct 30 10:19:14 2020 +0000 ++++ b/netwerk/dns/GetAddrInfo.cpp Fri Oct 30 08:16:25 2020 +0000 +@@ -5,6 +5,18 @@ + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + #include "GetAddrInfo.h" ++ ++#ifdef DNSQUERY_AVAILABLE ++// There is a bug in windns.h where the type of parameter ppQueryResultsSet for ++// DnsQuery_A is dependent on UNICODE being set. It should *always* be ++// PDNS_RECORDA, but if UNICODE is set it is PDNS_RECORDW. To get around this ++// we make sure that UNICODE is unset. ++# undef UNICODE ++# include ++# undef GetAddrInfo ++# include ++#endif // DNSQUERY_AVAILABLE ++ + #include "mozilla/ClearOnShutdown.h" + #include "mozilla/net/DNS.h" + #include "NativeDNSResolverOverrideParent.h" +@@ -19,17 +31,6 @@ + #include "mozilla/Logging.h" + #include "mozilla/StaticPrefs_network.h" + +-#ifdef DNSQUERY_AVAILABLE +-// There is a bug in windns.h where the type of parameter ppQueryResultsSet for +-// DnsQuery_A is dependent on UNICODE being set. It should *always* be +-// PDNS_RECORDA, but if UNICODE is set it is PDNS_RECORDW. To get around this +-// we make sure that UNICODE is unset. +-# undef UNICODE +-# include +-# undef GetAddrInfo +-# include +-#endif +- + namespace mozilla { + namespace net { + +@@ -42,6 +43,11 @@ + MOZ_LOG(gGetAddrInfoLog, LogLevel::Warning, ("[DNS]: " msg, ##__VA_ARGS__)) + + #ifdef DNSQUERY_AVAILABLE ++ ++# define COMPUTER_NAME_BUFFER_SIZE 100 ++static char sDNSComputerName[COMPUTER_NAME_BUFFER_SIZE]; ++static char sNETBIOSComputerName[MAX_COMPUTERNAME_LENGTH + 1]; ++ + //////////////////////////// + // WINDOWS IMPLEMENTATION // + //////////////////////////// +@@ -56,45 +62,63 @@ + // equal with the one already there. Gets the TTL value by calling + // to DnsQuery_A and iterating through the returned + // records to find the one with the smallest TTL value. +-static MOZ_ALWAYS_INLINE nsresult _GetMinTTLForRequestType_Windows( +- const char* aHost, uint16_t aRequestType, unsigned int* aResult) { +- MOZ_ASSERT(aHost); +- MOZ_ASSERT(aResult); ++static MOZ_ALWAYS_INLINE nsresult _CallDnsQuery_A_Windows( ++ const nsACString& aHost, uint16_t aAddressFamily, DWORD aFlags, ++ std::function aCallback) { ++ NS_ConvertASCIItoUTF16 name(aHost); ++ ++ auto callDnsQuery_A = [&](uint16_t reqFamily) { ++ PDNS_RECORDA dnsData = nullptr; ++ DNS_STATUS status = DnsQuery_A(aHost.BeginReading(), reqFamily, aFlags, ++ nullptr, &dnsData, nullptr); ++ if (status == DNS_INFO_NO_RECORDS || status == DNS_ERROR_RCODE_NAME_ERROR || ++ !dnsData) { ++ LOG("No DNS records found for %s. status=%X. reqFamily = %X\n", ++ aHost.BeginReading(), status, reqFamily); ++ return NS_ERROR_FAILURE; ++ } else if (status != NOERROR) { ++ LOG_WARNING("DnsQuery_A failed with status %X.\n", status); ++ return NS_ERROR_UNEXPECTED; ++ } + +- PDNS_RECORDA dnsData = nullptr; +- DNS_STATUS status = DnsQuery_A( +- aHost, aRequestType, +- (DNS_QUERY_STANDARD | DNS_QUERY_NO_NETBT | DNS_QUERY_NO_HOSTS_FILE | +- DNS_QUERY_NO_MULTICAST | DNS_QUERY_ACCEPT_TRUNCATED_RESPONSE | +- DNS_QUERY_DONT_RESET_TTL_VALUES), +- nullptr, &dnsData, nullptr); +- if (status == DNS_INFO_NO_RECORDS || status == DNS_ERROR_RCODE_NAME_ERROR || +- !dnsData) { +- LOG("No DNS records found for %s. status=%X. aRequestType = %X\n", aHost, +- status, aRequestType); +- return NS_ERROR_FAILURE; +- } else if (status != NOERROR) { +- LOG_WARNING("DnsQuery_A failed with status %X.\n", status); +- return NS_ERROR_UNEXPECTED; ++ for (PDNS_RECORDA curRecord = dnsData; curRecord; ++ curRecord = curRecord->pNext) { ++ // Only records in the answer section are important ++ if (curRecord->Flags.S.Section != DnsSectionAnswer) { ++ continue; ++ } ++ if (curRecord->wType != reqFamily) { ++ continue; ++ } ++ ++ aCallback(curRecord); ++ } ++ ++ DnsFree(dnsData, DNS_FREE_TYPE::DnsFreeRecordList); ++ return NS_OK; ++ }; ++ ++ if (aAddressFamily == PR_AF_UNSPEC || aAddressFamily == PR_AF_INET) { ++ callDnsQuery_A(DNS_TYPE_A); + } + +- for (PDNS_RECORDA curRecord = dnsData; curRecord; +- curRecord = curRecord->pNext) { +- // Only records in the answer section are important +- if (curRecord->Flags.S.Section != DnsSectionAnswer) { +- continue; +- } ++ if (aAddressFamily == PR_AF_UNSPEC || aAddressFamily == PR_AF_INET6) { ++ callDnsQuery_A(DNS_TYPE_AAAA); ++ } ++ return NS_OK; ++} + +- if (curRecord->wType == aRequestType) { +- *aResult = std::min(*aResult, curRecord->dwTtl); +- } else { +- LOG("Received unexpected record type %u in response for %s.\n", +- curRecord->wType, aHost); +- } ++bool recordTypeMatchesRequest(uint16_t wType, uint16_t aAddressFamily) { ++ if (aAddressFamily == PR_AF_UNSPEC) { ++ return wType == DNS_TYPE_A || wType == DNS_TYPE_AAAA; + } +- +- DnsFree(dnsData, DNS_FREE_TYPE::DnsFreeRecordList); +- return NS_OK; ++ if (aAddressFamily == PR_AF_INET) { ++ return wType == DNS_TYPE_A; ++ } ++ if (aAddressFamily == PR_AF_INET6) { ++ return wType == DNS_TYPE_AAAA; ++ } ++ return false; + } + + static MOZ_ALWAYS_INLINE nsresult _GetTTLData_Windows(const nsACString& aHost, +@@ -110,13 +134,21 @@ + // In order to avoid using ANY records which are not always implemented as a + // "Gimme what you have" request in hostname resolvers, we should send A + // and/or AAAA requests, based on the address family requested. ++ const DWORD ttlFlags = ++ (DNS_QUERY_STANDARD | DNS_QUERY_NO_NETBT | DNS_QUERY_NO_HOSTS_FILE | ++ DNS_QUERY_NO_MULTICAST | DNS_QUERY_ACCEPT_TRUNCATED_RESPONSE | ++ DNS_QUERY_DONT_RESET_TTL_VALUES); + unsigned int ttl = (unsigned int)-1; +- if (aAddressFamily == PR_AF_UNSPEC || aAddressFamily == PR_AF_INET) { +- _GetMinTTLForRequestType_Windows(aHost.BeginReading(), DNS_TYPE_A, &ttl); +- } +- if (aAddressFamily == PR_AF_UNSPEC || aAddressFamily == PR_AF_INET6) { +- _GetMinTTLForRequestType_Windows(aHost.BeginReading(), DNS_TYPE_AAAA, &ttl); +- } ++ _CallDnsQuery_A_Windows( ++ aHost, aAddressFamily, ttlFlags, ++ [&ttl, &aHost, aAddressFamily](PDNS_RECORDA curRecord) { ++ if (recordTypeMatchesRequest(curRecord->wType, aAddressFamily)) { ++ ttl = std::min(ttl, curRecord->dwTtl); ++ } else { ++ LOG("Received unexpected record type %u in response for %s.\n", ++ curRecord->wType, aHost.BeginReading()); ++ } ++ }); + + if (ttl == (unsigned int)-1) { + LOG("No useable TTL found."); +@@ -126,6 +158,41 @@ + *aResult = ttl; + return NS_OK; + } ++ ++static MOZ_ALWAYS_INLINE nsresult ++_DNSQuery_A_SingleLabel(const nsACString& aCanonHost, uint16_t aAddressFamily, ++ uint16_t aFlags, AddrInfo** aAddrInfo) { ++ bool setCanonName = aFlags & nsHostResolver::RES_CANON_NAME; ++ nsAutoCString canonName; ++ const DWORD flags = (DNS_QUERY_STANDARD | DNS_QUERY_NO_MULTICAST | ++ DNS_QUERY_ACCEPT_TRUNCATED_RESPONSE); ++ nsTArray addresses; ++ ++ _CallDnsQuery_A_Windows( ++ aCanonHost, aAddressFamily, flags, [&](PDNS_RECORDA curRecord) { ++ MOZ_DIAGNOSTIC_ASSERT(curRecord->wType == DNS_TYPE_A || ++ curRecord->wType == DNS_TYPE_AAAA); ++ if (setCanonName) { ++ canonName.Assign(curRecord->pName); ++ } ++ NetAddr addr{}; ++ addr.inet.family = AF_INET; ++ addr.inet.ip = curRecord->Data.A.IpAddress; ++ addresses.AppendElement(addr); ++ }); ++ ++ LOG("Query for: %s has %u results", aCanonHost.BeginReading(), ++ addresses.Length()); ++ if (addresses.IsEmpty()) { ++ return NS_ERROR_UNKNOWN_HOST; ++ } ++ RefPtr ai( ++ new AddrInfo(aCanonHost, canonName, 0, std::move(addresses))); ++ ai.forget(aAddrInfo); ++ ++ return NS_OK; ++} ++ + #endif + + //////////////////////////////////// +@@ -153,6 +220,24 @@ + aAddressFamily = PR_AF_UNSPEC; + } + ++#if defined(DNSQUERY_AVAILABLE) ++ if (StaticPrefs::network_dns_dns_query_single_label() && ++ !aCanonHost.Contains('.') && aCanonHost != NS_LITERAL_CSTRING("localhost")) { ++ // For some reason we can't use DnsQuery_A to get the computer's IP. ++ if (!aCanonHost.Equals(nsDependentCString(sDNSComputerName), ++ nsCaseInsensitiveCStringComparator) && ++ !aCanonHost.Equals(nsDependentCString(sNETBIOSComputerName), ++ nsCaseInsensitiveCStringComparator)) { ++ // This is a single label name resolve without a dot. ++ // We use DNSQuery_A for these. ++ LOG("Resolving %s using DnsQuery_A (computername: %s)\n", ++ aCanonHost.BeginReading(), sDNSComputerName); ++ return _DNSQuery_A_SingleLabel(aCanonHost, aAddressFamily, aFlags, ++ aAddrInfo); ++ } ++ } ++#endif ++ + PRAddrInfo* prai = + PR_GetAddrInfoByName(aCanonHost.BeginReading(), aAddressFamily, prFlags); + +@@ -184,6 +269,19 @@ + ////////////////////////////////////// + nsresult GetAddrInfoInit() { + LOG("Initializing GetAddrInfo.\n"); ++ ++#ifdef DNSQUERY_AVAILABLE ++ DWORD namesize = COMPUTER_NAME_BUFFER_SIZE; ++ if (!GetComputerNameEx(ComputerNameDnsHostname, sDNSComputerName, ++ &namesize)) { ++ sDNSComputerName[0] = 0; ++ } ++ namesize = MAX_COMPUTERNAME_LENGTH + 1; ++ if (!GetComputerNameEx(ComputerNameNetBIOS, sNETBIOSComputerName, ++ &namesize)) { ++ sNETBIOSComputerName[0] = 0; ++ } ++#endif + return NS_OK; + } + +diff -r 3e57839bffd2 -r 0344d5a76b7d netwerk/dns/moz.build +--- a/netwerk/dns/moz.build Fri Oct 30 10:19:14 2020 +0000 ++++ b/netwerk/dns/moz.build Fri Oct 30 08:16:25 2020 +0000 +@@ -54,6 +54,7 @@ + ] + + SOURCES += [ ++ 'GetAddrInfo.cpp', # Undefines UNICODE + 'nsEffectiveTLDService.cpp', # Excluded from UNIFIED_SOURCES due to special build flags. + 'nsHostResolver.cpp', # Redefines LOG + ] +@@ -65,7 +66,6 @@ + 'DNSRequestChild.cpp', + 'DNSRequestParent.cpp', +- 'GetAddrInfo.cpp', + 'HTTPSSVC.cpp', + 'IDNBlocklistUtils.cpp', + 'NativeDNSResolverOverrideChild.cpp', + 'NativeDNSResolverOverrideParent.cpp', diff --git a/CVE-2020-26967.patch b/CVE-2020-26967.patch new file mode 100644 index 0000000000000000000000000000000000000000..90f1db15faed42bcc7bb9eaf4aa1e214c5be3f2e --- /dev/null +++ b/CVE-2020-26967.patch @@ -0,0 +1,21 @@ +# HG changeset patch +# User Kaizer Soze +# Date 1602665311 0 +# Wed Oct 14 08:48:31 2020 +0000 +# Node ID 5a4b06d86f52685f2a4b51538f9ac3a7d9be265b +# Parent 1547b1a7189503e22eaa2180fa9597a044b91ff8 +Bug 1665820, r=emalysz + +Differential Revision: https://phabricator.services.mozilla.com/D92589 + +diff -r 1547b1a71895 -r 5a4b06d86f52 browser/extensions/screenshots/selector/ui.js +--- a/browser/extensions/screenshots/selector/ui.js Wed Oct 14 09:17:27 2020 +0000 ++++ b/browser/extensions/screenshots/selector/ui.js Wed Oct 14 08:48:31 2020 +0000 +@@ -361,6 +361,7 @@ + this.element.setAttribute("role", "dialog"); + this.element.onload = watchFunction(() => { + msgsPromise.then(([cancelTitle, copyTitle, downloadTitle]) => { ++ assertIsBlankDocument(this.element.contentDocument); + this.document = this.element.contentDocument; + // eslint-disable-next-line no-unsanitized/property + this.document.documentElement.innerHTML = ` diff --git a/firefox.spec b/firefox.spec index b7dbb2dd34fef6e8d2954146c1f724c38c0e3fd8..95dce21c0428ead7a12bb41db28465c3e2085ab0 100644 --- a/firefox.spec +++ b/firefox.spec @@ -88,7 +88,7 @@ Summary: Mozilla Firefox Web browser Name: firefox Version: 79.0 -Release: 4 +Release: 5 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 @@ -153,6 +153,28 @@ Patch607: CVE-2020-15668.patch Patch608: CVE-2020-15676.patch Patch609: CVE-2020-15677.patch Patch610: CVE-2020-15678.patch +Patch611: CVE-2020-15969.patch +Patch612: CVE-2020-15999.patch +Patch613: CVE-2020-16012.patch +Patch614: CVE-2020-26951-1.patch +Patch615: CVE-2020-26951-2.patch +Patch616: CVE-2020-26953-pre.patch +Patch617: CVE-2020-26953.patch +Patch618: CVE-2020-26956-1.patch +Patch619: CVE-2020-26956-2.patch +Patch620: CVE-2020-26956-3.patch +Patch621: CVE-2020-26957.patch +Patch622: CVE-2020-26958.patch +Patch623: CVE-2020-26959.patch +Patch624: CVE-2020-26960-1.patch +Patch625: CVE-2020-26960-2.patch +Patch626: CVE-2020-26961-1.patch +Patch627: CVE-2020-26961-2.patch +Patch628: CVE-2020-26963-1.patch +Patch629: CVE-2020-26963-2.patch +Patch630: CVE-2020-26965.patch +Patch631: CVE-2020-26966.patch +Patch632: CVE-2020-26967.patch %if %{?system_nss} BuildRequires: pkgconfig(nspr) >= %{nspr_version} pkgconfig(nss) >= %{nss_version} BuildRequires: nss-static >= %{nss_version} @@ -297,6 +319,28 @@ tar -xf %{SOURCE3} %patch608 -p1 %patch609 -p1 %patch610 -p1 +%patch611 -p1 +%patch612 -p1 +%patch613 -p1 +%patch614 -p1 +%patch615 -p1 +%patch616 -p1 +%patch617 -p1 +%patch618 -p1 +%patch619 -p1 +%patch620 -p1 +%patch621 -p1 +%patch622 -p1 +%patch623 -p1 +%patch624 -p1 +%patch625 -p1 +%patch626 -p1 +%patch627 -p1 +%patch628 -p1 +%patch629 -p1 +%patch630 -p1 +%patch631 -p1 +%patch632 -p1 %{__rm} -f .mozconfig %{__cp} %{SOURCE10} .mozconfig echo "ac_add_options --enable-default-toolkit=cairo-gtk3-wayland" >> .mozconfig @@ -744,6 +788,12 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : %endif %changelog +* Thu Jan 07 2021 wangxiao - 79.0-5 +- Fix CVE-2020-15969 CVE-2020-15999 CVE-2020-16012 CVE-2020-26951 + CVE-2020-26953 CVE-2020-26956 CVE-2020-26957 CVE-2020-26958 + CVE-2020-26959 CVE-2020-26960 CVE-2020-26961 CVE-2020-26963 + CVE-2020-26965 CVE-2020-25966 CVE-2020-26967 + * Wed Dec 16 2020 wangxiao - 79.0-4 - Fix CVE-2020-15664 CVE-2020-15665 CVE-2020-15666 CVE-2020-15667 CVE-2020-15668 CVE-2020-15676 CVE-2020-15677 CVE-2020-15678