mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-21 20:10:14 +01:00
radeonsi: Check pitch and offset for validity.
And lack of overflows, which should help for security. Reviewed-by: Marek Olšák <marek.olsak@amd.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6176>
This commit is contained in:
parent
395dac7bf9
commit
f7a4051b83
3 changed files with 72 additions and 7 deletions
|
|
@ -2446,6 +2446,10 @@ void ac_surface_zero_dcc_fields(struct radeon_surf *surf)
|
||||||
{
|
{
|
||||||
surf->dcc_offset = 0;
|
surf->dcc_offset = 0;
|
||||||
surf->display_dcc_offset = 0;
|
surf->display_dcc_offset = 0;
|
||||||
|
if (!surf->htile_offset && !surf->fmask_offset && !surf->cmask_offset) {
|
||||||
|
surf->total_size = surf->surf_size;
|
||||||
|
surf->alignment = surf->surf_alignment;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned eg_tile_split(unsigned tile_split)
|
static unsigned eg_tile_split(unsigned tile_split)
|
||||||
|
|
@ -2744,21 +2748,69 @@ void ac_surface_get_umd_metadata(const struct radeon_info *info, struct radeon_s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ac_surface_override_offset_stride(const struct radeon_info *info, struct radeon_surf *surf,
|
static uint32_t ac_surface_get_gfx9_pitch_align(struct radeon_surf *surf)
|
||||||
|
{
|
||||||
|
if (surf->u.gfx9.surf.swizzle_mode == ADDR_SW_LINEAR)
|
||||||
|
return 256 / surf->bpe;
|
||||||
|
|
||||||
|
if (surf->u.gfx9.resource_type == RADEON_RESOURCE_3D)
|
||||||
|
return 1; /* TODO */
|
||||||
|
|
||||||
|
unsigned bpe_shift = util_logbase2(surf->bpe) / 2;
|
||||||
|
switch(surf->u.gfx9.surf.swizzle_mode & ~3) {
|
||||||
|
case ADDR_SW_LINEAR: /* 256B block. */
|
||||||
|
return 16 >> bpe_shift;
|
||||||
|
case ADDR_SW_4KB_Z:
|
||||||
|
case ADDR_SW_4KB_Z_X:
|
||||||
|
return 64 >> bpe_shift;
|
||||||
|
case ADDR_SW_64KB_Z:
|
||||||
|
case ADDR_SW_64KB_Z_T:
|
||||||
|
case ADDR_SW_64KB_Z_X:
|
||||||
|
return 256 >> bpe_shift;
|
||||||
|
case ADDR_SW_VAR_Z_X:
|
||||||
|
default:
|
||||||
|
return 1; /* TODO */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ac_surface_override_offset_stride(const struct radeon_info *info, struct radeon_surf *surf,
|
||||||
unsigned num_mipmap_levels, uint64_t offset, unsigned pitch)
|
unsigned num_mipmap_levels, uint64_t offset, unsigned pitch)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* GFX10 and newer don't support custom strides. Furthermore, for
|
||||||
|
* multiple miplevels or compression data we'd really need to rerun
|
||||||
|
* addrlib to update all the fields in the surface. That, however, is a
|
||||||
|
* software limitation and could be relaxed later.
|
||||||
|
*/
|
||||||
|
bool require_equal_pitch = surf->surf_size != surf->total_size ||
|
||||||
|
num_mipmap_levels != 1 ||
|
||||||
|
info->chip_class >= GFX10;
|
||||||
|
|
||||||
if (info->chip_class >= GFX9) {
|
if (info->chip_class >= GFX9) {
|
||||||
if (pitch) {
|
if (pitch) {
|
||||||
surf->u.gfx9.surf_pitch = pitch;
|
if (surf->u.gfx9.surf_pitch != pitch && require_equal_pitch)
|
||||||
if (num_mipmap_levels == 1)
|
return false;
|
||||||
|
|
||||||
|
if ((ac_surface_get_gfx9_pitch_align(surf) - 1) & pitch)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (pitch != surf->u.gfx9.surf_pitch) {
|
||||||
|
unsigned slices = surf->surf_size / surf->u.gfx9.surf_slice_size;
|
||||||
|
|
||||||
|
surf->u.gfx9.surf_pitch = pitch;
|
||||||
surf->u.gfx9.surf.epitch = pitch - 1;
|
surf->u.gfx9.surf.epitch = pitch - 1;
|
||||||
surf->u.gfx9.surf_slice_size = (uint64_t)pitch * surf->u.gfx9.surf_height * surf->bpe;
|
surf->u.gfx9.surf_slice_size = (uint64_t)pitch * surf->u.gfx9.surf_height * surf->bpe;
|
||||||
|
surf->total_size = surf->surf_size = surf->u.gfx9.surf_slice_size * slices;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
surf->u.gfx9.surf_offset = offset;
|
surf->u.gfx9.surf_offset = offset;
|
||||||
if (surf->u.gfx9.stencil_offset)
|
if (surf->u.gfx9.stencil_offset)
|
||||||
surf->u.gfx9.stencil_offset += offset;
|
surf->u.gfx9.stencil_offset += offset;
|
||||||
} else {
|
} else {
|
||||||
if (pitch) {
|
if (pitch) {
|
||||||
|
if (surf->u.legacy.level[0].nblk_x != pitch && require_equal_pitch)
|
||||||
|
return false;
|
||||||
|
|
||||||
surf->u.legacy.level[0].nblk_x = pitch;
|
surf->u.legacy.level[0].nblk_x = pitch;
|
||||||
surf->u.legacy.level[0].slice_size_dw =
|
surf->u.legacy.level[0].slice_size_dw =
|
||||||
((uint64_t)pitch * surf->u.legacy.level[0].nblk_y * surf->bpe) / 4;
|
((uint64_t)pitch * surf->u.legacy.level[0].nblk_y * surf->bpe) / 4;
|
||||||
|
|
@ -2770,6 +2822,10 @@ void ac_surface_override_offset_stride(const struct radeon_info *info, struct ra
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (offset & (surf->alignment - 1) ||
|
||||||
|
offset >= UINT64_MAX - surf->total_size)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (surf->htile_offset)
|
if (surf->htile_offset)
|
||||||
surf->htile_offset += offset;
|
surf->htile_offset += offset;
|
||||||
if (surf->fmask_offset)
|
if (surf->fmask_offset)
|
||||||
|
|
@ -2780,6 +2836,7 @@ void ac_surface_override_offset_stride(const struct radeon_info *info, struct ra
|
||||||
surf->dcc_offset += offset;
|
surf->dcc_offset += offset;
|
||||||
if (surf->display_dcc_offset)
|
if (surf->display_dcc_offset)
|
||||||
surf->display_dcc_offset += offset;
|
surf->display_dcc_offset += offset;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned ac_surface_get_nplanes(const struct radeon_surf *surf)
|
unsigned ac_surface_get_nplanes(const struct radeon_surf *surf)
|
||||||
|
|
|
||||||
|
|
@ -318,7 +318,7 @@ void ac_surface_get_umd_metadata(const struct radeon_info *info, struct radeon_s
|
||||||
unsigned num_mipmap_levels, uint32_t desc[8],
|
unsigned num_mipmap_levels, uint32_t desc[8],
|
||||||
unsigned *size_metadata, uint32_t metadata[64]);
|
unsigned *size_metadata, uint32_t metadata[64]);
|
||||||
|
|
||||||
void ac_surface_override_offset_stride(const struct radeon_info *info, struct radeon_surf *surf,
|
bool ac_surface_override_offset_stride(const struct radeon_info *info, struct radeon_surf *surf,
|
||||||
unsigned num_mipmap_levels, uint64_t offset, unsigned pitch);
|
unsigned num_mipmap_levels, uint64_t offset, unsigned pitch);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1035,9 +1035,10 @@ static struct si_texture *si_texture_create_object(struct pipe_screen *screen,
|
||||||
*/
|
*/
|
||||||
tex->ps_draw_ratio = 0;
|
tex->ps_draw_ratio = 0;
|
||||||
|
|
||||||
ac_surface_override_offset_stride(&sscreen->info, &tex->surface,
|
if (!ac_surface_override_offset_stride(&sscreen->info, &tex->surface,
|
||||||
tex->buffer.b.b.last_level + 1,
|
tex->buffer.b.b.last_level + 1,
|
||||||
offset, pitch_in_bytes / tex->surface.bpe);
|
offset, pitch_in_bytes / tex->surface.bpe))
|
||||||
|
goto error;
|
||||||
|
|
||||||
if (tex->is_depth) {
|
if (tex->is_depth) {
|
||||||
if (sscreen->info.chip_class >= GFX9) {
|
if (sscreen->info.chip_class >= GFX9) {
|
||||||
|
|
@ -1463,6 +1464,13 @@ static struct pipe_resource *si_texture_from_winsys_buffer(struct si_screen *ssc
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ac_surface_get_plane_offset(sscreen->info.chip_class, &tex->surface, 0, 0) +
|
||||||
|
tex->surface.total_size > buf->size ||
|
||||||
|
buf->alignment < tex->surface.alignment) {
|
||||||
|
si_texture_reference(&tex, NULL);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Displayable DCC requires an explicit flush. */
|
/* Displayable DCC requires an explicit flush. */
|
||||||
if (dedicated && offset == 0 && !(usage & PIPE_HANDLE_USAGE_EXPLICIT_FLUSH) &&
|
if (dedicated && offset == 0 && !(usage & PIPE_HANDLE_USAGE_EXPLICIT_FLUSH) &&
|
||||||
si_has_displayable_dcc(tex)) {
|
si_has_displayable_dcc(tex)) {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue