vtest: Don't read past the iovec

Signed-off-by: Dave Airlie <airlied@redhat.com>
macos/master
Jakob Bornecrantz 6 years ago committed by Dave Airlie
parent fdcb5b588c
commit fed5d2d2d8
  1. 43
      vtest/vtest_renderer.c

@ -77,6 +77,16 @@ __failed_call(const char* func, const char *called, int ret)
#define report_failed_call(called, ret) \ #define report_failed_call(called, ret) \
__failed_call(__FUNCTION__, called, ret) __failed_call(__FUNCTION__, called, ret)
static int
__failure(const char* func, const char *reason, int ret)
{
fprintf(stderr, "%s %s (%d)\n", func, reason, ret);
return ret;
}
#define report_failure(reason, ret) \
__failure(__FUNCTION__, reason, ret)
static unsigned static unsigned
hash_func(void *key) hash_func(void *key)
{ {
@ -119,6 +129,21 @@ static int vtest_block_write(int fd, void *buf, int size)
return size; return size;
} }
static int vtest_block_write_zero(int fd, int size)
{
char zero[256] = {0};
int left;
int ret;
left = size;
do {
ret = write(fd, zero, MIN2(left, 256));
if (ret < 0)
return -errno;
left -= ret;
} while (left);
return size;
}
int vtest_block_read(int fd, void *buf, int size) int vtest_block_read(int fd, void *buf, int size)
{ {
void *ptr = buf; void *ptr = buf;
@ -559,6 +584,7 @@ int vtest_transfer_get2(void)
struct virgl_box box; struct virgl_box box;
uint32_t data_size; uint32_t data_size;
uint32_t offset; uint32_t offset;
uint32_t extra_data = 0;
struct iovec *iovec; struct iovec *iovec;
ret = vtest_block_read(renderer.in_fd, thdr_buf, sizeof(thdr_buf)); ret = vtest_block_read(renderer.in_fd, thdr_buf, sizeof(thdr_buf));
@ -573,6 +599,10 @@ int vtest_transfer_get2(void)
return report_failed_call("util_hash_table_get", -ESRCH); return report_failed_call("util_hash_table_get", -ESRCH);
} }
if (offset >= iovec->iov_len) {
return report_failure("offset larger then length of backing store", -EFAULT);
}
ret = virgl_renderer_transfer_read_iov(handle, ret = virgl_renderer_transfer_read_iov(handle,
ctx_id, ctx_id,
level, level,
@ -585,6 +615,12 @@ int vtest_transfer_get2(void)
return report_failed_call("virgl_renderer_transfer_read_iov", ret); return report_failed_call("virgl_renderer_transfer_read_iov", ret);
} }
/* Make sure we don't read out of bounds. */
if (data_size > (iovec->iov_len - offset)) {
extra_data = data_size - (iovec->iov_len - offset);
data_size -= extra_data;
}
ret = vtest_block_write(renderer.out_fd, ret = vtest_block_write(renderer.out_fd,
iovec->iov_base + offset, iovec->iov_base + offset,
data_size); data_size);
@ -592,6 +628,13 @@ int vtest_transfer_get2(void)
return report_failed_call("vtest_block_write", ret); return report_failed_call("vtest_block_write", ret);
} }
if (extra_data) {
ret = vtest_block_write_zero(renderer.out_fd, extra_data);
if (ret < 0) {
return report_failed_call("vtest_block_write_zero", ret);
}
}
return ret < 0 ? ret : 0; return ret < 0 ? ret : 0;
} }

Loading…
Cancel
Save