diff mbox series

[RESEND] drm/ast: Allocate initial CRTC state of the correct size

Message ID 20200129123112.11989-1-tzimmermann@suse.de (mailing list archive)
State New, archived
Headers show
Series [RESEND] drm/ast: Allocate initial CRTC state of the correct size | expand

Commit Message

Thomas Zimmermann Jan. 29, 2020, 12:31 p.m. UTC
The ast driver inherits from DRM's CRTC state, but still uses the atomic
helper for struct drm_crtc_funcs.reset, drm_atomic_helper_crtc_reset().

The helper only allocates enough memory for the core CRTC state. That
results in an out-ouf-bounds access when duplicating the initial CRTC
state. Simplified backtrace shown below:

[   21.469321] ==================================================================
[   21.469434] BUG: KASAN: slab-out-of-bounds in ast_crtc_atomic_duplicate_state+0x84/0x100 [ast]
[   21.469445] Read of size 8 at addr ffff888036c1c5f8 by task systemd-udevd/382
[   21.469451]
[   21.469464] CPU: 2 PID: 382 Comm: systemd-udevd Tainted: G            E     5.5.0-rc6-1-default+ #214
[   21.469473] Hardware name: Sun Microsystems SUN FIRE X2270 M2/SUN FIRE X2270 M2, BIOS 2.05    07/01/2010
[   21.469480] Call Trace:
[   21.469501]  dump_stack+0xb8/0x110
[   21.469528]  print_address_description.constprop.0+0x1b/0x1e0
[   21.469557]  ? ast_crtc_atomic_duplicate_state+0x84/0x100 [ast]
[   21.469581]  ? ast_crtc_atomic_duplicate_state+0x84/0x100 [ast]
[   21.469597]  __kasan_report.cold+0x1a/0x35
[   21.469640]  ? ast_crtc_atomic_duplicate_state+0x84/0x100 [ast]
[   21.469665]  kasan_report+0xe/0x20
[   21.469693]  ast_crtc_atomic_duplicate_state+0x84/0x100 [ast]
[   21.469733]  drm_atomic_get_crtc_state+0xbf/0x1c0
[   21.469768]  __drm_atomic_helper_set_config+0x81/0x5a0
[   21.469803]  ? drm_atomic_plane_check+0x690/0x690
[   21.469843]  ? drm_client_rotation+0xae/0x240
[   21.469876]  drm_client_modeset_commit_atomic+0x230/0x390
[   21.469888]  ? __mutex_lock+0x8f0/0xbe0
[   21.469929]  ? drm_client_firmware_config.isra.0+0xa60/0xa60
[   21.469948]  ? drm_client_modeset_commit_force+0x28/0x230
[   21.470031]  ? memset+0x20/0x40
[   21.470078]  drm_client_modeset_commit_force+0x90/0x230
[   21.470110]  drm_fb_helper_restore_fbdev_mode_unlocked+0x5f/0xc0
[   21.470132]  drm_fb_helper_set_par+0x59/0x70
[   21.470155]  fbcon_init+0x61d/0xad0
[   21.470185]  ? drm_fb_helper_restore_fbdev_mode_unlocked+0xc0/0xc0
[   21.470232]  visual_init+0x187/0x240
[   21.470266]  do_bind_con_driver+0x2e3/0x460
[   21.470321]  do_take_over_console+0x20a/0x290
[   21.470371]  do_fbcon_takeover+0x85/0x100
[   21.470402]  register_framebuffer+0x2fd/0x490
[   21.470425]  ? kzalloc.constprop.0+0x10/0x10
[   21.470503]  __drm_fb_helper_initial_config_and_unlock+0xf2/0x140
[   21.470533]  drm_fbdev_client_hotplug+0x162/0x250
[   21.470563]  drm_fbdev_generic_setup+0xd2/0x155
[   21.470602]  ast_driver_load+0x688/0x850 [ast]
<...>
[   21.472625] ==================================================================

Allocating enough memory for struct ast_crtc_state in a custom ast CRTC
reset handler fixes the problem.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Fixes: 83be6a3ceb11 ("drm/ast: Introduce struct ast_crtc_state")
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Dave Airlie <airlied@redhat.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: "Noralf Trønnes" <noralf@tronnes.org>
Cc: Sam Ravnborg <sam@ravnborg.org>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/ast/ast_mode.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

--
2.25.0

Comments

Daniel Vetter Jan. 29, 2020, 12:43 p.m. UTC | #1
On Wed, Jan 29, 2020 at 1:31 PM Thomas Zimmermann <tzimmermann@suse.de> wrote:
>
> The ast driver inherits from DRM's CRTC state, but still uses the atomic
> helper for struct drm_crtc_funcs.reset, drm_atomic_helper_crtc_reset().
>
> The helper only allocates enough memory for the core CRTC state. That
> results in an out-ouf-bounds access when duplicating the initial CRTC
> state. Simplified backtrace shown below:
>
> [   21.469321] ==================================================================
> [   21.469434] BUG: KASAN: slab-out-of-bounds in ast_crtc_atomic_duplicate_state+0x84/0x100 [ast]
> [   21.469445] Read of size 8 at addr ffff888036c1c5f8 by task systemd-udevd/382
> [   21.469451]
> [   21.469464] CPU: 2 PID: 382 Comm: systemd-udevd Tainted: G            E     5.5.0-rc6-1-default+ #214
> [   21.469473] Hardware name: Sun Microsystems SUN FIRE X2270 M2/SUN FIRE X2270 M2, BIOS 2.05    07/01/2010
> [   21.469480] Call Trace:
> [   21.469501]  dump_stack+0xb8/0x110
> [   21.469528]  print_address_description.constprop.0+0x1b/0x1e0
> [   21.469557]  ? ast_crtc_atomic_duplicate_state+0x84/0x100 [ast]
> [   21.469581]  ? ast_crtc_atomic_duplicate_state+0x84/0x100 [ast]
> [   21.469597]  __kasan_report.cold+0x1a/0x35
> [   21.469640]  ? ast_crtc_atomic_duplicate_state+0x84/0x100 [ast]
> [   21.469665]  kasan_report+0xe/0x20
> [   21.469693]  ast_crtc_atomic_duplicate_state+0x84/0x100 [ast]
> [   21.469733]  drm_atomic_get_crtc_state+0xbf/0x1c0
> [   21.469768]  __drm_atomic_helper_set_config+0x81/0x5a0
> [   21.469803]  ? drm_atomic_plane_check+0x690/0x690
> [   21.469843]  ? drm_client_rotation+0xae/0x240
> [   21.469876]  drm_client_modeset_commit_atomic+0x230/0x390
> [   21.469888]  ? __mutex_lock+0x8f0/0xbe0
> [   21.469929]  ? drm_client_firmware_config.isra.0+0xa60/0xa60
> [   21.469948]  ? drm_client_modeset_commit_force+0x28/0x230
> [   21.470031]  ? memset+0x20/0x40
> [   21.470078]  drm_client_modeset_commit_force+0x90/0x230
> [   21.470110]  drm_fb_helper_restore_fbdev_mode_unlocked+0x5f/0xc0
> [   21.470132]  drm_fb_helper_set_par+0x59/0x70
> [   21.470155]  fbcon_init+0x61d/0xad0
> [   21.470185]  ? drm_fb_helper_restore_fbdev_mode_unlocked+0xc0/0xc0
> [   21.470232]  visual_init+0x187/0x240
> [   21.470266]  do_bind_con_driver+0x2e3/0x460
> [   21.470321]  do_take_over_console+0x20a/0x290
> [   21.470371]  do_fbcon_takeover+0x85/0x100
> [   21.470402]  register_framebuffer+0x2fd/0x490
> [   21.470425]  ? kzalloc.constprop.0+0x10/0x10
> [   21.470503]  __drm_fb_helper_initial_config_and_unlock+0xf2/0x140
> [   21.470533]  drm_fbdev_client_hotplug+0x162/0x250
> [   21.470563]  drm_fbdev_generic_setup+0xd2/0x155
> [   21.470602]  ast_driver_load+0x688/0x850 [ast]
> <...>
> [   21.472625] ==================================================================
>
> Allocating enough memory for struct ast_crtc_state in a custom ast CRTC
> reset handler fixes the problem.
>
> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
> Fixes: 83be6a3ceb11 ("drm/ast: Introduce struct ast_crtc_state")
> Cc: Gerd Hoffmann <kraxel@redhat.com>
> Cc: Dave Airlie <airlied@redhat.com>
> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> Cc: Alex Deucher <alexander.deucher@amd.com>
> Cc: "Noralf Trønnes" <noralf@tronnes.org>
> Cc: Sam Ravnborg <sam@ravnborg.org>
> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/gpu/drm/ast/ast_mode.c | 19 ++++++++++++++++++-
>  1 file changed, 18 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
> index 34608f0499eb..b5a0e2a0595b 100644
> --- a/drivers/gpu/drm/ast/ast_mode.c
> +++ b/drivers/gpu/drm/ast/ast_mode.c
> @@ -882,6 +882,23 @@ static const struct drm_crtc_helper_funcs ast_crtc_helper_funcs = {
>         .atomic_disable = ast_crtc_helper_atomic_disable,
>  };
>
> +static void ast_crtc_reset(struct drm_crtc *crtc)
> +{
> +       struct ast_crtc_state *ast_state;
> +
> +       if (crtc->state) {
> +               crtc->funcs->atomic_destroy_state(crtc, crtc->state);
> +               crtc->state = NULL;
> +       }
> +
> +       ast_state = kzalloc(sizeof(*ast_state), GFP_KERNEL);
> +       if (!ast_state)
> +               return;
> +
> +       crtc->state = &ast_state->base;
> +       crtc->state->crtc = crtc;
> +}

Please model this after drm_atomic_helper_crtc_reset and call
__drm_atomic_helper_crtc_reset at the bottom. It's just tw lines of
shared code you're saving, but not using these helpers has cost us in
the past. With that:

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

> +
>  static void ast_crtc_destroy(struct drm_crtc *crtc)
>  {
>         drm_crtc_cleanup(crtc);
> @@ -920,7 +937,7 @@ static void ast_crtc_atomic_destroy_state(struct drm_crtc *crtc,
>  }
>
>  static const struct drm_crtc_funcs ast_crtc_funcs = {
> -       .reset = drm_atomic_helper_crtc_reset,
> +       .reset = ast_crtc_reset,
>         .set_config = drm_crtc_helper_set_config,
>         .gamma_set = drm_atomic_helper_legacy_gamma_set,
>         .destroy = ast_crtc_destroy,
> --
> 2.25.0
>
diff mbox series

Patch

diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
index 34608f0499eb..b5a0e2a0595b 100644
--- a/drivers/gpu/drm/ast/ast_mode.c
+++ b/drivers/gpu/drm/ast/ast_mode.c
@@ -882,6 +882,23 @@  static const struct drm_crtc_helper_funcs ast_crtc_helper_funcs = {
 	.atomic_disable = ast_crtc_helper_atomic_disable,
 };

+static void ast_crtc_reset(struct drm_crtc *crtc)
+{
+	struct ast_crtc_state *ast_state;
+
+	if (crtc->state) {
+		crtc->funcs->atomic_destroy_state(crtc, crtc->state);
+		crtc->state = NULL;
+	}
+
+	ast_state = kzalloc(sizeof(*ast_state), GFP_KERNEL);
+	if (!ast_state)
+		return;
+
+	crtc->state = &ast_state->base;
+	crtc->state->crtc = crtc;
+}
+
 static void ast_crtc_destroy(struct drm_crtc *crtc)
 {
 	drm_crtc_cleanup(crtc);
@@ -920,7 +937,7 @@  static void ast_crtc_atomic_destroy_state(struct drm_crtc *crtc,
 }

 static const struct drm_crtc_funcs ast_crtc_funcs = {
-	.reset = drm_atomic_helper_crtc_reset,
+	.reset = ast_crtc_reset,
 	.set_config = drm_crtc_helper_set_config,
 	.gamma_set = drm_atomic_helper_legacy_gamma_set,
 	.destroy = ast_crtc_destroy,