1 #include <algorithm>
2 #include <functional>
3 #include <limits>
4 #include <ostream>
5 
6 #include <gtest/gtest.h>
7 
8 #include <gui/ISurfaceComposer.h>
9 #include <gui/LayerDebugInfo.h>
10 #include <gui/Surface.h>
11 #include <gui/SurfaceComposerClient.h>
12 
13 #include <private/android_filesystem_config.h>
14 #include <private/gui/ComposerService.h>
15 #include <ui/DisplayInfo.h>
16 #include <utils/String8.h>
17 
18 namespace android {
19 
20 using Transaction = SurfaceComposerClient::Transaction;
21 using ui::ColorMode;
22 
23 namespace {
24 const String8 DISPLAY_NAME("Credentials Display Test");
25 const String8 SURFACE_NAME("Test Surface Name");
26 const uint32_t ROTATION = 0;
27 const float FRAME_SCALE = 1.0f;
28 } // namespace
29 
30 /**
31  * This class tests the CheckCredentials method in SurfaceFlinger.
32  * Methods like EnableVsyncInjections and InjectVsync are not tested since they do not
33  * return anything meaningful.
34  */
35 class CredentialsTest : public ::testing::Test {
36 protected:
SetUp()37     void SetUp() override {
38         // Start the tests as root.
39         seteuid(AID_ROOT);
40 
41         ASSERT_NO_FATAL_FAILURE(initClient());
42     }
43 
TearDown()44     void TearDown() override {
45         mComposerClient->dispose();
46         mBGSurfaceControl.clear();
47         mComposerClient.clear();
48         // Finish the tests as root.
49         seteuid(AID_ROOT);
50     }
51 
52     sp<IBinder> mDisplay;
53     sp<IBinder> mVirtualDisplay;
54     sp<SurfaceComposerClient> mComposerClient;
55     sp<SurfaceControl> mBGSurfaceControl;
56     sp<SurfaceControl> mVirtualSurfaceControl;
57 
initClient()58     void initClient() {
59         mComposerClient = new SurfaceComposerClient;
60         ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
61     }
62 
setupBackgroundSurface()63     void setupBackgroundSurface() {
64         mDisplay = SurfaceComposerClient::getInternalDisplayToken();
65         ASSERT_FALSE(mDisplay == nullptr);
66 
67         DisplayInfo info;
68         ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayInfo(mDisplay, &info));
69         const ssize_t displayWidth = info.w;
70         const ssize_t displayHeight = info.h;
71 
72         // Background surface
73         mBGSurfaceControl =
74                 mComposerClient->createSurface(SURFACE_NAME, displayWidth, displayHeight,
75                                                PIXEL_FORMAT_RGBA_8888, 0);
76         ASSERT_TRUE(mBGSurfaceControl != nullptr);
77         ASSERT_TRUE(mBGSurfaceControl->isValid());
78 
79         Transaction t;
80         t.setDisplayLayerStack(mDisplay, 0);
81         ASSERT_EQ(NO_ERROR,
82                   t.setLayer(mBGSurfaceControl, INT_MAX - 3).show(mBGSurfaceControl).apply());
83     }
84 
setupVirtualDisplay()85     void setupVirtualDisplay() {
86         mVirtualDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, true);
87         const ssize_t displayWidth = 100;
88         const ssize_t displayHeight = 100;
89 
90         // Background surface
91         mVirtualSurfaceControl =
92                 mComposerClient->createSurface(SURFACE_NAME, displayWidth, displayHeight,
93                                                PIXEL_FORMAT_RGBA_8888, 0);
94         ASSERT_TRUE(mVirtualSurfaceControl != nullptr);
95         ASSERT_TRUE(mVirtualSurfaceControl->isValid());
96 
97         Transaction t;
98         t.setDisplayLayerStack(mVirtualDisplay, 0);
99         ASSERT_EQ(NO_ERROR,
100                   t.setLayer(mVirtualSurfaceControl, INT_MAX - 3)
101                           .show(mVirtualSurfaceControl)
102                           .apply());
103     }
104 
105     /**
106      * Sets UID to imitate Graphic's process.
107      */
setGraphicsUID()108     void setGraphicsUID() {
109         seteuid(AID_ROOT);
110         seteuid(AID_GRAPHICS);
111     }
112 
113     /**
114      * Sets UID to imitate System's process.
115      */
setSystemUID()116     void setSystemUID() {
117         seteuid(AID_ROOT);
118         seteuid(AID_SYSTEM);
119     }
120 
121     /**
122      * Sets UID to imitate a process that doesn't have any special privileges in
123      * our code.
124      */
setBinUID()125     void setBinUID() {
126         seteuid(AID_ROOT);
127         seteuid(AID_BIN);
128     }
129 
130     /**
131      * Template function the check a condition for different types of users: root
132      * graphics, system, and non-supported user. Root, graphics, and system should
133      * always equal privilegedValue, and non-supported user should equal unprivilegedValue.
134      */
135     template <typename T>
checkWithPrivileges(std::function<T ()> condition,T privilegedValue,T unprivilegedValue)136     void checkWithPrivileges(std::function<T()> condition, T privilegedValue, T unprivilegedValue) {
137         // Check with root.
138         seteuid(AID_ROOT);
139         ASSERT_EQ(privilegedValue, condition());
140 
141         // Check as a Graphics user.
142         setGraphicsUID();
143         ASSERT_EQ(privilegedValue, condition());
144 
145         // Check as a system user.
146         setSystemUID();
147         ASSERT_EQ(privilegedValue, condition());
148 
149         // Check as a non-supported user.
150         setBinUID();
151         ASSERT_EQ(unprivilegedValue, condition());
152     }
153 };
154 
TEST_F(CredentialsTest,ClientInitTest)155 TEST_F(CredentialsTest, ClientInitTest) {
156     // Root can init can init the client.
157     ASSERT_NO_FATAL_FAILURE(initClient());
158 
159     // Graphics can init the client.
160     setGraphicsUID();
161     ASSERT_NO_FATAL_FAILURE(initClient());
162 
163     // System can init the client.
164     setSystemUID();
165     ASSERT_NO_FATAL_FAILURE(initClient());
166 
167     // Anyone else can init the client.
168     setBinUID();
169     mComposerClient = new SurfaceComposerClient;
170     ASSERT_NO_FATAL_FAILURE(initClient());
171 }
172 
TEST_F(CredentialsTest,GetBuiltInDisplayAccessTest)173 TEST_F(CredentialsTest, GetBuiltInDisplayAccessTest) {
174     std::function<bool()> condition = [] {
175         return SurfaceComposerClient::getInternalDisplayToken() != nullptr;
176     };
177     // Anyone can access display information.
178     ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, true));
179 }
180 
TEST_F(CredentialsTest,AllowedGetterMethodsTest)181 TEST_F(CredentialsTest, AllowedGetterMethodsTest) {
182     // The following methods are tested with a UID that is not root, graphics,
183     // or system, to show that anyone can access them.
184     setBinUID();
185     const auto display = SurfaceComposerClient::getInternalDisplayToken();
186     ASSERT_TRUE(display != nullptr);
187 
188     DisplayInfo info;
189     ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayInfo(display, &info));
190 
191     Vector<DisplayInfo> configs;
192     ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayConfigs(display, &configs));
193 
194     ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveConfig(display));
195 
196     ASSERT_NE(static_cast<ui::ColorMode>(BAD_VALUE),
197               SurfaceComposerClient::getActiveColorMode(display));
198 }
199 
TEST_F(CredentialsTest,GetDisplayColorModesTest)200 TEST_F(CredentialsTest, GetDisplayColorModesTest) {
201     const auto display = SurfaceComposerClient::getInternalDisplayToken();
202     std::function<status_t()> condition = [=]() {
203         Vector<ui::ColorMode> outColorModes;
204         return SurfaceComposerClient::getDisplayColorModes(display, &outColorModes);
205     };
206     ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, NO_ERROR));
207 }
208 
TEST_F(CredentialsTest,GetDisplayNativePrimariesTest)209 TEST_F(CredentialsTest, GetDisplayNativePrimariesTest) {
210     const auto display = SurfaceComposerClient::getInternalDisplayToken();
211     std::function<status_t()> condition = [=]() {
212         ui::DisplayPrimaries primaries;
213         return SurfaceComposerClient::getDisplayNativePrimaries(display, primaries);
214     };
215     ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, NO_ERROR));
216 }
217 
TEST_F(CredentialsTest,SetActiveConfigTest)218 TEST_F(CredentialsTest, SetActiveConfigTest) {
219     const auto display = SurfaceComposerClient::getInternalDisplayToken();
220     std::function<status_t()> condition = [=]() {
221         return SurfaceComposerClient::setActiveConfig(display, 0);
222     };
223     ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
224 }
225 
TEST_F(CredentialsTest,SetActiveColorModeTest)226 TEST_F(CredentialsTest, SetActiveColorModeTest) {
227     const auto display = SurfaceComposerClient::getInternalDisplayToken();
228     std::function<status_t()> condition = [=]() {
229         return SurfaceComposerClient::setActiveColorMode(display, ui::ColorMode::NATIVE);
230     };
231     ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
232 }
233 
TEST_F(CredentialsTest,CreateDisplayTest)234 TEST_F(CredentialsTest, CreateDisplayTest) {
235     std::function<bool()> condition = [=]() {
236         sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, true);
237         return testDisplay.get() != nullptr;
238     };
239     ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, false));
240 
241     condition = [=]() {
242         sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, false);
243         return testDisplay.get() != nullptr;
244     };
245     ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, false));
246 }
247 
TEST_F(CredentialsTest,DISABLED_DestroyDisplayTest)248 TEST_F(CredentialsTest, DISABLED_DestroyDisplayTest) {
249     setupVirtualDisplay();
250 
251     DisplayInfo info;
252     ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayInfo(mVirtualDisplay, &info));
253     SurfaceComposerClient::destroyDisplay(mVirtualDisplay);
254     // This test currently fails. TODO(b/112002626): Find a way to properly create
255     // a display in the test environment, so that destroy display can remove it.
256     ASSERT_EQ(NAME_NOT_FOUND, SurfaceComposerClient::getDisplayInfo(mVirtualDisplay, &info));
257 }
258 
TEST_F(CredentialsTest,CaptureTest)259 TEST_F(CredentialsTest, CaptureTest) {
260     const auto display = SurfaceComposerClient::getInternalDisplayToken();
261     std::function<status_t()> condition = [=]() {
262         sp<GraphicBuffer> outBuffer;
263         return ScreenshotClient::capture(display, ui::Dataspace::V0_SRGB,
264                                          ui::PixelFormat::RGBA_8888, Rect(), 0 /*reqWidth*/,
265                                          0 /*reqHeight*/, false, ROTATION, &outBuffer);
266     };
267     ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
268 }
269 
TEST_F(CredentialsTest,CaptureLayersTest)270 TEST_F(CredentialsTest, CaptureLayersTest) {
271     setupBackgroundSurface();
272     sp<GraphicBuffer> outBuffer;
273     std::function<status_t()> condition = [=]() {
274         sp<GraphicBuffer> outBuffer;
275         return ScreenshotClient::captureLayers(mBGSurfaceControl->getHandle(),
276                                                ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888,
277                                                Rect(), FRAME_SCALE, &outBuffer);
278     };
279     ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
280 }
281 
282 /**
283  * The following tests are for methods accessible directly through SurfaceFlinger.
284  */
285 
286 /**
287  * An app can pass a buffer queue to the media server and ask the media server to decode a DRM video
288  * to that buffer queue. The media server is the buffer producer in this case. Because the app may create
289  * its own buffer queue and act as the buffer consumer, the media server wants to be careful to avoid
290  * sending decoded video frames to the app. This is where authenticateSurfaceTexture call comes in, to check
291  * the consumer of a buffer queue is SurfaceFlinger.
292  */
TEST_F(CredentialsTest,AuthenticateSurfaceTextureTest)293 TEST_F(CredentialsTest, AuthenticateSurfaceTextureTest) {
294     setupBackgroundSurface();
295     sp<IGraphicBufferProducer> producer =
296             mBGSurfaceControl->getSurface()->getIGraphicBufferProducer();
297     sp<ISurfaceComposer> sf(ComposerService::getComposerService());
298 
299     std::function<bool()> condition = [=]() { return sf->authenticateSurfaceTexture(producer); };
300     // Anyone should be able to check if the consumer of the buffer queue is SF.
301     ASSERT_NO_FATAL_FAILURE(checkWithPrivileges(condition, true, true));
302 }
303 
TEST_F(CredentialsTest,GetLayerDebugInfo)304 TEST_F(CredentialsTest, GetLayerDebugInfo) {
305     setupBackgroundSurface();
306     sp<ISurfaceComposer> sf(ComposerService::getComposerService());
307 
308     // Historically, only root and shell can access the getLayerDebugInfo which
309     // is called when we call dumpsys. I don't see a reason why we should change this.
310     std::vector<LayerDebugInfo> outLayers;
311     // Check with root.
312     seteuid(AID_ROOT);
313     ASSERT_EQ(NO_ERROR, sf->getLayerDebugInfo(&outLayers));
314 
315     // Check as a shell.
316     seteuid(AID_SHELL);
317     ASSERT_EQ(NO_ERROR, sf->getLayerDebugInfo(&outLayers));
318 
319     // Check as anyone else.
320     seteuid(AID_ROOT);
321     seteuid(AID_BIN);
322     ASSERT_EQ(PERMISSION_DENIED, sf->getLayerDebugInfo(&outLayers));
323 }
324 
TEST_F(CredentialsTest,IsWideColorDisplayBasicCorrectness)325 TEST_F(CredentialsTest, IsWideColorDisplayBasicCorrectness) {
326     const auto display = SurfaceComposerClient::getInternalDisplayToken();
327     ASSERT_FALSE(display == nullptr);
328     bool result = false;
329     status_t error = SurfaceComposerClient::isWideColorDisplay(display, &result);
330     ASSERT_EQ(NO_ERROR, error);
331     bool hasWideColorMode = false;
332     Vector<ColorMode> colorModes;
333     SurfaceComposerClient::getDisplayColorModes(display, &colorModes);
334     for (ColorMode colorMode : colorModes) {
335         switch (colorMode) {
336             case ColorMode::DISPLAY_P3:
337             case ColorMode::ADOBE_RGB:
338             case ColorMode::DCI_P3:
339                 hasWideColorMode = true;
340                 break;
341             default:
342                 break;
343         }
344     }
345     ASSERT_EQ(hasWideColorMode, result);
346 }
347 
TEST_F(CredentialsTest,IsWideColorDisplayWithPrivileges)348 TEST_F(CredentialsTest, IsWideColorDisplayWithPrivileges) {
349     const auto display = SurfaceComposerClient::getInternalDisplayToken();
350     ASSERT_FALSE(display == nullptr);
351     std::function<status_t()> condition = [=]() {
352         bool result = false;
353         return SurfaceComposerClient::isWideColorDisplay(display, &result);
354     };
355     ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, NO_ERROR));
356 }
357 
TEST_F(CredentialsTest,GetActiveColorModeBasicCorrectness)358 TEST_F(CredentialsTest, GetActiveColorModeBasicCorrectness) {
359     const auto display = SurfaceComposerClient::getInternalDisplayToken();
360     ASSERT_FALSE(display == nullptr);
361     ColorMode colorMode = SurfaceComposerClient::getActiveColorMode(display);
362     ASSERT_NE(static_cast<ColorMode>(BAD_VALUE), colorMode);
363 }
364 
365 } // namespace android
366