summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc-André Lureau <marcandre.lureau@redhat.com>2016-02-04 08:36:40 +0100
committerDave Airlie <airlied@redhat.com>2016-02-10 12:39:48 +1000
commitb93e67deb0693d6af58fb01ea6c08712cee8b630 (patch)
treeab7324c1e31fdd050d117e869f1eacc99e1ff85e
parent7febc0023bf65dcb2ef5e2da006c88d0d2f689d7 (diff)
decode: check the buffer length before access
Avoid out of bounds array access. Found thanks to AddressSanitizer & american fuzzy lop. Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
-rw-r--r--src/vrend_decode.c72
1 files changed, 39 insertions, 33 deletions
diff --git a/src/vrend_decode.c b/src/vrend_decode.c
index 0e54a7a..fad633e 100644
--- a/src/vrend_decode.c
+++ b/src/vrend_decode.c
@@ -126,14 +126,14 @@ static int vrend_decode_create_stream_output_target(struct vrend_decode_ctx *ctx
static int vrend_decode_set_framebuffer_state(struct vrend_decode_ctx *ctx, int length)
{
+ if (length < 2)
+ return EINVAL;
+
uint32_t nr_cbufs = get_buf_entry(ctx, VIRGL_SET_FRAMEBUFFER_STATE_NR_CBUFS);
uint32_t zsurf_handle = get_buf_entry(ctx, VIRGL_SET_FRAMEBUFFER_STATE_NR_ZSURF_HANDLE);
uint32_t surf_handle[8];
int i;
- if (length < 2)
- return EINVAL;
-
if (length != (2 + nr_cbufs))
return EINVAL;
for (i = 0; i < nr_cbufs; i++)
@@ -229,15 +229,15 @@ static int vrend_decode_set_constant_buffer(struct vrend_decode_ctx *ctx, uint16
static int vrend_decode_set_uniform_buffer(struct vrend_decode_ctx *ctx, int length)
{
+ if (length != VIRGL_SET_UNIFORM_BUFFER_SIZE)
+ return EINVAL;
+
uint32_t shader = get_buf_entry(ctx, VIRGL_SET_UNIFORM_BUFFER_SHADER_TYPE);
uint32_t index = get_buf_entry(ctx, VIRGL_SET_UNIFORM_BUFFER_INDEX);
uint32_t offset = get_buf_entry(ctx, VIRGL_SET_UNIFORM_BUFFER_OFFSET);
uint32_t blength = get_buf_entry(ctx, VIRGL_SET_UNIFORM_BUFFER_LENGTH);
uint32_t handle = get_buf_entry(ctx, VIRGL_SET_UNIFORM_BUFFER_RES_HANDLE);
- if (length != VIRGL_SET_UNIFORM_BUFFER_SIZE)
- return EINVAL;
-
if (shader >= PIPE_SHADER_TYPES)
return EINVAL;
@@ -641,13 +641,14 @@ static int vrend_decode_create_query(struct vrend_decode_ctx *ctx, uint32_t hand
static int vrend_decode_create_object(struct vrend_decode_ctx *ctx, int length)
{
+ if (length < 1)
+ return EINVAL;
+
uint32_t header = get_buf_entry(ctx, VIRGL_OBJ_CREATE_HEADER);
uint32_t handle = get_buf_entry(ctx, VIRGL_OBJ_CREATE_HANDLE);
uint8_t obj_type = (header >> 8) & 0xff;
int ret = 0;
- if (length < 1)
- return EINVAL;
if (handle == 0)
return EINVAL;
@@ -691,13 +692,13 @@ static int vrend_decode_create_object(struct vrend_decode_ctx *ctx, int length)
static int vrend_decode_bind_object(struct vrend_decode_ctx *ctx, uint16_t length)
{
+ if (length != 1)
+ return EINVAL;
+
uint32_t header = get_buf_entry(ctx, VIRGL_OBJ_BIND_HEADER);
uint32_t handle = get_buf_entry(ctx, VIRGL_OBJ_BIND_HANDLE);
uint8_t obj_type = (header >> 8) & 0xff;
- if (length != 1)
- return EINVAL;
-
switch (obj_type) {
case VIRGL_OBJECT_BLEND:
vrend_object_bind_blend(ctx->grctx, handle);
@@ -720,23 +721,23 @@ static int vrend_decode_bind_object(struct vrend_decode_ctx *ctx, uint16_t lengt
static int vrend_decode_destroy_object(struct vrend_decode_ctx *ctx, int length)
{
- uint32_t handle = get_buf_entry(ctx, VIRGL_OBJ_DESTROY_HANDLE);
-
if (length != 1)
return EINVAL;
+ uint32_t handle = get_buf_entry(ctx, VIRGL_OBJ_DESTROY_HANDLE);
+
vrend_renderer_object_destroy(ctx->grctx, handle);
return 0;
}
static int vrend_decode_set_stencil_ref(struct vrend_decode_ctx *ctx, int length)
{
- struct pipe_stencil_ref ref;
- uint32_t val = get_buf_entry(ctx, VIRGL_SET_STENCIL_REF);
-
if (length != VIRGL_SET_STENCIL_REF_SIZE)
return EINVAL;
+ struct pipe_stencil_ref ref;
+ uint32_t val = get_buf_entry(ctx, VIRGL_SET_STENCIL_REF);
+
ref.ref_value[0] = val & 0xff;
ref.ref_value[1] = (val >> 8) & 0xff;
vrend_set_stencil_ref(ctx->grctx, &ref);
@@ -906,13 +907,13 @@ static int vrend_decode_blit(struct vrend_decode_ctx *ctx, int length)
static int vrend_decode_bind_sampler_states(struct vrend_decode_ctx *ctx, int length)
{
+ if (length < 2)
+ return EINVAL;
+
uint32_t shader_type = get_buf_entry(ctx, VIRGL_BIND_SAMPLER_STATES_SHADER_TYPE);
uint32_t start_slot = get_buf_entry(ctx, VIRGL_BIND_SAMPLER_STATES_START_SLOT);
uint32_t num_states = length - 2;
- if (length < 2)
- return EINVAL;
-
if (shader_type >= PIPE_SHADER_TYPES)
return EINVAL;
@@ -923,75 +924,80 @@ static int vrend_decode_bind_sampler_states(struct vrend_decode_ctx *ctx, int le
static int vrend_decode_begin_query(struct vrend_decode_ctx *ctx, int length)
{
- uint32_t handle = get_buf_entry(ctx, VIRGL_QUERY_BEGIN_HANDLE);
-
if (length != 1)
return EINVAL;
+ uint32_t handle = get_buf_entry(ctx, VIRGL_QUERY_BEGIN_HANDLE);
+
vrend_begin_query(ctx->grctx, handle);
return 0;
}
static int vrend_decode_end_query(struct vrend_decode_ctx *ctx, int length)
{
- uint32_t handle = get_buf_entry(ctx, VIRGL_QUERY_END_HANDLE);
-
if (length != 1)
return EINVAL;
+ uint32_t handle = get_buf_entry(ctx, VIRGL_QUERY_END_HANDLE);
+
vrend_end_query(ctx->grctx, handle);
return 0;
}
static int vrend_decode_get_query_result(struct vrend_decode_ctx *ctx, int length)
{
+ if (length != 2)
+ return EINVAL;
+
uint32_t handle = get_buf_entry(ctx, VIRGL_QUERY_RESULT_HANDLE);
uint32_t wait = get_buf_entry(ctx, VIRGL_QUERY_RESULT_WAIT);
- if (length != 2)
- return EINVAL;
vrend_get_query_result(ctx->grctx, handle, wait);
return 0;
}
static int vrend_decode_set_render_condition(struct vrend_decode_ctx *ctx, int length)
{
+ if (length != VIRGL_RENDER_CONDITION_SIZE)
+ return EINVAL;
+
uint32_t handle = get_buf_entry(ctx, VIRGL_RENDER_CONDITION_HANDLE);
bool condition = get_buf_entry(ctx, VIRGL_RENDER_CONDITION_CONDITION) & 1;
uint mode = get_buf_entry(ctx, VIRGL_RENDER_CONDITION_MODE);
- if (length != VIRGL_RENDER_CONDITION_SIZE)
- return EINVAL;
vrend_render_condition(ctx->grctx, handle, condition, mode);
return 0;
}
static int vrend_decode_set_sub_ctx(struct vrend_decode_ctx *ctx, int length)
{
- uint32_t ctx_sub_id = get_buf_entry(ctx, 1);
-
if (length != 1)
return EINVAL;
+
+ uint32_t ctx_sub_id = get_buf_entry(ctx, 1);
+
vrend_renderer_set_sub_ctx(ctx->grctx, ctx_sub_id);
return 0;
}
static int vrend_decode_create_sub_ctx(struct vrend_decode_ctx *ctx, int length)
{
- uint32_t ctx_sub_id = get_buf_entry(ctx, 1);
-
if (length != 1)
return EINVAL;
+
+ uint32_t ctx_sub_id = get_buf_entry(ctx, 1);
+
vrend_renderer_create_sub_ctx(ctx->grctx, ctx_sub_id);
return 0;
}
static int vrend_decode_destroy_sub_ctx(struct vrend_decode_ctx *ctx, int length)
{
- uint32_t ctx_sub_id = get_buf_entry(ctx, 1);
-
if (length != 1)
return EINVAL;
+
+ uint32_t ctx_sub_id = get_buf_entry(ctx, 1);
+
vrend_renderer_destroy_sub_ctx(ctx->grctx, ctx_sub_id);
return 0;
}