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:
ProxyBQP(const sp<IGraphicBufferProducer> & producer)30     ProxyBQP(const sp<IGraphicBufferProducer>& producer) : mProducer(producer) {}
31 
32     // Pass through calls to mProducer
requestBuffer(int slot,sp<GraphicBuffer> * buf)33     status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) override {
34         return mProducer->requestBuffer(slot, buf);
35     }
setMaxDequeuedBufferCount(int maxDequeuedBuffers)36     status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers) override {
37         return mProducer->setMaxDequeuedBufferCount(maxDequeuedBuffers);
38     }
setAsyncMode(bool async)39     status_t setAsyncMode(bool async) override { return mProducer->setAsyncMode(async); }
dequeueBuffer(int * slot,sp<Fence> * fence,uint32_t w,uint32_t h,PixelFormat format,uint32_t usage,FrameEventHistoryDelta * outTimestamps)40     status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w, uint32_t h, PixelFormat format,
41                            uint32_t usage, FrameEventHistoryDelta* outTimestamps) override {
42         return mProducer->dequeueBuffer(slot, fence, w, h, format, usage, outTimestamps);
43     }
detachBuffer(int slot)44     status_t detachBuffer(int slot) override { return mProducer->detachBuffer(slot); }
detachNextBuffer(sp<GraphicBuffer> * outBuffer,sp<Fence> * outFence)45     status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence) override {
46         return mProducer->detachNextBuffer(outBuffer, outFence);
47     }
attachBuffer(int * outSlot,const sp<GraphicBuffer> & buffer)48     status_t attachBuffer(int* outSlot, const sp<GraphicBuffer>& buffer) override {
49         return mProducer->attachBuffer(outSlot, buffer);
50     }
queueBuffer(int slot,const QueueBufferInput & input,QueueBufferOutput * output)51     status_t queueBuffer(int slot, const QueueBufferInput& input,
52                          QueueBufferOutput* output) override {
53         return mProducer->queueBuffer(slot, input, output);
54     }
cancelBuffer(int slot,const sp<Fence> & fence)55     status_t cancelBuffer(int slot, const sp<Fence>& fence) override {
56         return mProducer->cancelBuffer(slot, fence);
57     }
query(int what,int * value)58     int query(int what, int* value) override { return mProducer->query(what, value); }
connect(const sp<IProducerListener> & listener,int api,bool producerControlledByApp,QueueBufferOutput * output)59     status_t connect(const sp<IProducerListener>& listener, int api, bool producerControlledByApp,
60                      QueueBufferOutput* output) override {
61         return mProducer->connect(listener, api, producerControlledByApp, output);
62     }
disconnect(int api,DisconnectMode mode)63     status_t disconnect(int api, DisconnectMode mode) override {
64         return mProducer->disconnect(api, mode);
65     }
setSidebandStream(const sp<NativeHandle> & stream)66     status_t setSidebandStream(const sp<NativeHandle>& stream) override {
67         return mProducer->setSidebandStream(stream);
68     }
allocateBuffers(uint32_t width,uint32_t height,PixelFormat format,uint32_t usage)69     void allocateBuffers(uint32_t width, uint32_t height, PixelFormat format,
70                          uint32_t usage) override {
71         mProducer->allocateBuffers(width, height, format, usage);
72     }
allowAllocation(bool allow)73     status_t allowAllocation(bool allow) override { return mProducer->allowAllocation(allow); }
setGenerationNumber(uint32_t generationNumber)74     status_t setGenerationNumber(uint32_t generationNumber) override {
75         return mProducer->setGenerationNumber(generationNumber);
76     }
getConsumerName() const77     String8 getConsumerName() const override { return mProducer->getConsumerName(); }
setSharedBufferMode(bool sharedBufferMode)78     status_t setSharedBufferMode(bool sharedBufferMode) override {
79         return mProducer->setSharedBufferMode(sharedBufferMode);
80     }
setAutoRefresh(bool autoRefresh)81     status_t setAutoRefresh(bool autoRefresh) override {
82         return mProducer->setAutoRefresh(autoRefresh);
83     }
setDequeueTimeout(nsecs_t timeout)84     status_t setDequeueTimeout(nsecs_t timeout) override {
85         return mProducer->setDequeueTimeout(timeout);
86     }
getLastQueuedBuffer(sp<GraphicBuffer> * outBuffer,sp<Fence> * outFence,float outTransformMatrix[16])87     status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence,
88                                  float outTransformMatrix[16]) override {
89         return mProducer->getLastQueuedBuffer(outBuffer, outFence, outTransformMatrix);
90     }
getFrameTimestamps(FrameEventHistoryDelta *)91     void getFrameTimestamps(FrameEventHistoryDelta*) override {}
getUniqueId(uint64_t * outId) const92     status_t getUniqueId(uint64_t* outId) const override { return mProducer->getUniqueId(outId); }
93 
94 protected:
95     sp<IGraphicBufferProducer> mProducer;
96 };
97 
98 class MaliciousBQP : public ProxyBQP {
99 public:
MaliciousBQP(const sp<IGraphicBufferProducer> & producer)100     MaliciousBQP(const sp<IGraphicBufferProducer>& producer) : ProxyBQP(producer) {}
101 
beMalicious(int32_t value)102     void beMalicious(int32_t value) { mMaliciousValue = value; }
103 
setExpectedSlot(int32_t slot)104     void setExpectedSlot(int32_t slot) { mExpectedSlot = slot; }
105 
106     // Override dequeueBuffer, optionally corrupting the returned slot number
dequeueBuffer(int * buf,sp<Fence> * fence,uint32_t width,uint32_t height,PixelFormat format,uint32_t usage,FrameEventHistoryDelta * outTimestamps)107     status_t dequeueBuffer(int* buf, sp<Fence>* fence, uint32_t width, uint32_t height,
108                            PixelFormat format, uint32_t usage,
109                            FrameEventHistoryDelta* outTimestamps) override {
110         EXPECT_EQ(BUFFER_NEEDS_REALLOCATION,
111                   mProducer->dequeueBuffer(buf, fence, width, height, format, usage,
112                                            outTimestamps));
113         EXPECT_EQ(mExpectedSlot, *buf);
114         if (mMaliciousValue != 0) {
115             *buf = mMaliciousValue;
116             return NO_ERROR;
117         } else {
118             return BUFFER_NEEDS_REALLOCATION;
119         }
120     }
121 
122 private:
123     int32_t mMaliciousValue = 0;
124     int32_t mExpectedSlot = 0;
125 };
126 
127 class DummyListener : public BnConsumerListener {
128 public:
onFrameAvailable(const BufferItem &)129     void onFrameAvailable(const BufferItem&) override {}
onBuffersReleased()130     void onBuffersReleased() override {}
onSidebandStreamChanged()131     void onSidebandStreamChanged() override {}
132 };
133 
getMaliciousBQP()134 sp<MaliciousBQP> getMaliciousBQP() {
135     sp<IGraphicBufferProducer> producer;
136     sp<IGraphicBufferConsumer> consumer;
137     BufferQueue::createBufferQueue(&producer, &consumer);
138     sp<IConsumerListener> listener = new DummyListener;
139     consumer->consumerConnect(listener, false);
140 
141     sp<MaliciousBQP> malicious = new MaliciousBQP(producer);
142     return malicious;
143 }
144 
TEST(Malicious,Bug36991414Max)145 TEST(Malicious, Bug36991414Max) {
146     sp<MaliciousBQP> malicious = getMaliciousBQP();
147     sp<Surface> surface = new Surface(malicious);
148 
149     ASSERT_EQ(NO_ERROR, surface->connect(NATIVE_WINDOW_API_CPU, nullptr, false));
150     ANativeWindow_Buffer buffer;
151     ASSERT_EQ(NO_ERROR, surface->lock(&buffer, nullptr));
152     ASSERT_EQ(NO_ERROR, surface->unlockAndPost());
153 
154     malicious->setExpectedSlot(1);
155     malicious->beMalicious(std::numeric_limits<int32_t>::max());
156     ASSERT_EQ(FAILED_TRANSACTION, surface->lock(&buffer, nullptr));
157 }
158 
TEST(Malicious,Bug36991414Min)159 TEST(Malicious, Bug36991414Min) {
160     sp<MaliciousBQP> malicious = getMaliciousBQP();
161     sp<Surface> surface = new Surface(malicious);
162 
163     ASSERT_EQ(NO_ERROR, surface->connect(NATIVE_WINDOW_API_CPU, nullptr, false));
164     ANativeWindow_Buffer buffer;
165     ASSERT_EQ(NO_ERROR, surface->lock(&buffer, nullptr));
166     ASSERT_EQ(NO_ERROR, surface->unlockAndPost());
167 
168     malicious->setExpectedSlot(1);
169     malicious->beMalicious(std::numeric_limits<int32_t>::min());
170     ASSERT_EQ(FAILED_TRANSACTION, surface->lock(&buffer, nullptr));
171 }
172 
TEST(Malicious,Bug36991414NegativeOne)173 TEST(Malicious, Bug36991414NegativeOne) {
174     sp<MaliciousBQP> malicious = getMaliciousBQP();
175     sp<Surface> surface = new Surface(malicious);
176 
177     ASSERT_EQ(NO_ERROR, surface->connect(NATIVE_WINDOW_API_CPU, nullptr, false));
178     ANativeWindow_Buffer buffer;
179     ASSERT_EQ(NO_ERROR, surface->lock(&buffer, nullptr));
180     ASSERT_EQ(NO_ERROR, surface->unlockAndPost());
181 
182     malicious->setExpectedSlot(1);
183     malicious->beMalicious(-1);
184     ASSERT_EQ(FAILED_TRANSACTION, surface->lock(&buffer, nullptr));
185 }
186 
TEST(Malicious,Bug36991414NumSlots)187 TEST(Malicious, Bug36991414NumSlots) {
188     sp<MaliciousBQP> malicious = getMaliciousBQP();
189     sp<Surface> surface = new Surface(malicious);
190 
191     ASSERT_EQ(NO_ERROR, surface->connect(NATIVE_WINDOW_API_CPU, nullptr, false));
192     ANativeWindow_Buffer buffer;
193     ASSERT_EQ(NO_ERROR, surface->lock(&buffer, nullptr));
194     ASSERT_EQ(NO_ERROR, surface->unlockAndPost());
195 
196     malicious->setExpectedSlot(1);
197     malicious->beMalicious(BufferQueueDefs::NUM_BUFFER_SLOTS);
198     ASSERT_EQ(FAILED_TRANSACTION, surface->lock(&buffer, nullptr));
199 }
200 
201 } // namespace test
202 } // namespace android
203