Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <gui/BufferQueue.h>
     18 #include <gui/IProducerListener.h>
     19 #include <gui/Surface.h>
     20 
     21 #include <android/native_window.h>
     22 
     23 #include <gtest/gtest.h>
     24 
     25 namespace android {
     26 namespace test {
     27 
     28 class ProxyBQP : public BnGraphicBufferProducer {
     29 public:
     30     ProxyBQP(const sp<IGraphicBufferProducer>& producer) : mProducer(producer) {}
     31 
     32     // Pass through calls to mProducer
     33     status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) override {
     34         return mProducer->requestBuffer(slot, buf);
     35     }
     36     status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers) override {
     37         return mProducer->setMaxDequeuedBufferCount(maxDequeuedBuffers);
     38     }
     39     status_t setAsyncMode(bool async) override { return mProducer->setAsyncMode(async); }
     40     status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w, uint32_t h, PixelFormat format,
     41                            uint64_t usage, uint64_t* outBufferAge,
     42                            FrameEventHistoryDelta* outTimestamps) override {
     43         return mProducer->dequeueBuffer(slot, fence, w, h, format, usage, outBufferAge,
     44                                         outTimestamps);
     45     }
     46     status_t detachBuffer(int slot) override { return mProducer->detachBuffer(slot); }
     47     status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence) override {
     48         return mProducer->detachNextBuffer(outBuffer, outFence);
     49     }
     50     status_t attachBuffer(int* outSlot, const sp<GraphicBuffer>& buffer) override {
     51         return mProducer->attachBuffer(outSlot, buffer);
     52     }
     53     status_t queueBuffer(int slot, const QueueBufferInput& input,
     54                          QueueBufferOutput* output) override {
     55         return mProducer->queueBuffer(slot, input, output);
     56     }
     57     status_t cancelBuffer(int slot, const sp<Fence>& fence) override {
     58         return mProducer->cancelBuffer(slot, fence);
     59     }
     60     int query(int what, int* value) override { return mProducer->query(what, value); }
     61     status_t connect(const sp<IProducerListener>& listener, int api, bool producerControlledByApp,
     62                      QueueBufferOutput* output) override {
     63         return mProducer->connect(listener, api, producerControlledByApp, output);
     64     }
     65     status_t disconnect(int api, DisconnectMode mode) override {
     66         return mProducer->disconnect(api, mode);
     67     }
     68     status_t setSidebandStream(const sp<NativeHandle>& stream) override {
     69         return mProducer->setSidebandStream(stream);
     70     }
     71     void allocateBuffers(uint32_t width, uint32_t height, PixelFormat format,
     72                          uint64_t usage) override {
     73         mProducer->allocateBuffers(width, height, format, usage);
     74     }
     75     status_t allowAllocation(bool allow) override { return mProducer->allowAllocation(allow); }
     76     status_t setGenerationNumber(uint32_t generationNumber) override {
     77         return mProducer->setGenerationNumber(generationNumber);
     78     }
     79     String8 getConsumerName() const override { return mProducer->getConsumerName(); }
     80     status_t setSharedBufferMode(bool sharedBufferMode) override {
     81         return mProducer->setSharedBufferMode(sharedBufferMode);
     82     }
     83     status_t setAutoRefresh(bool autoRefresh) override {
     84         return mProducer->setAutoRefresh(autoRefresh);
     85     }
     86     status_t setDequeueTimeout(nsecs_t timeout) override {
     87         return mProducer->setDequeueTimeout(timeout);
     88     }
     89     status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence,
     90                                  float outTransformMatrix[16]) override {
     91         return mProducer->getLastQueuedBuffer(outBuffer, outFence, outTransformMatrix);
     92     }
     93     void getFrameTimestamps(FrameEventHistoryDelta*) override {}
     94     status_t getUniqueId(uint64_t* outId) const override { return mProducer->getUniqueId(outId); }
     95     status_t getConsumerUsage(uint64_t* outUsage) const override {
     96         return mProducer->getConsumerUsage(outUsage);
     97     }
     98 
     99 protected:
    100     sp<IGraphicBufferProducer> mProducer;
    101 };
    102 
    103 class MaliciousBQP : public ProxyBQP {
    104 public:
    105     MaliciousBQP(const sp<IGraphicBufferProducer>& producer) : ProxyBQP(producer) {}
    106 
    107     void beMalicious(int32_t value) { mMaliciousValue = value; }
    108 
    109     void setExpectedSlot(int32_t slot) { mExpectedSlot = slot; }
    110 
    111     // Override dequeueBuffer, optionally corrupting the returned slot number
    112     status_t dequeueBuffer(int* buf, sp<Fence>* fence, uint32_t width, uint32_t height,
    113                            PixelFormat format, uint64_t usage, uint64_t* outBufferAge,
    114                            FrameEventHistoryDelta* outTimestamps) override {
    115         EXPECT_EQ(BUFFER_NEEDS_REALLOCATION,
    116                   mProducer->dequeueBuffer(buf, fence, width, height, format, usage, outBufferAge,
    117                                            outTimestamps));
    118         EXPECT_EQ(mExpectedSlot, *buf);
    119         if (mMaliciousValue != 0) {
    120             *buf = mMaliciousValue;
    121             return NO_ERROR;
    122         } else {
    123             return BUFFER_NEEDS_REALLOCATION;
    124         }
    125     }
    126 
    127 private:
    128     int32_t mMaliciousValue = 0;
    129     int32_t mExpectedSlot = 0;
    130 };
    131 
    132 class DummyListener : public BnConsumerListener {
    133 public:
    134     void onFrameAvailable(const BufferItem&) override {}
    135     void onBuffersReleased() override {}
    136     void onSidebandStreamChanged() override {}
    137 };
    138 
    139 sp<MaliciousBQP> getMaliciousBQP() {
    140     sp<IGraphicBufferProducer> producer;
    141     sp<IGraphicBufferConsumer> consumer;
    142     BufferQueue::createBufferQueue(&producer, &consumer);
    143     sp<IConsumerListener> listener = new DummyListener;
    144     consumer->consumerConnect(listener, false);
    145 
    146     sp<MaliciousBQP> malicious = new MaliciousBQP(producer);
    147     return malicious;
    148 }
    149 
    150 TEST(Malicious, Bug36991414Max) {
    151     sp<MaliciousBQP> malicious = getMaliciousBQP();
    152     sp<Surface> surface = new Surface(malicious);
    153 
    154     ASSERT_EQ(NO_ERROR, surface->connect(NATIVE_WINDOW_API_CPU, nullptr, false));
    155     ANativeWindow_Buffer buffer;
    156     ASSERT_EQ(NO_ERROR, surface->lock(&buffer, nullptr));
    157     ASSERT_EQ(NO_ERROR, surface->unlockAndPost());
    158 
    159     malicious->setExpectedSlot(1);
    160     malicious->beMalicious(std::numeric_limits<int32_t>::max());
    161     ASSERT_EQ(FAILED_TRANSACTION, surface->lock(&buffer, nullptr));
    162 }
    163 
    164 TEST(Malicious, Bug36991414Min) {
    165     sp<MaliciousBQP> malicious = getMaliciousBQP();
    166     sp<Surface> surface = new Surface(malicious);
    167 
    168     ASSERT_EQ(NO_ERROR, surface->connect(NATIVE_WINDOW_API_CPU, nullptr, false));
    169     ANativeWindow_Buffer buffer;
    170     ASSERT_EQ(NO_ERROR, surface->lock(&buffer, nullptr));
    171     ASSERT_EQ(NO_ERROR, surface->unlockAndPost());
    172 
    173     malicious->setExpectedSlot(1);
    174     malicious->beMalicious(std::numeric_limits<int32_t>::min());
    175     ASSERT_EQ(FAILED_TRANSACTION, surface->lock(&buffer, nullptr));
    176 }
    177 
    178 TEST(Malicious, Bug36991414NegativeOne) {
    179     sp<MaliciousBQP> malicious = getMaliciousBQP();
    180     sp<Surface> surface = new Surface(malicious);
    181 
    182     ASSERT_EQ(NO_ERROR, surface->connect(NATIVE_WINDOW_API_CPU, nullptr, false));
    183     ANativeWindow_Buffer buffer;
    184     ASSERT_EQ(NO_ERROR, surface->lock(&buffer, nullptr));
    185     ASSERT_EQ(NO_ERROR, surface->unlockAndPost());
    186 
    187     malicious->setExpectedSlot(1);
    188     malicious->beMalicious(-1);
    189     ASSERT_EQ(FAILED_TRANSACTION, surface->lock(&buffer, nullptr));
    190 }
    191 
    192 TEST(Malicious, Bug36991414NumSlots) {
    193     sp<MaliciousBQP> malicious = getMaliciousBQP();
    194     sp<Surface> surface = new Surface(malicious);
    195 
    196     ASSERT_EQ(NO_ERROR, surface->connect(NATIVE_WINDOW_API_CPU, nullptr, false));
    197     ANativeWindow_Buffer buffer;
    198     ASSERT_EQ(NO_ERROR, surface->lock(&buffer, nullptr));
    199     ASSERT_EQ(NO_ERROR, surface->unlockAndPost());
    200 
    201     malicious->setExpectedSlot(1);
    202     malicious->beMalicious(BufferQueueDefs::NUM_BUFFER_SLOTS);
    203     ASSERT_EQ(FAILED_TRANSACTION, surface->lock(&buffer, nullptr));
    204 }
    205 
    206 } // namespace test
    207 } // namespace android
    208