Closed Bug 1742382 (CVE-2022-22738) Opened 3 years ago Closed 3 years ago

heap-buffer-overflow in blendGaussianBlur


(Core :: Graphics: WebRender, defect)




97 Branch
Tracking Status
firefox-esr91 96+ verified
firefox95 --- wontfix
firefox96 + verified
firefox97 + verified


(Reporter: attekett, Assigned: lsalzman)



(Keywords: csectype-bounds, reporter-external, sec-high, Whiteboard: [sec-survey][adv-main96+][adv-ESR91.5+])


(6 files)

Tested on:

OS: Ubuntu 20.04
Firefox version: $ fuzzfetch --target firefox --os Linux --asan --fuzzing -n firefox

          [2021-11-22 14:04:37] > Task ID: Lkjj4P35Rde9LyC3IRKhUQ
          [2021-11-22 14:04:37] > Rank: 1637573952
          [2021-11-22 14:04:37] > Changeset: ace2f4af2c29de1886e1e627d0fdb583e7573b59
          [2021-11-22 14:04:37] > Build ID: 20211122093912
          [2021-11-22 14:04:37] > Downloading:

Release Firefox 94.0 (64-bit) crashes with an MOZ_CRASH "called Option::unwrap() on a None value". Didn't set affected version since I didn't try with sanitizer build
Reported it as
Nightly Firefox crash report:

Repro-file as an attachment. If the issue doesn't reproduce, try increasing the number of insertions for the HTML chunk. For my laptop, 800 was enough to start crashing reliably, so I set it to 1000 for the repro-file.

47:  var count = 1000;

AddressSanitizer trace:

ATTENTION: default value of option mesa_glthread overridden by environment.
==1855133==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x7f887c952807 at pc 0x7f8920093b27 bp 0x7f88f7363c40 sp 0x7f88f7363c38
READ of size 16 at 0x7f887c952807 thread T13 (Renderer)
    #0 0x7f8920093b26 in load<unsigned int> /builds/worker/checkouts/gecko/gfx/wr/swgl/src/vector_type.h:503:5
    #1 0x7f8920093b26 in unaligned_load<unsigned int __attribute__((ext_vector_type(4))), unsigned int> /builds/worker/checkouts/gecko/gfx/wr/swgl/src/vector_type.h:532:10
    #2 0x7f8920093b26 in unsigned short vector[(4) * (sizeof (unsigned int))] glsl::gaussianBlurVertical<unsigned int, glsl::sampler2D_impl*>(glsl::sampler2D_impl*, glsl::ivec2_scalar const&, int, int, int, float, float) /builds/worker/checkouts/gecko/gfx/wr/swgl/src/texture.h:1110:24
    #3 0x7f892008533b in blendGaussianBlur<false, glsl::sampler2D_impl *, unsigned int> /builds/worker/checkouts/gecko/gfx/wr/swgl/src/swgl_ext.h:958:16
    #4 0x7f892008533b in cs_blur_COLOR_TARGET_frag::swgl_drawSpanRGBA8() /builds/worker/workspace/obj-build/x86_64-unknown-linux-gnu/release/build/swgl-7a39aed50e042c2c/out/cs_blur_COLOR_TARGET.h:635:2
    #5 0x7f892007fd19 in cs_blur_COLOR_TARGET_frag::draw_span_RGBA8(cs_blur_COLOR_TARGET_frag*) /builds/worker/workspace/obj-build/x86_64-unknown-linux-gnu/release/build/swgl-7a39aed50e042c2c/out/cs_blur_COLOR_TARGET.h:678:42
    #6 0x7f892018de16 in draw_span /builds/worker/checkouts/gecko/gfx/wr/swgl/src/program.h:168:12
    #7 0x7f892018de16 in void draw_quad_spans<unsigned int>(int, glsl::vec2_scalar*, unsigned int, glsl::vec3*, Texture&, Texture&, ClipRect const&) /builds/worker/checkouts/gecko/gfx/wr/swgl/src/rasterize.h:1028:42
    #8 0x7f891fc7c57e in draw_quad(int, Texture&, Texture&) /builds/worker/checkouts/gecko/gfx/wr/swgl/src/rasterize.h:1615:5
    #9 0x7f891fc7a09c in void draw_elements<unsigned short>(int, int, unsigned long, VertexArray&, Texture&, Texture&) /builds/worker/checkouts/gecko/gfx/wr/swgl/src/rasterize.h:1648:7
    #10 0x7f891fc79cd9 in DrawElementsInstanced /builds/worker/checkouts/gecko/gfx/wr/swgl/src/
    #11 0x7f891f7b69a0 in webrender::device::gl::Device::draw_indexed_triangles_instanced_u16::hf874f8a08646d2b7 /builds/worker/checkouts/gecko/gfx/wr/webrender/src/device/
    #12 0x7f891f7b69a0 in webrender::renderer::Renderer::draw_instanced_batch::ha606111b3f9e79d9 /builds/worker/checkouts/gecko/gfx/wr/webrender/src/renderer/
    #34 0x7f892dc52292 in clone /build/glibc-eX1tMB/glibc-2.31/misc/../sysdeps/unix/sysv/linux/x86_64/clone.S:95

0x7f887c952807 is located 7 bytes to the right of 16777216-byte region [0x7f887b952800,0x7f887c952800)
allocated by thread T13 (Renderer) here:
    #0 0x55e3f8fba683 in realloc /builds/worker/fetches/llvm-project/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cpp:148:3
    #1 0x7f891fc800a1 in Texture::allocate(bool, int, int) /builds/worker/checkouts/gecko/gfx/wr/swgl/src/
    #2 0x7f891fc65dcf in set_tex_storage(Texture&, unsigned int, int, int, void*, int, int, int) /builds/worker/checkouts/gecko/gfx/wr/swgl/src/
    #3 0x7f891fc6588e in TexStorage2D /builds/worker/checkouts/gecko/gfx/wr/swgl/src/
    #4 0x7f891fc66b69 in TexImage2D /builds/worker/checkouts/gecko/gfx/wr/swgl/src/
    #5 0x7f891fc49a9f in _$LT$swgl..swgl_fns..Context$u20$as$u20$$GT$::tex_image_2d::h40885d72a076c3fe /builds/worker/checkouts/gecko/gfx/wr/swgl/src/
    #6 0x7f891f578213 in webrender::device::gl::Device::create_texture::h309962d0f1ae9501 /builds/worker/checkouts/gecko/gfx/wr/webrender/src/device/
    #7 0x7f891f78c743 in webrender::renderer::Renderer::update_texture_cache::_$u7b$$u7b$closure$u7d$$u7d$::h37693bd23f49b62b /builds/worker/checkouts/gecko/gfx/wr/webrender/src/renderer/
    #8 0x7f891f78c743 in core::option::Option$LT$T$GT$::unwrap_or_else::h846cfa865feb4642 /builds/worker/fetches/rust/library/core/src/
    #26 0x7f892cf8409e in _pt_root /builds/worker/checkouts/gecko/nsprpub/pr/src/pthreads/ptthread.c:201:5
    #27 0x7f892e08a608 in start_thread /build/glibc-eX1tMB/glibc-2.31/nptl/pthread_create.c:477:8

Thread T13 (Renderer) created by T0 (GeckoMain) here:
    #0 0x55e3f8fa4a8c in pthread_create /builds/worker/fetches/llvm-project/llvm/projects/compiler-rt/lib/asan/asan_interceptors.cpp:207:3
    #1 0x7f892cf74124 in _PR_CreateThread /builds/worker/checkouts/gecko/nsprpub/pr/src/pthreads/ptthread.c:458:14
    #2 0x7f892cf653ce in PR_CreateThread /builds/worker/checkouts/gecko/nsprpub/pr/src/pthreads/ptthread.c:533:12
    #3 0x7f890f8436d5 in nsThread::Init(nsTSubstring<char> const&) /builds/worker/checkouts/gecko/xpcom/threads/nsThread.cpp:615:18
    #4 0x7f890f85091f in nsThreadManager::NewNamedThread(nsTSubstring<char> const&, unsigned int, nsIThread**) /builds/worker/checkouts/gecko/xpcom/threads/nsThreadManager.cpp:581:12
    #5 0x7f890f85bae1 in NS_NewNamedThread(nsTSubstring<char> const&, nsIThread**, already_AddRefed<nsIRunnable>, unsigned int) /builds/worker/checkouts/gecko/xpcom/threads/nsThreadUtils.cpp:163:57
    #6 0x7f89129416d1 in NS_NewNamedThread<9UL> /builds/worker/workspace/obj-build/dist/include/nsThreadUtils.h:74:10
    #7 0x7f89129416d1 in mozilla::wr::RenderThread::Start() /builds/worker/checkouts/gecko/gfx/webrender_bindings/RenderThread.cpp:92:17
    #8 0x7f89126e1b0e in InitLayersIPC /builds/worker/checkouts/gecko/gfx/thebes/gfxPlatform.cpp:1291:7
    #50 0x55e3f8fef6d9 in main /builds/worker/checkouts/gecko/browser/app/nsBrowserApp.cpp:395:16
    #51 0x7f892db570b2 in __libc_start_main /build/glibc-eX1tMB/glibc-2.31/csu/../csu/libc-start.c:308:16

SUMMARY: AddressSanitizer: heap-buffer-overflow /builds/worker/checkouts/gecko/gfx/wr/swgl/src/vector_type.h:503:5 in load<unsigned int>
Exiting due to channel error.
Exiting due to channel error.
Exiting due to channel error.
Exiting due to channel error.
Group: firefox-core-security → gfx-core-security
Component: General → Graphics: WebRender
Product: Firefox → Core

Lee, is this something you could look into? It looks like you've worked on blendGaussianBlur before. Thanks.

Flags: needinfo?(lsalzman)

I can't get the testcase to reproduce at all. I did the fuzzfetch and tried to run the testcase, but nothing triggered. I tried adding asserts as well, nothing triggers.

Flags: needinfo?(lsalzman)

Same here. I'm unable to reproduce this using Ubuntu 20.04 on m-c rev ace2f4af2c29 using either a build with --enable-address-sanitizer or --enable-debug. Atte, is there anything specific about your setup our how you're launching the testcase that might help us reproduce this issue? Any special prefs enabled?

Nothing special. I have a Windows 10 host and a VMware VM, with Ubuntu 20.04.

I just reproduced the issue with following steps that should be reproducible to you too, I didn't use prefpicker and ffpuppet previously, because those weren't needed, but that should verify that there is no prefs from my system enabled.

$ prefpicker browser-fuzzing.yml prefs.js
Loading 'browser-fuzzing.yml'...
Loaded 185 prefs and 5 variants
Generating 'prefs.js' using variant 'default'...
$ fuzzfetch --target firefox --os Linux --asan --fuzzing -n firefox2
[2021-11-22 22:15:51] Identified task:
[2021-11-22 22:15:51] > Task ID: L0jMwv3tT-eaGKY4HpE3xw
[2021-11-22 22:15:51] > Rank: 1637595800
[2021-11-22 22:15:51] > Changeset: d8a16efe2d2c394e8695b300a721f41ff6f64539
[2021-11-22 22:15:51] > Build ID: 20211122154320
[2021-11-22 22:15:53] > Downloading: (380.41MiB total)
[2021-11-22 22:16:08] .. downloaded (25.20MB/s)
[2021-11-22 22:16:08] .. extracting
[2021-11-22 22:17:43] Extracted into /home/attekett/firefox2
$ ffpuppet ./firefox2/firefox -p ./prefs.js -u ./heap-buffer-overflow-blendGaussianBlur.html -d 2>&1 | grep SUMMARY
SUMMARY: AddressSanitizer: heap-buffer-overflow /builds/worker/checkouts/gecko/gfx/wr/swgl/src/vector_type.h:503:5 in load<unsigned int>

On my fuzzing cluster the issue was caught in a Docker container running firefox in Xvfb launched by ffpuppet.

My fuzzer uses an html that loads test case to iframe. I originally had some trouble reproducing without loading the file first to an iframe like this.

      var iframe = document.body.appendChild(document.createElement("iframe")); = 1223; = 967;
      iframe.src = "./heap-buffer-overflow-blendGaussianBlur.html"

The iframe width and height were affecting reproducing the issue with the original repro, that was hitting OOM very often. I thought I solved that issue with the minimized repro, but it may be that my system just has the right resolution for it. I have 3840x2160 resolution with 200% scale set from Ubuntu settings.

Other than that, I have no idea what could affect it.

I managed to reproduce this on one machine (Ubuntu Desktop 20.04) but not two other machines (Ubuntu Desktop 20.04 and 18.04).

I was not able to reproduce with Xvfb. I needed to change count = 1000 in the test case to count = 2000 . I believe there are a few reasons for this not reproducing. First is the prefs.js file. PrefPicker can generate a different file each time it is called. I will attached the prefs.js I used (forced SW-WR). Second is screen resolution.

Atte could you please attach a test case that you can consistently reproduce when using Xvfb? This should help by removing some differences from our environments.

Flags: needinfo?(attekett)
Attached file prefs.js

A Pernosco session is available here:

Flags: needinfo?(lsalzman)

I'll take a look if some of the reduced cases reproduce reliably on Xvfb. The original repro wasn't reliable and it is too large to be useful, ~1.5MB of HTML+CSS.

Flags: needinfo?(attekett)

Tyson, can you try with this file. It is over 1MB, but at least on my system reproduces clearly on xvfb and the prefs.js you attached.

$ ffpuppet ../firefox2/firefox -p ./tyson_prefs.js -u ./heap-buffer-overflow-loadunsigned-unalignedloadunsigned-unsigned-blendGaussianBlurfalse0-min.html -d --xvfb 2>&1 | grep SUMMARY
SUMMARY: AddressSanitizer: heap-buffer-overflow /builds/worker/checkouts/gecko/gfx/wr/swgl/src/vector_type.h:503:5 in load<unsigned int>
Flags: needinfo?(twsmith)
Blocks: gfx-triage

Calling this sec-high for now because of the bounds condition. Not sure if the read offset is controllable, and might downgrade to moderate if we can't make a more reliable (across different machines) testcase.

Keywords: sec-high
Flags: needinfo?(lsalzman)
Assignee: nobody → lsalzman

Tyson, I haven't been able to reproduce this bug locally at all. But I made a patch that should fix what I saw in the Pernosco session. If you can repro, can you apply my patch and verify that if fixes this, please?

Did you try with Tyson's prefs.js, ffpuppet, xvfb and the large repro? That was reliable repro for my VM, if that doesn't work for others, I can make a temporary Ubuntu Desktop install to one of my testing machines to see if I can refine the repro.

I am happy to verify the patch with the testcase that is available. I have one machine that I can repro consistently on :)

Tyson, can you also check if the second test case reproduces on your other systems? I'm sure the test case can be modified to reproduce on other systems, and it would be a shame to have the severity lowered because of that.

No longer blocks: gfx-triage

Lee, I cannot reproduce the issue with the patch applied. Thanks!

Atte, Yes I can reproduce the issue reliably with the second test case when using Xvfb. Thank you for attaching it.

Flags: needinfo?(twsmith)

Comment on attachment 9253487 [details]
Bug 1742382 - Clamp bounds to sampler. r?jrmuizel

Security Approval Request

  • How easily could an exploit be constructed based on the patch?: Not easily. Seems hard to nail down specific test scenario.
  • Do comments in the patch, the check-in comment, or tests included in the patch paint a bulls-eye on the security problem?: Unknown
  • Which older supported branches are affected by this flaw?: 91+
  • If not all supported branches, which bug introduced the flaw?: None
  • Do you have backports for the affected branches?: Yes
  • If not, how different, hard to create, and risky will they be?:
  • How likely is this patch to cause regressions; how much testing does it need?: Unlikely, just adds a single bounds check.
Attachment #9253487 - Flags: sec-approval?

The severity field is not set for this bug.
:jimm, could you have a look please?

For more information, please visit auto_nag documentation.

Flags: needinfo?(jmathies)
Severity: -- → S3
Flags: needinfo?(jmathies)
Flags: sec-bounty?

Comment on attachment 9253487 [details]
Bug 1742382 - Clamp bounds to sampler. r?jrmuizel

Approved to land and uplift

Attachment #9253487 - Flags: sec-approval?
Attachment #9253487 - Flags: sec-approval+
Attachment #9253487 - Flags: approval-mozilla-esr91+
Attachment #9253487 - Flags: approval-mozilla-beta+
Group: gfx-core-security → core-security-release
Closed: 3 years ago
Resolution: --- → FIXED
Target Milestone: --- → 97 Branch

As part of a security bug pattern analysis, we are requesting your help with a high level analysis of this bug. It is our hope to develop static analysis (or potentially runtime/dynamic analysis) in the future to identify classes of bugs.

Please visit this google form to reply.

Flags: needinfo?(lsalzman)
Whiteboard: [sec-survey]
Flags: needinfo?(lsalzman)
Attachment #9252055 - Attachment mime type: application/octet-stream → text/html
Flags: sec-bounty? → sec-bounty+
Depends on: 1746062
QA Whiteboard: [post-critsmash-triage]
Flags: qe-verify+
Attached file crash.txt

Hello! We reproduced the crash using the build from comment 4 on Ubuntu 18.04 and the attached prefs.js by opening the second test case. The build was opened by terminal with prefs.js placed inside the profile folder. We could not reproduce the issue on Ubuntu 20.04.

Firefox is no longer crashing with the latest Nightly asan build but sometimes I still got a crash when opening the second test case on 96.0b11 (20220102190138) and 91.5.0esr (20211221141432). Attached the log. Also if Firefox does not crash when loading the test case a hang is presented. Are these behaviors expected? Thank you in advance.

Flags: needinfo?(lsalzman)

If you look at the crash log, it is no longer hitting the overflow anymore. It's just triggering an assertion in the rust code because of a different reason.

Flags: needinfo?(lsalzman)

(In reply to Lee Salzman [:lsalzman] from comment #26)

If you look at the crash log, it is no longer hitting the overflow anymore. It's just triggering an assertion in the rust code because of a different reason.

Thank you! Closing this because it seems that this issue is fixed per the above comments. Maybe the remaining crash has to do with bug 1746062 since the crash does not occur on Nightly.

Flags: qe-verify+
Whiteboard: [sec-survey] → [sec-survey][adv-main96+][adv-ESR91.5+]
Attached file advisory.txt
Alias: CVE-2022-22738
Group: core-security-release
You need to log in before you can comment on or make changes to this bug.