diff options
author | Marc-André Lureau <marcandre.lureau@redhat.com> | 2016-02-04 08:36:40 +0100 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2016-02-10 12:39:48 +1000 |
commit | b93e67deb0693d6af58fb01ea6c08712cee8b630 (patch) | |
tree | ab7324c1e31fdd050d117e869f1eacc99e1ff85e | |
parent | 7febc0023bf65dcb2ef5e2da006c88d0d2f689d7 (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.c | 72 |
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; } |