On 2026. július 15., szerda 13:10:51 közép-európai nyári idő sashiko-
[email protected] wrote:
> Thank you for your contribution! Sashiko AI review found 3 potential
> issue(s) to consider: - [High] Uninitialized variable `block_size_log2` in
> GFX6 modifier path causes undefined behavior and potential kernel panic. -
> [High] User-controlled `PIPE_CONFIG` in GFX6 modifier can trigger
> `unreachable()`, leading to kernel panic or undefined behavior. - [Medium]
> Unbounded `drm_err()` on invalid GFX6 array mode allows userspace to flood
> the kernel log. --
> 
> --- Patch [2]: [PATCH 2/4] drm/amdgpu: Convert tiling flags to modifiers on
> GFX6-8 --- commit 642125971654c581668fe700356dfbee6905eccc
> Author: Timur Kristóf <[email protected]>
> Subject: drm/amdgpu: Convert tiling flags to modifiers on GFX6-8
> 
> This commit converts the tiling flags to modifiers on GFX8 and older,
> so that the DC display driver can rely on them like on newer generations.
> 
> > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
> > b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index
> > 950937b363fbe..dcca930ed3c04 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
> 
> [ ... ]
> 
> > @@ -940,6 +940,55 @@ static int convert_tiling_flags_to_modifier(struct
> > amdgpu_framebuffer *afb)> 
> >     return 0;
> >  
> >  }
> > 
> > +static int convert_tiling_flags_to_modifier_gfx6(struct
> > amdgpu_framebuffer *afb) +{
> > +   const uint32_t array_mode = AMDGPU_TILING_GET(afb->tiling_flags,
> > ARRAY_MODE); +      const uint32_t pipe_config =
> > AMDGPU_TILING_GET(afb->tiling_flags, PIPE_CONFIG);
> [ ... ]
> 
> > +   switch (array_mode) {
> > +   case DC_ARRAY_LINEAR_GENERAL:
> > +   case DC_ARRAY_LINEAR_ALLIGNED:
> > +           modifier = DRM_FORMAT_MOD_LINEAR;
> > +           break;
> > +
> > +   case DC_ARRAY_2D_TILED_THIN1:
> > +           /* Macro tiled modes only */
> > +           modifier |=
> > +                   AMD_FMT_MOD_SET(PIPE_CONFIG, pipe_config) |
> > +                   AMD_FMT_MOD_SET(TILE_SPLIT, tile_split) |
> > +                   AMD_FMT_MOD_SET(BANK_WIDTH, bank_width) |
> > +                   AMD_FMT_MOD_SET(BANK_HEIGHT, bank_height) |
> > +                   AMD_FMT_MOD_SET(MACRO_TILE_ASPECT, 
macro_tile_aspect) |
> > +                   AMD_FMT_MOD_SET(NUM_BANKS, num_banks);
> > +           fallthrough;
> > +
> > +   case DC_ARRAY_1D_TILED_THIN1:
> > +           /* Micro and macro tiled modes */
> > +           modifier |=
> > +                   AMD_FMT_MOD |
> > +                   AMD_FMT_MOD_SET(TILE_VERSION, 
AMD_FMT_MOD_TILE_VER_GFX6) |
> > +                   AMD_FMT_MOD_SET(TILE, array_mode) |
> > +                   AMD_FMT_MOD_SET(MICROTILE, micro_tile_mode);
> > +           break;
> > +
> > +   default:
> > +           drm_err(&adev->ddev, "array mode 0x%x not supported by 
DCE\n",
> > array_mode);
> [Severity: Medium]
> Could this drm_err() be triggered repeatedly by a user space process
> providing an invalid array_mode to DRM_IOCTL_MODE_ADDFB2, flooding the
> kernel log?
> 
> Should this use a rate-limited print or drm_dbg_kms() instead to prevent log
> spam from unprivileged users?

I will just change this to drm_dbg_kms()

> 
> > +           return -EINVAL;
> > +   }
> > +
> > +   afb->base.modifier = modifier;
> > +   afb->base.flags |= DRM_MODE_FB_MODIFIERS;
> > +   return 0;
> > +}
> 
> [ ... ]
> 
> > @@ -1093,7 +1142,7 @@ static int amdgpu_display_verify_sizes(struct
> > amdgpu_framebuffer *rfb)> 
> >                     get_block_dimensions(block_size_log2, 
format_info->cpp[i],
> >                     
> >                                          &block_width, 
&block_height);
> > 
> > -           } else {
> > +           } else if (AMD_FMT_MOD_GET(TILE_VERSION, modifier) >=
> > AMD_FMT_MOD_TILE_VER_GFX9) {> 
> >                     int swizzle = AMD_FMT_MOD_GET(TILE, 
modifier);
> >                     
> >                     switch ((swizzle & ~3) + 1) {
> > 
> > @@ -1120,6 +1169,60 @@ static int amdgpu_display_verify_sizes(struct
> > amdgpu_framebuffer *rfb)> 
> >                     get_block_dimensions(block_size_log2, 
format_info->cpp[i],
> >                     
> >                                          &block_width, 
&block_height);
> > 
> > +           } else if (AMD_FMT_MOD_GET(TILE_VERSION, modifier) ==
> > AMD_FMT_MOD_TILE_VER_GFX6) { +                      const u32 
display_micro_tile_pitch = 32;
> > /* required by DCE */ +                     const u32 
micro_tile_width = 8;
> > +                   const u32 micro_tile_height = 8;
> > +                   const u32 micro_tile_mode = 
AMD_FMT_MOD_GET(MICROTILE, modifier);
> > +                   const u32 array_mode = AMD_FMT_MOD_GET(TILE, 
modifier);
> > +                   u32 num_banks, bank_width, bank_height, 
pipe_config,
> > macro_tile_aspect;
> > +                   u32 num_pipes;
> > +
> > +                   if (AMD_FMT_MOD_GET(DCC, modifier)) {
> > +                           drm_dbg_kms(rfb->base.dev, "DCC 
is not displayable on GFX6-8\n");
> > +                           return -EINVAL;
> > +                   }
> > +                   if (array_mode != 
AMD_FMT_MOD_TILE_GFX6_1D_TILED_THIN1 &&
> > +                       array_mode != 
AMD_FMT_MOD_TILE_GFX6_2D_TILED_THIN1) {
> > +                           drm_dbg_kms(rfb->base.dev,
> > +                                   "Array mode %u is not 
supported by the display driver\n",
> > +                                   array_mode);
> > +                           return -EINVAL;
> > +                   }
> > +                   if (micro_tile_mode != 
AMD_FMT_MOD_MICROTILE_DISPLAY) {
> > +                           drm_dbg_kms(rfb->base.dev,
> > +                                   "Micro tile mode %u is 
not displayable on GFX6-8\n",
> > +                                   micro_tile_mode);
> > +                           return -EINVAL;
> > +                   }
> > +
> > +                   num_banks = 2 << AMD_FMT_MOD_GET(NUM_BANKS, 
modifier);
> > +                   bank_width = 1 << 
AMD_FMT_MOD_GET(BANK_WIDTH, modifier);
> > +                   bank_height = 1 << 
AMD_FMT_MOD_GET(BANK_HEIGHT, modifier);
> > +                   pipe_config = AMD_FMT_MOD_GET(PIPE_CONFIG, 
modifier);
> > +                   macro_tile_aspect = 1 << 
AMD_FMT_MOD_GET(MACRO_TILE_ASPECT, modifier);
> > +
> > +                   if (pipe_config >= 
AMD_FMT_MOD_PIPE_CONFIG_P16_32x32_8x16)
> > +                           num_pipes = 16;
> > +                   else if (pipe_config >= 
AMD_FMT_MOD_PIPE_CONFIG_P8_16x16_8x16)
> > +                           num_pipes = 8;
> > +                   else if (pipe_config >= 
AMD_FMT_MOD_PIPE_CONFIG_P4_8x16)
> > +                           num_pipes = 4;
> > +                   else if (pipe_config == 
AMD_FMT_MOD_PIPE_CONFIG_P2)
> > +                           num_pipes = 2;
> > +                   else
> > +                           unreachable();
> 
> [Severity: High]
> Since pipe_config comes from AMD_FMT_MOD_GET(PIPE_CONFIG, modifier), which
> is user-controlled via the framebuffer modifier, could a user pass a value
> smaller than AMD_FMT_MOD_PIPE_CONFIG_P2?
> 
> If so, hitting unreachable() here would result in undefined compiler
> behavior. With CONFIG_OBJTOOL enabled, it can emit an invalid instruction
> that immediately panics the kernel. If execution falls through, num_pipes
> remains uninitialized and is subsequently used in a multiplication.

I will replace unreachable() with "return -EINVAL"

> 
> > +
> > +                   if (array_mode < 
AMD_FMT_MOD_TILE_GFX6_2D_TILED_THIN1) {
> > +                           block_width = 
display_micro_tile_pitch;
> > +                           block_height = micro_tile_height;
> > +                   } else {
> > +                           /* Assume non-PRT macro tiling 
modes */
> > +                           block_width = num_pipes * 
micro_tile_width *
> > +                                         bank_width * 
macro_tile_aspect;
> > +                           block_height = micro_tile_height 
* bank_height *
> > +                                          num_banks / 
macro_tile_aspect;
> > +                   }
> > 
> >             }
> >             
> >             ret = amdgpu_display_verify_plane(rfb, i, format_info,
> >             
> >                                               
block_width, block_height, block_size_log2);
> 
> [Severity: High]
> Does this pass an uninitialized block_size_log2 into
> amdgpu_display_verify_plane()?

I will fix that, thanks for noticing.



Reply via email to