This commit is contained in:
wangxiao65 2021-01-07 15:15:15 +08:00
parent 60f67e1c86
commit 3d3d4358d9
23 changed files with 3479 additions and 1 deletions

51
CVE-2020-15969.patch Normal file
View File

@ -0,0 +1,51 @@
# HG changeset patch
# User Dan Minor <dminor@mozilla.com>
# 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;
}
}

45
CVE-2020-15999.patch Normal file
View File

@ -0,0 +1,45 @@
# HG changeset patch
# User Werner Lemberg <wl@gnu.org>
# 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 */

406
CVE-2020-16012.patch Normal file
View File

@ -0,0 +1,406 @@
# HG changeset patch
# User Lee Salzman <lsalzman@mozilla.com>
# 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 <immintrin.h>
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 <arm_neon.h>
+ // 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<const uint8_t*>(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<uint8_t*>(dst), src_col);
- dst += 8;
- continue;
- }
-
- uint8x8x4_t dst_col = vld4_u8(reinterpret_cast<uint8_t*>(dst));
- vst4_u8(reinterpret_cast<uint8_t*>(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<const uint8_t*>(src));
- uint8x8_t dst2 = vld1_u8(reinterpret_cast<const uint8_t*>(dst));
- vst1_u8(reinterpret_cast<uint8_t*>(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

102
CVE-2020-26951-1.patch Normal file
View File

@ -0,0 +1,102 @@
# HG changeset patch
# User Henri Sivonen <hsivonen@hsivonen.fi>
# 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<Document> inert;
RefPtr<DocumentFragment> 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<Document> doc;
nsCOMPtr<nsIPrincipal> 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 =

177
CVE-2020-26951-2.patch Normal file
View File

@ -0,0 +1,177 @@
# HG changeset patch
# User Henri Sivonen <hsivonen@hsivonen.fi>
# 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 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset=utf-8>
+ <title>Test for Bug 1667113</title>
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1667113">Mozilla Bug 1667113</a>
+<div></div>
+<script>
+SimpleTest.waitForExplicitFinish();
+
+// Please note that 'fakeServer' does not exist because the test relies
+// on "csp-on-violate-policy" , and "specialpowers-http-notify-request"
+// which fire if either the request is blocked or fires. The test does
+// not rely on the result of the load.
+
+function fail() {
+ ok(false, "Should not call this")
+}
+
+function examiner() {
+ SpecialPowers.addObserver(this, "csp-on-violate-policy");
+ SpecialPowers.addObserver(this, "specialpowers-http-notify-request");
+}
+examiner.prototype = {
+ observe(subject, topic, data) {
+ if (topic === "csp-on-violate-policy") {
+ let asciiSpec = SpecialPowers.getPrivilegedProps(
+ SpecialPowers.do_QueryInterface(subject, "nsIURI"),
+ "asciiSpec");
+ if (asciiSpec.includes("fakeServer")) {
+ ok (false, "Should not attempt fetch, not even blocked by CSP.");
+ }
+ }
+
+ if (topic === "specialpowers-http-notify-request") {
+ if (data.includes("fakeServer")) {
+ ok (false, "Should not try fetch");
+ }
+ }
+ },
+ remove() {
+ SpecialPowers.removeObserver(this, "csp-on-violate-policy");
+ SpecialPowers.removeObserver(this, "specialpowers-http-notify-request");
+ }
+}
+
+window.examiner = new examiner();
+
+let div = document.getElementsByTagName("div")[0];
+div.innerHTML = "<svg><style><title><audio src=fakeServer onerror=fail() onload=fail()>";
+
+let svg = div.firstChild;
+is(svg.nodeName, "svg", "Node name should be svg");
+
+let style = svg.firstChild;
+if (style) {
+ is(style.firstChild, null, "Style should not have child nodes.");
+} else {
+ ok(false, "Should have gotten a node.");
+}
+
+
+SimpleTest.executeSoon(function() {
+ window.examiner.remove();
+ SimpleTest.finish();
+});
+
+</script>
+</body>
+</html>
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 @@
+<!DOCTYPE HTML>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Test for Bug 1667113</title>
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1667113">Mozilla Bug 1667113</a>
+<div></div>
+<script><![CDATA[
+SimpleTest.waitForExplicitFinish();
+
+// Please note that 'fakeServer' does not exist because the test relies
+// on "csp-on-violate-policy" , and "specialpowers-http-notify-request"
+// which fire if either the request is blocked or fires. The test does
+// not rely on the result of the load.
+
+function fail() {
+ ok(false, "Should not call this")
+}
+
+function examiner() {
+ SpecialPowers.addObserver(this, "csp-on-violate-policy");
+ SpecialPowers.addObserver(this, "specialpowers-http-notify-request");
+}
+examiner.prototype = {
+ observe(subject, topic, data) {
+ if (topic === "csp-on-violate-policy") {
+ let asciiSpec = SpecialPowers.getPrivilegedProps(
+ SpecialPowers.do_QueryInterface(subject, "nsIURI"),
+ "asciiSpec");
+ if (asciiSpec.includes("fakeServer")) {
+ ok (false, "Should not attempt fetch, not even blocked by CSP.");
+ }
+ }
+
+ if (topic === "specialpowers-http-notify-request") {
+ if (data.includes("fakeServer")) {
+ ok (false, "Should not try fetch");
+ }
+ }
+ },
+ remove() {
+ SpecialPowers.removeObserver(this, "csp-on-violate-policy");
+ SpecialPowers.removeObserver(this, "specialpowers-http-notify-request");
+ }
+}
+
+window.examiner = new examiner();
+
+let div = document.getElementsByTagName("div")[0];
+div.innerHTML = "<svg xmlns='http://www.w3.org/2000/svg'><style><title><audio xmlns='http://www.w3.org/1999/xhtml' src='fakeServer' onerror='fail()' onload='fail()'></audio></title></style></svg>";
+
+let svg = div.firstChild;
+is(svg.nodeName, "svg", "Node name should be svg");
+
+let style = svg.firstChild;
+if (style) {
+ is(style.firstChild, null, "Style should not have child nodes.");
+} else {
+ ok(false, "Should have gotten a node.");
+}
+
+
+SimpleTest.executeSoon(function() {
+ window.examiner.remove();
+ SimpleTest.finish();
+});
+
+]]></script>
+</body>
+</html>

85
CVE-2020-26953-pre.patch Normal file
View File

@ -0,0 +1,85 @@
# HG changeset patch
# User Alphan Chen <alchen@mozilla.com>
# 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;
},

231
CVE-2020-26953.patch Normal file
View File

@ -0,0 +1,231 @@
# HG changeset patch
# User Steven MacLeod <steven@smacleod.ca>
# 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) {

56
CVE-2020-26956-1.patch Normal file
View File

@ -0,0 +1,56 @@
# HG changeset patch
# User Henri Sivonen <hsivonen@hsivonen.fi>
# 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.

171
CVE-2020-26956-2.patch Normal file
View File

@ -0,0 +1,171 @@
# HG changeset patch
# User Henri Sivonen <hsivonen@hsivonen.fi>
# 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<nsIURI> uri;
- NS_NewURI(getter_AddRefs(uri), "about:blank");
- nsCOMPtr<nsIPrincipal> principal =
- NullPrincipal::CreateWithoutOriginAttributes();
- RefPtr<Document> 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> 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<Document> nsContentUtils::CreateInertXMLDocument(
+ const Document* aTemplate) {
+ return nsContentUtils::CreateInertDocument(aTemplate, DocumentFlavorXML);
+}
+
+/* static */
+already_AddRefed<Document> nsContentUtils::CreateInertHTMLDocument(
+ const Document* aTemplate) {
+ return nsContentUtils::CreateInertDocument(aTemplate, DocumentFlavorHTML);
+}
+
+/* static */
+already_AddRefed<Document> nsContentUtils::CreateInertDocument(
+ const Document* aTemplate, DocumentFlavor aFlavor) {
+ if (aTemplate) {
+ bool hasHad = true;
+ nsIScriptGlobalObject* sgo = aTemplate->GetScriptHandlingObject(hasHad);
+ NS_ENSURE_TRUE(sgo || !hasHad, nullptr);
+
+ nsCOMPtr<Document> 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<nsIURI> uri;
+ NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("about:blank"));
+ if (!uri) {
+ return nullptr;
+ }
+
+ RefPtr<NullPrincipal> nullPrincipal =
+ NullPrincipal::CreateWithoutOriginAttributes();
+ if (!nullPrincipal) {
+ return nullptr;
+ }
+
+ nsCOMPtr<Document> 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<Document> 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<Document> CreateInertXMLDocument(
+ const Document* aTemplate);
+
+ private:
+ static already_AddRefed<Document> 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<DocumentFragment> fragment = new (aTargetDocument->NodeInfoManager())
- DocumentFragment(aTargetDocument->NodeInfoManager());
+ nsCOMPtr<Document> doc =
+ nsContentUtils::CreateInertHTMLDocument(aTargetDocument);
+ if (!doc) {
+ return NS_ERROR_FAILURE;
+ }
+ RefPtr<DocumentFragment> 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<nsIURI> uri;
- NS_NewURI(getter_AddRefs(uri), "about:blank");
- nsCOMPtr<nsIPrincipal> principal =
- mozilla::NullPrincipal::CreateWithoutOriginAttributes();
- RefPtr<Document> document;
- nsresult rv = NS_NewDOMDocument(getter_AddRefs(document), EmptyString(),
- EmptyString(), nullptr, uri, uri, principal,
- true, nullptr, DocumentFlavorHTML);
- NS_ENSURE_SUCCESS(rv, rv);
+ RefPtr<Document> 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);

99
CVE-2020-26956-3.patch Normal file
View File

@ -0,0 +1,99 @@
# HG changeset patch
# User Henri Sivonen <hsivonen@hsivonen.fi>
# 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("<svg xmlns='http://www.w3.org/2000/svg'>Not supposed to load this</svg>");
+ }
+}
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 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test pasting table rows</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<textarea></textarea>
+<div contenteditable="true">Paste target</div>
+<script>
+ SimpleTest.waitForExplicitFinish();
+ function fail() {
+ ok(false, "Should not run event handlers.");
+ }
+ document.addEventListener('copy', ev => {
+ dump("IN LISTENER\n");
+ const payload = `<svg><style><image href=file_sanitizer_on_paste.sjs onerror=fail() onload=fail()>`
+
+ ev.preventDefault();
+ ev.clipboardData.setData('text/html', payload);
+ ev.clipboardData.setData('text/plain', payload);
+ });
+
+ document.getElementsByTagName("textarea")[0].focus();
+ synthesizeKey("c", { accelKey: true } /* aEvent*/);
+
+ let div = document.getElementsByTagName("div")[0];
+ div.focus();
+ synthesizeKey("v", { accelKey: true } /* aEvent*/);
+
+ let svg = div.firstChild;
+ is(svg.nodeName, "svg", "Node name should be svg");
+
+ let style = svg.firstChild;
+ if (style) {
+ is(style.firstChild, null, "Style should not have child nodes.");
+ } else {
+ ok(false, "Should have gotten a node.");
+ }
+
+ var s = document.createElement("script");
+ s.src = "file_sanitizer_on_paste.sjs?report=1";
+ document.body.appendChild(s);
+</script>
+</body>
\ No newline at end of file

33
CVE-2020-26957.patch Normal file
View File

@ -0,0 +1,33 @@
# HG changeset patch
# User Agi Sferro <agi@sferro.dev>
# 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.

768
CVE-2020-26958.patch Normal file
View File

@ -0,0 +1,768 @@
# HG changeset patch
# User Andrew Sutherland <asutherland@asutherland.org>
# 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<nsString, 1> params;
+ CopyUTF8toUTF16(contentTypeOptionsHeader, *params.AppendElement());
+ RefPtr<dom::Document> 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<nsIURI> 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<HttpBaseChannel>;
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<nsString, 1> params;
- CopyUTF8toUTF16(contentTypeOptionsHeader, *params.AppendElement());
- RefPtr<Document> 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<nsIURI> 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

63
CVE-2020-26959.patch Normal file
View File

@ -0,0 +1,63 @@
# HG changeset patch
# User Luca Greco <lgreco@mozilla.com>
# 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<WebRequestService> sWebRequestService;
/* static */ WebRequestService& WebRequestService::GetSingleton() {
- static RefPtr<WebRequestService> 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<WebRequestChannelEntry> 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;

49
CVE-2020-26960-1.patch Normal file
View File

@ -0,0 +1,49 @@
# HG changeset patch
# User Jon Coppeard <jcoppeard@mozilla.com>
# 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<Header*>(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<Header*>(ptr);
mHdr->mCapacity = length;
}

136
CVE-2020-26960-2.patch Normal file
View File

@ -0,0 +1,136 @@
# HG changeset patch
# User Jon Coppeard <jcoppeard@mozilla.com>
# 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<T> 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 <class ArrayT>
-static void RunTest(JSContext* cx, ArrayT* array) {
+static void TestGrow(JSContext* cx) {
JS_GC(cx);
+ auto array = MakeUnique<ArrayT>();
ASSERT_TRUE(array != nullptr);
- JS_AddExtraGCRootsTracer(cx, TraceArray<ArrayT>, array);
+
+ JS_AddExtraGCRootsTracer(cx, TraceArray<ArrayT>, 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<int32_t>(i), value.toInt32());
}
- JS_RemoveExtraGCRootsTracer(cx, TraceArray<ArrayT>, array);
+ JS_RemoveExtraGCRootsTracer(cx, TraceArray<ArrayT>, array.get());
+}
+
+template <class ArrayT>
+static void TestShrink(JSContext* cx) {
+ JS_GC(cx);
+
+ auto array = MakeUnique<ArrayT>();
+ ASSERT_TRUE(array != nullptr);
+
+ JS_AddExtraGCRootsTracer(cx, TraceArray<ArrayT>, 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<int32_t>(i), value.toInt32());
+ }
+
+ JS_RemoveExtraGCRootsTracer(cx, TraceArray<ArrayT>, array.get());
+}
+
+template <class ArrayT>
+static void TestArrayType(JSContext* cx) {
+ TestGrow<ArrayT>(cx);
+ TestShrink<ArrayT>(cx);
}
static void CreateGlobalAndRunTest(JSContext* cx) {
@@ -89,25 +141,11 @@
JS::Realm* oldRealm = JS::EnterRealm(cx, global);
- typedef Heap<JSObject*> ElementT;
-
- {
- nsTArray<ElementT>* array = new nsTArray<ElementT>(InitialElements);
- RunTest(cx, array);
- delete array;
- }
+ using ElementT = Heap<JSObject*>;
- {
- FallibleTArray<ElementT>* array =
- new FallibleTArray<ElementT>(InitialElements);
- RunTest(cx, array);
- delete array;
- }
-
- {
- AutoTArray<ElementT, InitialElements> array;
- RunTest(cx, &array);
- }
+ TestArrayType<nsTArray<ElementT>>(cx);
+ TestArrayType<FallibleTArray<ElementT>>(cx);
+ TestArrayType<AutoTArray<ElementT, 1>>(cx);
JS::LeaveRealm(cx, oldRealm);
}

58
CVE-2020-26961-1.patch Normal file
View File

@ -0,0 +1,58 @@
# HG changeset patch
# User Valentin Gosu <valentin.gosu@gmail.com>
# 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;
}

47
CVE-2020-26961-2.patch Normal file
View File

@ -0,0 +1,47 @@
# HG changeset patch
# User Valentin Gosu <valentin.gosu@gmail.com>
# 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)

371
CVE-2020-26963-1.patch Normal file
View File

@ -0,0 +1,371 @@
# HG changeset patch
# User pbz <pbz@mozilla.com>
# 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<SessionStorageManager> mSessionStorageManager;
RefPtr<ChildSHistory> 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<nsDocShellLoadState> 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<nsPIDOMWindowInner> 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<nsPIDOMWindowInner> 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<nsPIDOMWindowInner> 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<JS::Value> 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<JS::Value> 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<JS::Value> aData,
const nsAString& aTitle,
- const nsAString& aUrl, ErrorResult& aRv,
+ const nsAString& aUrl,
+ CallerType aCallerType, ErrorResult& aRv,
bool aReplace) {
nsCOMPtr<nsPIDOMWindowInner> 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<nsIDocShell> 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<JS::Value> 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<JS::Value> aData,
const nsAString& aTitle, const nsAString& aUrl,
+ mozilla::dom::CallerType aCallerType,
mozilla::ErrorResult& aRv);
void ReplaceState(JSContext* aCx, JS::Handle<JS::Value> 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<JS::Value> aData,
const nsAString& aTitle, const nsAString& aUrl,
+ mozilla::dom::CallerType aCallerType,
mozilla::ErrorResult& aRv, bool aReplace);
already_AddRefed<mozilla::dom::ChildSHistory> 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

118
CVE-2020-26963-2.patch Normal file
View File

@ -0,0 +1,118 @@
# HG changeset patch
# User pbz <pbz@mozilla.com>
# 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 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1314912
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1314912</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+ /** Test for Bug 1314912 **/
+
+ const RATE_LIMIT_COUNT = 90;
+ const RATE_LIMIT_TIME_SPAN = 3;
+
+ async function setup() {
+ await SpecialPowers.pushPrefEnv({set: [
+ ["dom.navigation.locationChangeRateLimit.count", RATE_LIMIT_COUNT],
+ ["dom.navigation.locationChangeRateLimit.timespan", RATE_LIMIT_TIME_SPAN]]});
+ }
+
+ let inc = 0;
+
+ const rateLimitedFunctions = (win) => ({
+ "history.replaceState": () => win.history.replaceState(null, "test", `${win.location.href}#${inc++}`),
+ "history.pushState": () => win.history.pushState(null, "test", `${win.location.href}#${inc++}`),
+ "history.back": () => win.history.back(),
+ "history.forward": () => win.history.forward(),
+ "history.go": () => win.history.go(-1),
+ "location.hash": () => win.location.hash = inc++,
+ "location.host": () => win.location.host = win.location.host + "",
+ "location.hostname": () => win.location.hostname = win.location.hostname + "",
+ "location.pathname": () => win.location.pathname = win.location.pathname + "",
+ "location.port": () => win.location.port = win.location.port + "",
+ "location.protocol": () => win.location.protocol = win.location.protocol + "",
+ "location.search": () => win.location.search = win.location.search + "",
+ });
+
+ async function test() {
+ await setup();
+
+ // Open new window and wait for it to load
+ let win = window.open("blank.html");
+ await new Promise((resolve) => SimpleTest.waitForFocus(resolve, win))
+
+ // Execute the history and location functions
+ Object.entries(rateLimitedFunctions(win)).forEach(([name, fn]) => {
+ // Reset the rate limit for the next run.
+ info("Reset rate limit.");
+ SpecialPowers.wrap(win).browsingContext.resetLocationChangeRateLimit();
+
+ info(`Calling ${name} ${RATE_LIMIT_COUNT} times to reach the rate limit.`);
+ for(let i = 0; i< RATE_LIMIT_COUNT; i++) {
+ fn.call(this);
+ }
+ // Next calls should throw because we're above the rate limit
+ for(let i = 0; i < 5; i++) {
+ SimpleTest.doesThrow(() => fn.call(this), `Call #${RATE_LIMIT_COUNT + i + 1} to ${name} should throw.`);
+ }
+ })
+
+ // We didn't reset the rate limit after the last loop iteration above.
+ // Wait for the rate limit timer to expire.
+ SimpleTest.requestFlakyTimeout("Waiting to trigger rate limit reset.");
+ await new Promise((resolve) => setTimeout(resolve, 5000));
+
+ // Calls should be allowed again.
+ Object.entries(rateLimitedFunctions(win)).forEach(([name, fn]) => {
+ let didThrow = false;
+ try {
+ fn.call(this);
+ } catch(error) {
+ didThrow = true;
+ }
+ is(didThrow, false, `Call to ${name} must not throw.`)
+ });
+
+ // Cleanup
+ win.close();
+ SpecialPowers.wrap(win).browsingContext.resetLocationChangeRateLimit();
+ SimpleTest.finish();
+ }
+
+ </script>
+</head>
+<body onload="setTimeout(test, 0);">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1314912">Mozilla Bug 1314912</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>

28
CVE-2020-26965.patch Normal file
View File

@ -0,0 +1,28 @@
# HG changeset patch
# User Makoto Kato <m_kato@ga2.so-net.ne.jp>
# 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());

312
CVE-2020-26966.patch Normal file
View File

@ -0,0 +1,312 @@
# HG changeset patch
# User Valentin Gosu <valentin.gosu@gmail.com>
# 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 <ws2tcpip.h>
+# undef GetAddrInfo
+# include <windns.h>
+#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 <ws2tcpip.h>
-# undef GetAddrInfo
-# include <windns.h>
-#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<void(PDNS_RECORDA)> 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<unsigned int>(*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<unsigned int>(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<NetAddr> 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<AddrInfo> 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',

21
CVE-2020-26967.patch Normal file
View File

@ -0,0 +1,21 @@
# HG changeset patch
# User Kaizer Soze <kaizersoze915@gmail.com>
# 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 = `

View File

@ -88,7 +88,7 @@
Summary: Mozilla Firefox Web browser Summary: Mozilla Firefox Web browser
Name: firefox Name: firefox
Version: 79.0 Version: 79.0
Release: 4 Release: 5
URL: https://www.mozilla.org/firefox/ URL: https://www.mozilla.org/firefox/
License: MPLv1.1 or GPLv2+ or LGPLv2+ License: MPLv1.1 or GPLv2+ or LGPLv2+
Source0: https://archive.mozilla.org/pub/firefox/releases/%{version}/source/firefox-%{version}.source.tar.xz Source0: https://archive.mozilla.org/pub/firefox/releases/%{version}/source/firefox-%{version}.source.tar.xz
@ -153,6 +153,29 @@ Patch607: CVE-2020-15668.patch
Patch608: CVE-2020-15676.patch Patch608: CVE-2020-15676.patch
Patch609: CVE-2020-15677.patch Patch609: CVE-2020-15677.patch
Patch610: CVE-2020-15678.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} %if %{?system_nss}
BuildRequires: pkgconfig(nspr) >= %{nspr_version} pkgconfig(nss) >= %{nss_version} BuildRequires: pkgconfig(nspr) >= %{nspr_version} pkgconfig(nss) >= %{nss_version}
BuildRequires: nss-static >= %{nss_version} BuildRequires: nss-static >= %{nss_version}
@ -297,6 +320,28 @@ tar -xf %{SOURCE3}
%patch608 -p1 %patch608 -p1
%patch609 -p1 %patch609 -p1
%patch610 -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 %{__rm} -f .mozconfig
%{__cp} %{SOURCE10} .mozconfig %{__cp} %{SOURCE10} .mozconfig
echo "ac_add_options --enable-default-toolkit=cairo-gtk3-wayland" >> .mozconfig echo "ac_add_options --enable-default-toolkit=cairo-gtk3-wayland" >> .mozconfig
@ -738,6 +783,12 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
%endif %endif
%changelog %changelog
* Thu Jan 07 2021 wangxiao <wangxiao65@huawei.com> - 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 <wangxiao65@huawei.com> - 79.0-4 * Wed Dec 16 2020 wangxiao <wangxiao65@huawei.com> - 79.0-4
- Fix CVE-2020-15664 CVE-2020-15665 CVE-2020-15666 CVE-2020-15667 - 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 CVE-2020-15668 CVE-2020-15676 CVE-2020-15677 CVE-2020-15678