New issue
Advanced search Search tips

Issue 887244 link

Starred by 1 user

Issue metadata

Status: WontFix
Owner: ----
Closed: Sep 22
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Linux , Android , Windows , Chrome , Mac
Pri: 1
Type: Bug-Security



Sign in to add a comment

Security: Out-Of-Bounds Read Vulnerability in Skia.

Reported by quangn...@gmail.com, Sep 20

Issue description

VULNERABILITY 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 ()
```
 
A similar vulnerability is located at SkPipeInflator::getFactory. 

https://cs.chromium.org/chromium/src/third_party/skia/src/pipe/SkPipeReader.cpp?g=0&l=51

You also can use the PoC to test reproduce this case.

Patch for this case:
```
diff --git a/src/pipe/SkPipeReader.cpp b/src/pipe/SkPipeReader.cpp
index 78db581..f416a76 100644
--- a/src/pipe/SkPipeReader.cpp
+++ b/src/pipe/SkPipeReader.cpp
@@ -45,9 +45,13 @@ public:
         return fTypefaces->get(index - 1);
     }
     SkFlattenable::Factory getFactory(int index) override {
+        if (index < 1 || index > fFactories->count())
+            return nullptr;
         return index ? fFactories->getAt(index - 1) : nullptr;
     }
```
Components: Internals>Skia
Labels: Security_Severity-Medium Security_Impact-Stable OS-Android OS-Chrome OS-Linux OS-Mac OS-Windows
Owner: reed@chromium.org
Status: Assigned (was: Unconfirmed)
reed: would you mind taking a look at this when you have time or reassigning to a good owner?
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;
 };
```

SkPipeReader_SkPipeInflator_getPicture_oob
288 bytes View Download
SkPipeReader_SkPipeInflator_getImage_invalid_index
584 bytes View Download
SkPipeInflator_getTypeface_oob_2
236 bytes View Download
Project Member

Comment 4 by sheriffbot@chromium.org, Sep 21

Labels: Target-70 M-70
Project Member

Comment 5 by sheriffbot@chromium.org, Sep 21

Labels: Pri-1
Cc: kjlubick@chromium.org hcm@google.com mtklein@chromium.org reed@google.com
Labels: Security_Impact-None
Owner: ----
Status: Available (was: Assigned)
Bulk edit of recently filed skia pipe bugs.
Status: WontFix (was: Available)
See https://bugs.chromium.org/p/chromium/issues/detail?id=886713#c8
Project Member

Comment 8 by sheriffbot@chromium.org, Dec 29

Labels: -Restrict-View-SecurityTeam allpublic
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