Security: Out-Of-Bounds Read Vulnerability in Skia.
Reported by
quangn...@gmail.com,
Sep 20
|
|||||||
Issue descriptionVULNERABILITY DETAILS I have found a vulnerability in SkPipeInflator::getTypeface. The attached poc can crash skia. Check the following line: https://cs.chromium.org/chromium/src/third_party/skia/src/pipe/SkPipeReader.cpp?g=0&l=48 ``` SkTypeface* getTypeface(int index) override { return fTypefaces->get(index - 1); } ``` In `getTypeface` method, developer doesnot check the `index` parameter and compare with capacity of `fTypefaces`. This mistake leads to access out-of-bounds by using index. Notice that, in Release build configuration, `SkASSERT` is disabled. VERSION Operating System: Linux REPRODUCTION CASE Build Skia with asserts disabled ``` bin/gn gen out/Release --args='is_debug=false' ninja -C out/Release ``` Run testcase: ``` ./out/Release/fuzz -t pipe -b SkPipeInflator_getTypeface_oob ``` Crate state: ``` #0 0x0000000000c1ad73 in std::__atomic_base<int>::fetch_add (__m=std::memory_order_relaxed, __i=0x1, this=0x7034745349656477) at /usr/include/c++/5/bits/atomic_base.h:514 #1 SkRefCntBase::ref (this=0x703474534965646f) at ../../include/core/SkRefCnt.h:76 #2 0x0000000000df04f7 in SkSafeRef<SkTypeface> (obj=0x703474534965646f) at ../../include/core/SkRefCnt.h:153 #3 0x0000000000defc18 in sk_ref_sp<SkTypeface> (obj=0x703474534965646f) at ../../include/core/SkRefCnt.h:416 #4 0x0000000000deef8b in SkReadBuffer::readTypeface (this=0x7fffffffcc20) at ../../src/core/SkReadBuffer.cpp:367 #5 0x0000000000e5aa85 in read_paint (reader=...) at ../../src/pipe/SkPipeReader.cpp:179 #6 0x0000000000e5be01 in drawPaint_handler (reader=..., packedVerb=0x12e61014, canvas=0x25f15c0) at ../../src/pipe/SkPipeReader.cpp:421 #7 0x0000000000e5dc83 in do_playback (reader=..., canvas=0x25f15c0, endPictureIndex=0x7fffffffcaf8) at ../../src/pipe/SkPipeReader.cpp:862 #8 0x0000000000e5d35a in definePicture_handler (reader=..., packedVerb=0x23000000, canvas=0x0) at ../../src/pipe/SkPipeReader.cpp:686 #9 0x0000000000e5da33 in SkPipeDeserializer::readPicture (this=0x7fffffffcd70, data=0x7ffff7ff6000, size=0x18c) at ../../src/pipe/SkPipeReader.cpp:818 #10 0x0000000000c34e4b in SkPipeDeserializer::readPicture (this=0x7fffffffcd70, data=0x25f0a10) at ../../src/core/SkPipe.h:63 #11 0x0000000000c38251 in fuzz_skpipe (bytes=...) at ../../fuzz/FuzzMain.cpp:614 #12 0x0000000000c35df6 in fuzz_file (path=..., type=...) at ../../fuzz/FuzzMain.cpp:189 #13 0x0000000000c35966 in main (argc=0x3, argv=0x7fffffffe198) at ../../fuzz/FuzzMain.cpp:109 #14 0x00007ffff6061830 in __libc_start_main (main=0xc35835 <main(int, char**)>, argc=0x3, argv=0x7fffffffe198, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffe188) at ../csu/libc-start.c:291 #15 0x0000000000c1a519 in _start () ```
,
Sep 20
reed: would you mind taking a look at this when you have time or reassigning to a good owner?
,
Sep 21
Notice that, `SkASSERT` is always disabled in Release configuration. I have found many similar vulnerabilities in SkPipeInflator class. Developer doesn't validate `index` before using it. Let's check them: https://cs.chromium.org/chromium/src/third_party/skia/src/pipe/SkPipeReader.cpp?g=0&l=41 ``` SkImage* getImage(int index) override { return index ? fImages->get(index - 1) : nullptr; } SkPicture* getPicture(int index) override { return index ? fPictures->get(index - 1) : nullptr; } SkTypeface* getTypeface(int index) override { return fTypefaces->get(index - 1); } SkFlattenable::Factory getFactory(int index) override { return index ? fFactories->getAt(index - 1) : nullptr; } bool setImage(int index, sk_sp<SkImage> img) { return fImages->set(index - 1, std::move(img)); } bool setPicture(int index, sk_sp<SkPicture> pic) { return fPictures->set(index - 1, std::move(pic)); } bool setTypeface(int index, sk_sp<SkTypeface> face) { return fTypefaces->set(index - 1, std::move(face)); } ``` There is a patch for this issue. I also include a patch from https://bugs.chromium.org/p/chromium/issues/detail?id=887196: ``` diff --git a/src/pipe/SkPipeReader.cpp b/src/pipe/SkPipeReader.cpp index 78db581..a2d523c 100644 --- a/src/pipe/SkPipeReader.cpp +++ b/src/pipe/SkPipeReader.cpp @@ -39,25 +39,39 @@ public: {} SkImage* getImage(int index) override { + if (index < 1 || (size_t)index > fImages->size()) + return nullptr; return index ? fImages->get(index - 1) : nullptr; } SkPicture* getPicture(int index) override { + if (index < 1 || (size_t)index > fPictures->size()) + return nullptr; return index ? fPictures->get(index - 1) : nullptr; } SkTypeface* getTypeface(int index) override { + if (index < 1 || (size_t)index > fTypefaces->size()) + return nullptr; return fTypefaces->get(index - 1); } SkFlattenable::Factory getFactory(int index) override { + if (index < 1 || (size_t)index > fFactories->size()) + return nullptr; return index ? fFactories->getAt(index - 1) : nullptr; } bool setImage(int index, sk_sp<SkImage> img) { + if (index < 1 || (size_t)index > fImages->size()) + return false; return fImages->set(index - 1, std::move(img)); } bool setPicture(int index, sk_sp<SkPicture> pic) { + if (index < 1 || (size_t)index > fPictures->size()) + return false; return fPictures->set(index - 1, std::move(pic)); } bool setTypeface(int index, sk_sp<SkTypeface> face) { + if (index < 1 || (size_t)index > fTypefaces->size()) + return false; return fTypefaces->set(index - 1, std::move(face)); } bool setFactory(int index, SkFlattenable::Factory factory) { @@ -683,7 +697,9 @@ static void definePicture_handler(SkPipeReader& reader, uint32_t packedVerb, SkC if (!cull) { return; } - do_playback(reader, recorder.beginRecording(*cull), &pictureIndex); + if (!do_playback(reader, recorder.beginRecording(*cull), &pictureIndex)) { + return; + } SkASSERT(pictureIndex > 0); sk_sp<SkPicture> picture = recorder.finishRecordingAsPicture(); inflator->setPicture(pictureIndex, std::move(picture)); diff --git a/src/pipe/SkRefSet.h b/src/pipe/SkRefSet.h index e556196..522283d 100644 --- a/src/pipe/SkRefSet.h +++ b/src/pipe/SkRefSet.h @@ -31,6 +31,8 @@ public: return false; } + size_t size() { return (size_t)fArray.count();} + private: SkTArray<sk_sp<T>> fArray; }; ```
,
Sep 21
,
Sep 21
,
Sep 21
Bulk edit of recently filed skia pipe bugs.
,
Sep 22
See https://bugs.chromium.org/p/chromium/issues/detail?id=886713#c8
,
Dec 29
This bug has been closed for more than 14 weeks. Removing security view restrictions. For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot |
|||||||
►
Sign in to add a comment |
|||||||
Comment 1 by quangn...@gmail.com
, Sep 20