vkr: validate ring variable memory regions as unique

Ensure all ring control member variables have their own storage during
ring creation. Member address re-use would otherwise result in undefined
behavior.

Signed-off-by: Ryan Neph <ryanneph@google.com>
Reviewed-by: Chia-I Wu <olvaffe@gmail.com>
macos/master
Ryan Neph 3 years ago
parent fe251d992d
commit 8417c2413d
  1. 51
      src/venus/vkr_transport.c

@ -155,20 +155,49 @@ lookup_ring(struct vkr_context *ctx, uint64_t ring_id)
static bool static bool
validate_ring_layout(const struct vkr_ring_layout *layout, size_t buf_size) validate_ring_layout(const struct vkr_ring_layout *layout, size_t buf_size)
{ {
if (layout->head.offset > buf_size || layout->tail.offset > buf_size || if (!layout->buffer.size || !util_is_power_of_two(layout->buffer.size)) {
layout->status.offset > buf_size || layout->buffer.offset > buf_size || vkr_log("ring buffer size (%lu) must be a power of two",
layout->extra.offset > buf_size) layout->buffer.size);
return false; return false;
}
if (sizeof(uint32_t) > buf_size - layout->head.offset || const struct memory_region *regions[] = {
sizeof(uint32_t) > buf_size - layout->tail.offset || &layout->head,
sizeof(uint32_t) > buf_size - layout->status.offset || &layout->tail,
layout->buffer.size > buf_size - layout->buffer.offset || &layout->status,
layout->extra.size > buf_size - layout->extra.offset) &layout->buffer,
return false; &layout->extra,
};
if (!layout->buffer.size || !util_is_power_of_two(layout->buffer.size)) for (size_t i = 0; i < ARRAY_SIZE(regions); i++) {
return false; if (regions[i]->offset > buf_size ||
regions[i]->size > buf_size - regions[i]->offset) {
vkr_log("ring buffer control variable (offset=%lu, size=%lu) placed"
" out-of-bounds in shared memory layout",
regions[i]->offset, regions[i]->size);
return false;
}
}
/* assumes region->size == 0 is valid */
for (size_t i = 0; i < ARRAY_SIZE(regions); i++) {
if (!regions[i]->size)
continue;
for (size_t j = i + 1; j < ARRAY_SIZE(regions); j++) {
if (!regions[j]->size)
continue;
if (regions[i]->offset < regions[j]->offset + regions[j]->size &&
regions[j]->offset < regions[i]->offset + regions[i]->size) {
vkr_log("ring buffer control variable (offset=%lu, size=%lu)"
" overlaps with control variable (offset=%lu, size=%lu)",
regions[j]->offset, regions[j]->size, regions[i]->offset,
regions[i]->size);
return false;
}
}
}
return true; return true;
} }

Loading…
Cancel
Save