/* * Copyright 2021 Google LLC * SPDX-License-Identifier: MIT */ #include #include #include #include #include "util/macros.h" #include "virglrenderer.h" #include "virglrenderer_hw.h" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); struct fuzz_renderer { bool initialized; }; static void fuzz_atexit_callback(void) { virgl_renderer_cleanup(NULL); } static void fuzz_debug_callback(UNUSED const char *fmt, UNUSED va_list ap) { /* no logging */ } static void fuzz_write_context_fence(UNUSED void *cookie, UNUSED uint32_t ctx_id, UNUSED uint32_t ring_idx, UNUSED uint64_t fence_id) { } static struct virgl_renderer_callbacks callbacks = { .version = 3, .write_context_fence = fuzz_write_context_fence, }; static struct fuzz_renderer * fuzz_renderer_get(void) { static struct fuzz_renderer renderer; if (renderer.initialized) return &renderer; int flags = VIRGL_RENDERER_NO_VIRGL | VIRGL_RENDERER_DRM | VIRGL_RENDERER_ASYNC_FENCE_CB; int ret = virgl_renderer_init(NULL, flags, &callbacks); if (ret) abort(); virgl_set_debug_callback(fuzz_debug_callback); atexit(fuzz_atexit_callback); renderer.initialized = true; return &renderer; } static uint32_t fuzz_context_create(UNUSED struct fuzz_renderer *renderer) { const uint32_t ctx_id = 1; const char name[] = "virgl_drm_fuzzer"; int ret = virgl_renderer_context_create_with_flags(ctx_id, VIRGL_RENDERER_CAPSET_DRM, sizeof(name), name); if (ret) abort(); return ctx_id; } static void fuzz_context_destroy(UNUSED struct fuzz_renderer *renderer, uint32_t ctx_id) { virgl_renderer_context_destroy(ctx_id); } static void fuzz_context_submit(UNUSED struct fuzz_renderer *renderer, uint32_t ctx_id, const uint8_t *data, size_t size) { /* We'll not be able to hit some codepaths without shmem buffer setup.. * but we'd also like to hit any potential errors that could come from * malicious input before shmem is setup. So run the same input twice, * once before and once after shmem setup. */ virgl_renderer_submit_cmd((void *)data, ctx_id, size / 4); virgl_renderer_resource_create_blob(&(struct virgl_renderer_resource_create_blob_args){ .res_handle = 1, .ctx_id = ctx_id, .size = 0x1000, }); virgl_renderer_submit_cmd((void *)data, ctx_id, size / 4); } int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { struct fuzz_renderer *renderer = fuzz_renderer_get(); const uint32_t ctx_id = fuzz_context_create(renderer); fuzz_context_submit(renderer, ctx_id, data, size); fuzz_context_destroy(renderer, ctx_id); return 0; }