1*bbecb9d1SAndroid Build Coastguard Worker // Copyright 2018 The Chromium OS Authors. All rights reserved.
2*bbecb9d1SAndroid Build Coastguard Worker //
3*bbecb9d1SAndroid Build Coastguard Worker // Redistribution and use in source and binary forms, with or without
4*bbecb9d1SAndroid Build Coastguard Worker // modification, are permitted provided that the following conditions are
5*bbecb9d1SAndroid Build Coastguard Worker // met:
6*bbecb9d1SAndroid Build Coastguard Worker //
7*bbecb9d1SAndroid Build Coastguard Worker // * Redistributions of source code must retain the above copyright
8*bbecb9d1SAndroid Build Coastguard Worker // notice, this list of conditions and the following disclaimer.
9*bbecb9d1SAndroid Build Coastguard Worker // * Redistributions in binary form must reproduce the above
10*bbecb9d1SAndroid Build Coastguard Worker // copyright notice, this list of conditions and the following disclaimer
11*bbecb9d1SAndroid Build Coastguard Worker // in the documentation and/or other materials provided with the
12*bbecb9d1SAndroid Build Coastguard Worker // distribution.
13*bbecb9d1SAndroid Build Coastguard Worker // * Neither the name of Google Inc. nor the names of its
14*bbecb9d1SAndroid Build Coastguard Worker // contributors may be used to endorse or promote products derived from
15*bbecb9d1SAndroid Build Coastguard Worker // this software without specific prior written permission.
16*bbecb9d1SAndroid Build Coastguard Worker //
17*bbecb9d1SAndroid Build Coastguard Worker // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18*bbecb9d1SAndroid Build Coastguard Worker // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19*bbecb9d1SAndroid Build Coastguard Worker // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20*bbecb9d1SAndroid Build Coastguard Worker // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21*bbecb9d1SAndroid Build Coastguard Worker // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22*bbecb9d1SAndroid Build Coastguard Worker // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23*bbecb9d1SAndroid Build Coastguard Worker // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24*bbecb9d1SAndroid Build Coastguard Worker // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25*bbecb9d1SAndroid Build Coastguard Worker // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26*bbecb9d1SAndroid Build Coastguard Worker // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27*bbecb9d1SAndroid Build Coastguard Worker // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*bbecb9d1SAndroid Build Coastguard Worker
29*bbecb9d1SAndroid Build Coastguard Worker // libfuzzer-based fuzzer for public APIs.
30*bbecb9d1SAndroid Build Coastguard Worker
31*bbecb9d1SAndroid Build Coastguard Worker #include <assert.h>
32*bbecb9d1SAndroid Build Coastguard Worker #include <stdint.h>
33*bbecb9d1SAndroid Build Coastguard Worker #include <stdlib.h>
34*bbecb9d1SAndroid Build Coastguard Worker #include <string.h>
35*bbecb9d1SAndroid Build Coastguard Worker #include <unistd.h>
36*bbecb9d1SAndroid Build Coastguard Worker
37*bbecb9d1SAndroid Build Coastguard Worker #include <epoxy/egl.h>
38*bbecb9d1SAndroid Build Coastguard Worker
39*bbecb9d1SAndroid Build Coastguard Worker #include "util/macros.h"
40*bbecb9d1SAndroid Build Coastguard Worker #include "virglrenderer.h"
41*bbecb9d1SAndroid Build Coastguard Worker
42*bbecb9d1SAndroid Build Coastguard Worker int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);
43*bbecb9d1SAndroid Build Coastguard Worker
44*bbecb9d1SAndroid Build Coastguard Worker #ifndef CLEANUP_EACH_INPUT
45*bbecb9d1SAndroid Build Coastguard Worker // eglInitialize leaks unless eglTeriminate is called (which only happens
46*bbecb9d1SAndroid Build Coastguard Worker // with CLEANUP_EACH_INPUT), so suppress leak detection on everything
47*bbecb9d1SAndroid Build Coastguard Worker // allocated by it.
48*bbecb9d1SAndroid Build Coastguard Worker const char* __lsan_default_suppressions(void);
__lsan_default_suppressions()49*bbecb9d1SAndroid Build Coastguard Worker const char* __lsan_default_suppressions() {
50*bbecb9d1SAndroid Build Coastguard Worker return "leak:eglInitialize\n";
51*bbecb9d1SAndroid Build Coastguard Worker }
52*bbecb9d1SAndroid Build Coastguard Worker
53*bbecb9d1SAndroid Build Coastguard Worker #endif // !CLEANUP_EACH_INPUT
54*bbecb9d1SAndroid Build Coastguard Worker
55*bbecb9d1SAndroid Build Coastguard Worker struct fuzzer_cookie
56*bbecb9d1SAndroid Build Coastguard Worker {
57*bbecb9d1SAndroid Build Coastguard Worker EGLDisplay display;
58*bbecb9d1SAndroid Build Coastguard Worker EGLConfig egl_config;
59*bbecb9d1SAndroid Build Coastguard Worker EGLContext ctx;
60*bbecb9d1SAndroid Build Coastguard Worker };
61*bbecb9d1SAndroid Build Coastguard Worker
fuzzer_write_fence(UNUSED void * opaque,UNUSED uint32_t fence)62*bbecb9d1SAndroid Build Coastguard Worker static void fuzzer_write_fence(UNUSED void *opaque, UNUSED uint32_t fence)
63*bbecb9d1SAndroid Build Coastguard Worker {
64*bbecb9d1SAndroid Build Coastguard Worker }
65*bbecb9d1SAndroid Build Coastguard Worker
fuzzer_create_gl_context(void * cookie,UNUSED int scanout_idx,struct virgl_renderer_gl_ctx_param * param)66*bbecb9d1SAndroid Build Coastguard Worker static virgl_renderer_gl_context fuzzer_create_gl_context(
67*bbecb9d1SAndroid Build Coastguard Worker void *cookie, UNUSED int scanout_idx,
68*bbecb9d1SAndroid Build Coastguard Worker struct virgl_renderer_gl_ctx_param *param)
69*bbecb9d1SAndroid Build Coastguard Worker {
70*bbecb9d1SAndroid Build Coastguard Worker struct fuzzer_cookie *cookie_data = cookie;
71*bbecb9d1SAndroid Build Coastguard Worker EGLContext shared = param->shared ? eglGetCurrentContext() : NULL;
72*bbecb9d1SAndroid Build Coastguard Worker const EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 3,
73*bbecb9d1SAndroid Build Coastguard Worker EGL_NONE };
74*bbecb9d1SAndroid Build Coastguard Worker EGLContext ctx = eglCreateContext(cookie_data->display,
75*bbecb9d1SAndroid Build Coastguard Worker cookie_data->egl_config,
76*bbecb9d1SAndroid Build Coastguard Worker shared,
77*bbecb9d1SAndroid Build Coastguard Worker context_attribs);
78*bbecb9d1SAndroid Build Coastguard Worker assert(ctx);
79*bbecb9d1SAndroid Build Coastguard Worker
80*bbecb9d1SAndroid Build Coastguard Worker return ctx;
81*bbecb9d1SAndroid Build Coastguard Worker }
82*bbecb9d1SAndroid Build Coastguard Worker
fuzzer_destroy_gl_context(void * cookie,virgl_renderer_gl_context ctx)83*bbecb9d1SAndroid Build Coastguard Worker static void fuzzer_destroy_gl_context(void *cookie,
84*bbecb9d1SAndroid Build Coastguard Worker virgl_renderer_gl_context ctx)
85*bbecb9d1SAndroid Build Coastguard Worker {
86*bbecb9d1SAndroid Build Coastguard Worker struct fuzzer_cookie *cookie_data = cookie;
87*bbecb9d1SAndroid Build Coastguard Worker eglDestroyContext(cookie_data->display, ctx);
88*bbecb9d1SAndroid Build Coastguard Worker }
89*bbecb9d1SAndroid Build Coastguard Worker
fuzzer_make_current(UNUSED void * cookie,UNUSED int scanout_idx,UNUSED virgl_renderer_gl_context ctx)90*bbecb9d1SAndroid Build Coastguard Worker static int fuzzer_make_current(UNUSED void *cookie, UNUSED int scanout_idx,
91*bbecb9d1SAndroid Build Coastguard Worker UNUSED virgl_renderer_gl_context ctx)
92*bbecb9d1SAndroid Build Coastguard Worker {
93*bbecb9d1SAndroid Build Coastguard Worker return 0;
94*bbecb9d1SAndroid Build Coastguard Worker }
95*bbecb9d1SAndroid Build Coastguard Worker
96*bbecb9d1SAndroid Build Coastguard Worker const int FUZZER_CTX_ID = 1;
97*bbecb9d1SAndroid Build Coastguard Worker const char *SWRAST_ENV = "LIBGL_ALWAYS_SOFTWARE";
98*bbecb9d1SAndroid Build Coastguard Worker
99*bbecb9d1SAndroid Build Coastguard Worker static struct fuzzer_cookie cookie;
100*bbecb9d1SAndroid Build Coastguard Worker
101*bbecb9d1SAndroid Build Coastguard Worker static struct virgl_renderer_callbacks fuzzer_cbs = {
102*bbecb9d1SAndroid Build Coastguard Worker .version = 1,
103*bbecb9d1SAndroid Build Coastguard Worker .write_fence = fuzzer_write_fence,
104*bbecb9d1SAndroid Build Coastguard Worker .create_gl_context = fuzzer_create_gl_context,
105*bbecb9d1SAndroid Build Coastguard Worker .destroy_gl_context = fuzzer_destroy_gl_context,
106*bbecb9d1SAndroid Build Coastguard Worker .make_current = fuzzer_make_current,
107*bbecb9d1SAndroid Build Coastguard Worker };
108*bbecb9d1SAndroid Build Coastguard Worker
109*bbecb9d1SAndroid Build Coastguard Worker static bool initialized = false;
110*bbecb9d1SAndroid Build Coastguard Worker
initialize_environment()111*bbecb9d1SAndroid Build Coastguard Worker static int initialize_environment()
112*bbecb9d1SAndroid Build Coastguard Worker {
113*bbecb9d1SAndroid Build Coastguard Worker if (!initialized) {
114*bbecb9d1SAndroid Build Coastguard Worker EGLBoolean ok;
115*bbecb9d1SAndroid Build Coastguard Worker
116*bbecb9d1SAndroid Build Coastguard Worker // Force SW rendering unless env variable is already set.
117*bbecb9d1SAndroid Build Coastguard Worker setenv(SWRAST_ENV, "true", 0);
118*bbecb9d1SAndroid Build Coastguard Worker
119*bbecb9d1SAndroid Build Coastguard Worker cookie.display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
120*bbecb9d1SAndroid Build Coastguard Worker assert(cookie.display != EGL_NO_DISPLAY);
121*bbecb9d1SAndroid Build Coastguard Worker
122*bbecb9d1SAndroid Build Coastguard Worker ok = eglInitialize(cookie.display, NULL, NULL);
123*bbecb9d1SAndroid Build Coastguard Worker assert(ok);
124*bbecb9d1SAndroid Build Coastguard Worker
125*bbecb9d1SAndroid Build Coastguard Worker const EGLint config_attribs[] = { EGL_SURFACE_TYPE, EGL_DONT_CARE,
126*bbecb9d1SAndroid Build Coastguard Worker EGL_NONE };
127*bbecb9d1SAndroid Build Coastguard Worker EGLint num_configs;
128*bbecb9d1SAndroid Build Coastguard Worker ok = eglChooseConfig(cookie.display, config_attribs,
129*bbecb9d1SAndroid Build Coastguard Worker &cookie.egl_config, 1, &num_configs);
130*bbecb9d1SAndroid Build Coastguard Worker assert(ok);
131*bbecb9d1SAndroid Build Coastguard Worker
132*bbecb9d1SAndroid Build Coastguard Worker ok = eglBindAPI(EGL_OPENGL_ES_API);
133*bbecb9d1SAndroid Build Coastguard Worker assert(ok);
134*bbecb9d1SAndroid Build Coastguard Worker
135*bbecb9d1SAndroid Build Coastguard Worker const EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 3,
136*bbecb9d1SAndroid Build Coastguard Worker EGL_NONE };
137*bbecb9d1SAndroid Build Coastguard Worker cookie.ctx = eglCreateContext(cookie.display, cookie.egl_config,
138*bbecb9d1SAndroid Build Coastguard Worker EGL_NO_CONTEXT, context_attribs);
139*bbecb9d1SAndroid Build Coastguard Worker assert(cookie.ctx != EGL_NO_CONTEXT);
140*bbecb9d1SAndroid Build Coastguard Worker
141*bbecb9d1SAndroid Build Coastguard Worker ok = eglMakeCurrent(cookie.display, EGL_NO_SURFACE, EGL_NO_SURFACE,
142*bbecb9d1SAndroid Build Coastguard Worker cookie.ctx);
143*bbecb9d1SAndroid Build Coastguard Worker assert(ok);
144*bbecb9d1SAndroid Build Coastguard Worker
145*bbecb9d1SAndroid Build Coastguard Worker initialized = true;
146*bbecb9d1SAndroid Build Coastguard Worker }
147*bbecb9d1SAndroid Build Coastguard Worker
148*bbecb9d1SAndroid Build Coastguard Worker return FUZZER_CTX_ID;
149*bbecb9d1SAndroid Build Coastguard Worker }
150*bbecb9d1SAndroid Build Coastguard Worker
151*bbecb9d1SAndroid Build Coastguard Worker #ifdef CLEANUP_EACH_INPUT
cleanup_environment()152*bbecb9d1SAndroid Build Coastguard Worker static void cleanup_environment()
153*bbecb9d1SAndroid Build Coastguard Worker {
154*bbecb9d1SAndroid Build Coastguard Worker if (cookie.ctx != EGL_NO_CONTEXT) {
155*bbecb9d1SAndroid Build Coastguard Worker eglMakeCurrent(cookie.display, NULL, NULL, NULL);
156*bbecb9d1SAndroid Build Coastguard Worker eglDestroyContext(cookie.display, cookie.ctx);
157*bbecb9d1SAndroid Build Coastguard Worker }
158*bbecb9d1SAndroid Build Coastguard Worker
159*bbecb9d1SAndroid Build Coastguard Worker if (cookie.display != EGL_NO_DISPLAY) {
160*bbecb9d1SAndroid Build Coastguard Worker eglTerminate(cookie.display);
161*bbecb9d1SAndroid Build Coastguard Worker }
162*bbecb9d1SAndroid Build Coastguard Worker
163*bbecb9d1SAndroid Build Coastguard Worker initialized = false;
164*bbecb9d1SAndroid Build Coastguard Worker }
165*bbecb9d1SAndroid Build Coastguard Worker #endif
166*bbecb9d1SAndroid Build Coastguard Worker
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)167*bbecb9d1SAndroid Build Coastguard Worker int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
168*bbecb9d1SAndroid Build Coastguard Worker {
169*bbecb9d1SAndroid Build Coastguard Worker uint32_t ctx_id = initialize_environment();
170*bbecb9d1SAndroid Build Coastguard Worker int ret;
171*bbecb9d1SAndroid Build Coastguard Worker
172*bbecb9d1SAndroid Build Coastguard Worker // There are trade-offs here between ensuring that state is not persisted
173*bbecb9d1SAndroid Build Coastguard Worker // between invocations of virgl_renderer_submit_cmd, and to avoid leaking
174*bbecb9d1SAndroid Build Coastguard Worker // resources that comes with repeated dlopen()/dlclose()ing the mesa
175*bbecb9d1SAndroid Build Coastguard Worker // driver with each eglInitialize()/eglTerminate() if CLEANUP_EACH_INPUT
176*bbecb9d1SAndroid Build Coastguard Worker // is set.
177*bbecb9d1SAndroid Build Coastguard Worker
178*bbecb9d1SAndroid Build Coastguard Worker ret = virgl_renderer_init(&cookie, 0, &fuzzer_cbs);
179*bbecb9d1SAndroid Build Coastguard Worker assert(!ret);
180*bbecb9d1SAndroid Build Coastguard Worker
181*bbecb9d1SAndroid Build Coastguard Worker const char *name = "fuzzctx";
182*bbecb9d1SAndroid Build Coastguard Worker ret = virgl_renderer_context_create(ctx_id, strlen(name), name);
183*bbecb9d1SAndroid Build Coastguard Worker assert(!ret);
184*bbecb9d1SAndroid Build Coastguard Worker
185*bbecb9d1SAndroid Build Coastguard Worker virgl_renderer_submit_cmd((void *) data, ctx_id, size / sizeof(uint32_t));
186*bbecb9d1SAndroid Build Coastguard Worker
187*bbecb9d1SAndroid Build Coastguard Worker virgl_renderer_context_destroy(ctx_id);
188*bbecb9d1SAndroid Build Coastguard Worker
189*bbecb9d1SAndroid Build Coastguard Worker virgl_renderer_cleanup(&cookie);
190*bbecb9d1SAndroid Build Coastguard Worker
191*bbecb9d1SAndroid Build Coastguard Worker #ifdef CLEANUP_EACH_INPUT
192*bbecb9d1SAndroid Build Coastguard Worker // The following cleans up between each input which is a lot slower.
193*bbecb9d1SAndroid Build Coastguard Worker cleanup_environment();
194*bbecb9d1SAndroid Build Coastguard Worker #endif
195*bbecb9d1SAndroid Build Coastguard Worker
196*bbecb9d1SAndroid Build Coastguard Worker return 0;
197*bbecb9d1SAndroid Build Coastguard Worker }
198