Commit message: tests: Add trigger for overflow in texture data upload

Related #140

Signed-off-by: Gert Wollny <gert.wollny@collabora.com>
Acked-by: Emil Velikov <emil.velikov@collabora.com>
CVE: CVE-2019-18391
CWE: CWE-787
Vulnerability description: A heap-based buffer overflow in the vrend_renderer_transfer_write_iov function in vrend_renderer.c in virglrenderer through 0.8.0 allows guest OS users to cause a denial of service via VIRGL_CCMD_RESOURCE_INLINE_WRITE commands.

Project: virglrenderer
File: test_fuzzer_formats.c

static void  test_format_is_plain_nullptr_deref_trigger()
{
   struct virgl_renderer_resource_create_args args;
   args.handle = 10;
   args.target = 0;
   args.format = 126;
   args.bind = 2;
   args.width = 10;
   args.height = 10;
   args.depth = 10;
   args.array_size = 0;
   args.last_level = 0;
   args.nr_samples = 0;
   args.flags = 0;

   virgl_renderer_resource_create(&args, NULL, 0);
   virgl_renderer_ctx_attach_resource(ctx_id, args.handle);

   uint32_t cmd[VIRGL_CMD_BLIT_SIZE + 1];

   int i = 0;
   cmd[i++] = VIRGL_CMD_BLIT_SIZE << 16 | 0 << 8 | VIRGL_CCMD_BLIT;
   cmd[i++] = 0; // s0
   cmd[i++] = 0; // minxy
   cmd[i++] = 0; // maxxy
   cmd[i++] = 10; //dhandle
   cmd[i++] = 0; // dlevel
   cmd[i++] = 445382656; //dformat
   cmd[i++] = 3; //dx
   cmd[i++] = 0; // dy
   cmd[i++] = 0; // dz
   cmd[i++] = 0; //dw
   cmd[i++] = 0; // dh
   cmd[i++] = 0; // dd
   cmd[i++] = 10; //shandle
   cmd[i++] = 0; //slevel
   cmd[i++] = 126; //sformat
   cmd[i++] = 0; //sx
   cmd[i++] = 0; // sy
   cmd[i++] = 0; // sz
   cmd[i++] = 0; // sw
   cmd[i++] = 3; // sh
   cmd[i++] = 0; // sd

   virgl_renderer_submit_cmd((void *) cmd, ctx_id, VIRGL_CMD_BLIT_SIZE + 1);
}

Project: virglrenderer
File: test_fuzzer_formats.c

static void test_format_is_has_alpha_nullptr_deref_trigger_original()
{
   struct virgl_renderer_resource_create_args args;
   args.handle = 8;
   args.target = 0;
   args.format = 10;
   args.bind = 8;
   args.width = 0;
   args.height = 45;
   args.depth = 35;
   args.array_size = 0;
   args.last_level = 0;
   args.nr_samples = 0;
   args.flags = 0;
   virgl_renderer_resource_create(&args, NULL, 0);
   virgl_renderer_ctx_attach_resource(ctx_id, args.handle);

   uint32_t cmd[VIRGL_OBJ_SAMPLER_VIEW_SIZE + 1];

   int i = 0;
   cmd[i++] = VIRGL_OBJ_SAMPLER_VIEW_SIZE << 16 | VIRGL_OBJECT_SAMPLER_VIEW << 8 | VIRGL_CCMD_CREATE_OBJECT;
   cmd[i++] = 35; //handle
   cmd[i++] = 8; // res_handle
   cmd[i++] = 524288; //format
   cmd[i++] = 0; //first_ele
   cmd[i++] = 0; //last_ele
   cmd[i++] = 10; //swizzle

   virgl_renderer_submit_cmd((void *) cmd, ctx_id, VIRGL_OBJ_SAMPLER_VIEW_SIZE + 1);
}

Project: virglrenderer
File: test_fuzzer_formats.c

fuzzer_create_gl_context(UNUSED void *cookie, UNUSED int scanout_idx,
                         struct virgl_renderer_gl_ctx_param *param)
{
   struct virgl_gl_ctx_param vparams;
   vparams.shared = false;
   vparams.major_ver = param->major_ver;
   vparams.minor_ver = param->minor_ver;
   return virgl_egl_create_context(test_egl, &vparams);
}

Project: virglrenderer
File: test_fuzzer_formats.c

static void test_heap_overflow_vrend_renderer_transfer_write_iov_compressed_tex()
{
   struct virgl_renderer_resource_create_args args;
   args.handle = 1;
   args.target = 5;
   args.format = 203;
   args.bind = 1;
   args.width = 100;
   args.height = 1;
   args.depth = 1;
   args.array_size = 0;
   args.last_level = 0;
   args.nr_samples = 0;
   args.flags = 1;

   virgl_renderer_resource_create(&args, NULL, 0);
   virgl_renderer_ctx_attach_resource(ctx_id, args.handle);

   char data[16];
   memset(data, 'A', 16);
   uint32_t cmd[11 + 4 +1];

   int i = 0;
   cmd[i++] = (11+4) << 16 | 0 << 8 | VIRGL_CCMD_RESOURCE_INLINE_WRITE;
   cmd[i++] = 1; // handle
   cmd[i++] = 0; // level
   cmd[i++] = 0; // usage
   cmd[i++] = 135168; // stride
   cmd[i++] = 655361; // layer_stride
   cmd[i++] = 1; // x
   cmd[i++] = 0; // y
   cmd[i++] = 0; // z
   cmd[i++] = 5; // w
   cmd[i++] = 1; // h
   cmd[i++] = 0; // d
   memcpy(&cmd[i], data, 16);

   virgl_renderer_submit_cmd((void *) cmd, ctx_id, 11 + 4 + 1);
}

Project: virglrenderer
File: test_fuzzer_formats.c

static void fuzzer_write_fence(UNUSED void *opaque, UNUSED uint32_t fence) {}

Project: virglrenderer
File: test_fuzzer_formats.c

static void initialize_environment()
{
   setenv("LIBGL_ALWAYS_SOFTWARE", "true", 0);
   setenv("GALLIUM_DRIVER", "softpipe", 0);
   test_egl = virgl_egl_init(NULL, true, true);
   assert(test_egl);

   virgl_renderer_init(&cookie, VIRGL_RENDERER_USE_GLES|
                       VIRGL_RENDERER_USE_SURFACELESS, &fuzzer_cbs);

   const char *name = "fuzzctx";
   virgl_renderer_context_create(ctx_id, (unsigned)strlen(name), name);
}

Project: virglrenderer
File: test_fuzzer_formats.c

static void test_format_util_format_is_rgb_nullptr_deref_trigger_illegal_resource()
{
   struct virgl_renderer_resource_create_args args;
   args.handle = 8;
   args.target = 0;
   args.format = 109;
   args.bind = 8;
   args.width = 2;
   args.height = 0;
   args.depth = 0;
   args.array_size = 0;
   args.last_level = 0;
   args.nr_samples = 0;
   args.flags = 0;

   virgl_renderer_resource_create(&args, NULL, 0);
   virgl_renderer_ctx_attach_resource(ctx_id, args.handle);

   uint32_t cmd[VIRGL_OBJ_SAMPLER_VIEW_SIZE + 1];

   int i = 0;
   cmd[i++] = VIRGL_OBJ_SAMPLER_VIEW_SIZE << 16 | VIRGL_OBJECT_SAMPLER_VIEW << 8 | VIRGL_CCMD_CREATE_OBJECT;
   cmd[i++] = 35; // handle
   cmd[i++] = 8; // res_handle
   cmd[i++] = 3107; //format
   cmd[i++] = 0; //first element
   cmd[i++] = 0; // last element
   cmd[i++] = 0; //swizzle

   virgl_renderer_submit_cmd((void *) cmd, ctx_id, VIRGL_OBJ_SAMPLER_VIEW_SIZE + 1);
}

Project: virglrenderer
File: test_fuzzer_formats.c

static void test_blit_info_format_check_null_format()
{
   struct virgl_renderer_resource_create_args args;
   args.handle = 10;
   args.target = 3;
   args.format = 10;
   args.bind = 10;
   args.width = 2;
   args.height = 1;
   args.depth = 1;
   args.array_size = 0;
   args.last_level = 0;
   args.nr_samples = 0;
   args.flags = 0;

   virgl_renderer_resource_create(&args, NULL, 0);
   virgl_renderer_ctx_attach_resource(ctx_id, args.handle);

   uint32_t cmd[VIRGL_CMD_BLIT_SIZE + 1];

   int i = 0;
   cmd[i++] = VIRGL_CMD_BLIT_SIZE << 16 | 0 << 8 | VIRGL_CCMD_BLIT;
   cmd[i++] = 0x8000001; // s0
   cmd[i++] = 0; // minxy
   cmd[i++] = 0; // maxxy
   cmd[i++] = 10; //dhandle
   cmd[i++] = 0; // dlevel
   cmd[i++] = 1; //dformat
   cmd[i++] = 0; //dx
   cmd[i++] = 0; // dy
   cmd[i++] = 0; // dz
   cmd[i++] = 0; //dw
   cmd[i++] = 0; // dh
   cmd[i++] = 0; // dd
   cmd[i++] = 10; //shandle
   cmd[i++] = 0; //slevel
   cmd[i++] = 0; //sformat
   cmd[i++] = 0; //sx
   cmd[i++] = 0; // sy
   cmd[i++] = 0; // sz
   cmd[i++] = 0; // sw
   cmd[i++] = 0; // sh
   cmd[i++] = 0; // sd

   virgl_renderer_submit_cmd((void *) cmd, ctx_id, VIRGL_CMD_BLIT_SIZE + 1);
}

Project: virglrenderer
File: test_fuzzer_formats.c

static void test_format_is_has_alpha_nullptr_deref_trigger_legal_resource()
{
   struct virgl_renderer_resource_create_args args;
   args.handle = 8;
   args.target = 2;
   args.format = 10;
   args.bind = 8;
   args.width = 10;
   args.height = 45;
   args.depth = 1;
   args.array_size = 0;
   args.last_level = 0;
   args.nr_samples = 0;
   args.flags = 0;
   virgl_renderer_resource_create(&args, NULL, 0);
   virgl_renderer_ctx_attach_resource(ctx_id, args.handle);

   uint32_t cmd[VIRGL_OBJ_SAMPLER_VIEW_SIZE + 1];

   int i = 0;
   cmd[i++] = VIRGL_OBJ_SAMPLER_VIEW_SIZE << 16 | VIRGL_OBJECT_SAMPLER_VIEW << 8 | VIRGL_CCMD_CREATE_OBJECT;
   cmd[i++] = 35; //handle
   cmd[i++] = 8; // res_handle
   cmd[i++] = 524288; //format
   cmd[i++] = 0; //first_ele
   cmd[i++] = 0; //last_ele
   cmd[i++] = 10; //swizzle

   virgl_renderer_submit_cmd((void *) cmd, ctx_id, VIRGL_OBJ_SAMPLER_VIEW_SIZE + 1);
}

Project: virglrenderer
File: test_fuzzer_formats.c

static void fuzzer_destory_gl_context(UNUSED void *cookie, virgl_renderer_gl_context ctx)
{
   virgl_egl_destroy_context(test_egl, ctx);
}

Project: virglrenderer
File: test_fuzzer_formats.c

int main()
{
   initialize_environment();

   test_format_wrong_size();
   test_blit_info_format_check();
   test_blit_info_format_check_null_format();
   test_format_is_plain_nullptr_deref_trigger();
   test_format_util_format_is_rgb_nullptr_deref_trigger_illegal_resource();
   test_format_util_format_is_rgb_nullptr_deref_trigger();
   test_double_free_in_vrend_renderer_blit_int_trigger_invalid_formats();
   test_double_free_in_vrend_renderer_blit_int_trigger();
   test_format_is_has_alpha_nullptr_deref_trigger_original();
   test_format_is_has_alpha_nullptr_deref_trigger_legal_resource();

   test_heap_overflow_vrend_renderer_transfer_write_iov();
   test_heap_overflow_vrend_renderer_transfer_write_iov_compressed_tex();

   virgl_renderer_context_destroy(ctx_id);
   virgl_renderer_cleanup(&cookie);
   virgl_egl_destroy(test_egl);

   return 0;
}

Project: virglrenderer
File: test_fuzzer_formats.c

static void test_blit_info_format_check()
{
   struct virgl_renderer_resource_create_args args;
   args.handle = 10;
   args.target = 3;
   args.format = 10;
   args.bind = 10;
   args.width = 2;
   args.height = 1;
   args.depth = 1;
   args.array_size = 0;
   args.last_level = 0;
   args.nr_samples = 0;
   args.flags = 0;

   virgl_renderer_resource_create(&args, NULL, 0);
   virgl_renderer_ctx_attach_resource(ctx_id, args.handle);

   uint32_t cmd[VIRGL_CMD_BLIT_SIZE + 1];

   int i = 0;
   cmd[i++] = VIRGL_CMD_BLIT_SIZE << 16 | 0 << 8 | VIRGL_CCMD_BLIT;
   cmd[i++] = 0x8000001; // s0
   cmd[i++] = 0; // minxy
   cmd[i++] = 0; // maxxy
   cmd[i++] = 10; //dhandle
   cmd[i++] = 0; // dlevel
   cmd[i++] = 0x1000029; //dformat
   cmd[i++] = 0; //dx
   cmd[i++] = 0; // dy
   cmd[i++] = 0; // dz
   cmd[i++] = 0; //dw
   cmd[i++] = 0; // dh
   cmd[i++] = 0; // dd
   cmd[i++] = 10; //shandle
   cmd[i++] = 0; //slevel
   cmd[i++] = 10; //sformat
   cmd[i++] = 0; //sx
   cmd[i++] = 0; // sy
   cmd[i++] = 0; // sz
   cmd[i++] = 0; // sw
   cmd[i++] = 0; // sh
   cmd[i++] = 0; // sd

   virgl_renderer_submit_cmd((void *) cmd, ctx_id, VIRGL_CMD_BLIT_SIZE + 1);
}

Project: virglrenderer
File: test_fuzzer_formats.c

static void test_double_free_in_vrend_renderer_blit_int_trigger()
{
   struct virgl_renderer_resource_create_args args;
   args.handle = 1;
   args.target = 2;
   args.format = VIRGL_FORMAT_Z32_UNORM;
   args.bind = VIRGL_BIND_SAMPLER_VIEW;
   args.width = 2;
   args.height = 2;
   args.depth = 1;
   args.array_size = 0;
   args.last_level = 0;
   args.nr_samples = 1;
   args.flags = 0;

   virgl_renderer_resource_create(&args, NULL, 0);
   virgl_renderer_ctx_attach_resource(ctx_id, args.handle);

   args.handle = 6;
   args.target = 2;
   args.format = VIRGL_FORMAT_Z32_UNORM;
   args.bind = VIRGL_BIND_SAMPLER_VIEW;
   args.width = 2;
   args.height = 2;
   args.depth = 1;
   args.array_size = 0;
   args.last_level = 0;
   args.nr_samples = 0;
   args.flags = 0;

   virgl_renderer_resource_create(&args, NULL, 0);
   virgl_renderer_ctx_attach_resource(ctx_id, args.handle);

   args.handle = 1;
   args.target = 7;
   args.format = VIRGL_FORMAT_Z32_UNORM;
   args.bind = 1;
   args.width = 6;
   args.height = 1;
   args.depth = 1;
   args.array_size = 2;
   args.last_level = 0;
   args.nr_samples = 0;
   args.flags = 0;

   virgl_renderer_resource_create(&args, NULL, 0);
   virgl_renderer_ctx_attach_resource(ctx_id, args.handle);

   uint32_t cmd[VIRGL_CMD_BLIT_SIZE + 1];

   int i = 0;
   cmd[i++] = VIRGL_CMD_BLIT_SIZE << 16 | 0 << 8 | VIRGL_CCMD_BLIT;
   cmd[i++] = 0x30 ; // s0
   cmd[i++] = 1; // minxy
   cmd[i++] = 36; // maxxy
   cmd[i++] = 6; //dhandle
   cmd[i++] = 0; // dlevel
   cmd[i++] = VIRGL_FORMAT_Z32_UNORM; //dformat
   cmd[i++] = 0; //dx
   cmd[i++] = 0; // dy
   cmd[i++] = 0; // dz
   cmd[i++] = 6; //dw
   cmd[i++] = 1; // dh
   cmd[i++] = 1; // dd
   cmd[i++] = 1; //shandle
   cmd[i++] = 0; //slevel
   cmd[i++] = VIRGL_FORMAT_Z32_UNORM; //sformat
   cmd[i++] = 0; //sx
   cmd[i++] = 0; // sy
   cmd[i++] = 0; // sz
   cmd[i++] = 1; // sw
   cmd[i++] = 2; // sh
   cmd[i++] = 1; // sd

   virgl_renderer_submit_cmd((void *) cmd, ctx_id, VIRGL_CMD_BLIT_SIZE + 1);
}

Project: virglrenderer
File: test_fuzzer_formats.c

static void test_heap_overflow_vrend_renderer_transfer_write_iov()
{
   struct virgl_renderer_resource_create_args args;
   args.handle = 4;
   args.target = 0;
   args.format = 4;
   args.bind = 131072;
   args.width = 0;
   args.height = 1;
   args.depth = 1;
   args.array_size = 0;
   args.last_level = 0;
   args.nr_samples = 0;
   args.flags = 0;

   virgl_renderer_resource_create(&args, NULL, 0);
   virgl_renderer_ctx_attach_resource(ctx_id, args.handle);

   char data[16];
   memset(data, 'A', 16);
   uint32_t cmd[11 + 4 +1];

   int i = 0;
   cmd[i++] = (11+4) << 16 | 0 << 8 | VIRGL_CCMD_RESOURCE_INLINE_WRITE;
   cmd[i++] = 4; // handle
   cmd[i++] = 0; // level
   cmd[i++] = 0; // usage
   cmd[i++] = 0; // stride
   cmd[i++] = 0; // layer_stride
   cmd[i++] = 0; // x
   cmd[i++] = 0; // y
   cmd[i++] = 0; // z
   cmd[i++] = 0x80000000; // w
   cmd[i++] = 0; // h
   cmd[i++] = 0; // d
   memcpy(&cmd[i], data, 16);

   virgl_renderer_submit_cmd((void *) cmd, ctx_id, 11 + 4 + 1);
}

Project: virglrenderer
File: test_fuzzer_formats.c

static int fuzzer_make_current(UNUSED void *cookie, UNUSED int scanout_idx,
                               virgl_renderer_gl_context ctx)
{
   return virgl_egl_make_context_current(test_egl, ctx);
}

Project: virglrenderer
File: test_fuzzer_formats.c

static void test_format_wrong_size()
{
   struct virgl_renderer_resource_create_args args;
   args.handle = 10;
   args.target = 3;
   args.format = 10;
   args.bind = 10;
   args.width = 2;
   args.height = 0;
   args.depth = 0;
   args.array_size = 0;
   args.last_level = 0;
   args.nr_samples = 0;
   args.flags = 0;

   virgl_renderer_resource_create(&args, NULL, 0);
   virgl_renderer_ctx_attach_resource(ctx_id, args.handle);

   uint32_t cmd[VIRGL_CMD_BLIT_SIZE + 1];

   int i = 0;
   cmd[i++] = VIRGL_CMD_BLIT_SIZE << 16 | 0 << 8 | VIRGL_CCMD_BLIT;
   cmd[i++] = 0x8000001; // s0
   cmd[i++] = 0; // minxy
   cmd[i++] = 0; // maxxy
   cmd[i++] = 10; //dhandle
   cmd[i++] = 0; // dlevel
   cmd[i++] = 0x1000029; //dformat
   cmd[i++] = 0; //dx
   cmd[i++] = 0; // dy
   cmd[i++] = 0; // dz
   cmd[i++] = 0; //dw
   cmd[i++] = 0; // dh
   cmd[i++] = 0; // dd
   cmd[i++] = 10; //shandle
   cmd[i++] = 0; //slevel
   cmd[i++] = 0; //sformat
   cmd[i++] = 0; //sx
   cmd[i++] = 0; // sy
   cmd[i++] = 0; // sz
   cmd[i++] = 0; // sw
   cmd[i++] = 0; // sh
   cmd[i++] = 0; // sd

   virgl_renderer_submit_cmd((void *) cmd, ctx_id, VIRGL_CMD_BLIT_SIZE + 1);
}

Project: virglrenderer
File: test_fuzzer_formats.c

static void test_double_free_in_vrend_renderer_blit_int_trigger_invalid_formats()
{
   struct virgl_renderer_resource_create_args args;
   args.handle = 1;
   args.target = 0;
   args.format = 262144;
   args.bind = 131072;
   args.width = 1;
   args.height = 1;
   args.depth = 1;
   args.array_size = 0;
   args.last_level = 0;
   args.nr_samples = 0;
   args.flags = 0;

   virgl_renderer_resource_create(&args, NULL, 0);
   virgl_renderer_ctx_attach_resource(ctx_id, args.handle);

   args.handle = 6;
   args.target = 4;
   args.format = 1;
   args.bind = 2;
   args.width = 2;
   args.height = 0;
   args.depth = 1;
   args.array_size = 6;
   args.last_level = 2;
   args.nr_samples = 0;
   args.flags = 0;

   virgl_renderer_resource_create(&args, NULL, 0);
   virgl_renderer_ctx_attach_resource(ctx_id, args.handle);

   args.handle = 1;
   args.target = 7;
   args.format = 237;
   args.bind = 1;
   args.width = 6;
   args.height = 0;
   args.depth = 1;
   args.array_size = 0;
   args.last_level = 0;
   args.nr_samples = 6;
   args.flags = 0;

   virgl_renderer_resource_create(&args, NULL, 0);
   virgl_renderer_ctx_attach_resource(ctx_id, args.handle);

   uint32_t cmd[VIRGL_CMD_BLIT_SIZE + 1];

   int i = 0;
   cmd[i++] = VIRGL_CMD_BLIT_SIZE << 16 | 0 << 8 | VIRGL_CCMD_BLIT;
   cmd[i++] = 17113104; // s0
   cmd[i++] = 1; // minxy
   cmd[i++] = 36; // maxxy
   cmd[i++] = 6; //dhandle
   cmd[i++] = 0; // dlevel
   cmd[i++] = 0; //dformat
   cmd[i++] = 0; //dx
   cmd[i++] = 0; // dy
   cmd[i++] = 0; // dz
   cmd[i++] = 6; //dw
   cmd[i++] = 0; // dh
   cmd[i++] = 0; // dd
   cmd[i++] = 1; //shandle
   cmd[i++] = 0; //slevel
   cmd[i++] = 0; //sformat
   cmd[i++] = 0; //sx
   cmd[i++] = 0; // sy
   cmd[i++] = 268435456; // sz
   cmd[i++] = 0; // sw
   cmd[i++] = 0; // sh
   cmd[i++] = 0; // sd

   virgl_renderer_submit_cmd((void *) cmd, ctx_id, VIRGL_CMD_BLIT_SIZE + 1);
}

Project: virglrenderer
File: test_fuzzer_formats.c

static void test_format_util_format_is_rgb_nullptr_deref_trigger()
{
   struct virgl_renderer_resource_create_args args;
   args.handle = 8;
   args.target = 1;
   args.format = 109;
   args.bind = 8;
   args.width = 2;
   args.height = 2;
   args.depth = 0;
   args.array_size = 0;
   args.last_level = 0;
   args.nr_samples = 0;
   args.flags = 0;

   virgl_renderer_resource_create(&args, NULL, 0);
   virgl_renderer_ctx_attach_resource(ctx_id, args.handle);

   uint32_t cmd[VIRGL_OBJ_SAMPLER_VIEW_SIZE + 1];

   int i = 0;
   cmd[i++] = VIRGL_OBJ_SAMPLER_VIEW_SIZE << 16 | VIRGL_OBJECT_SAMPLER_VIEW << 8 | VIRGL_CCMD_CREATE_OBJECT;
   cmd[i++] = 35; // handle
   cmd[i++] = 8; // res_handle
   cmd[i++] = 3107; //format
   cmd[i++] = 0; //first element
   cmd[i++] = 0; // last element
   cmd[i++] = 0; //swizzle

   virgl_renderer_submit_cmd((void *) cmd, ctx_id, VIRGL_OBJ_SAMPLER_VIEW_SIZE + 1);
}