amlogic: drm/meson: Fix plane state out-of-bounds access 60/251560/1
authorSeung-Woo Kim <sw0312.kim@samsung.com>
Fri, 15 Jan 2021 04:41:36 +0000 (13:41 +0900)
committerSeung-Woo Kim <sw0312.kim@samsung.com>
Fri, 15 Jan 2021 05:14:50 +0000 (14:14 +0900)
For drm_plane_funcs callbacks, it was fixed to use meson specific
functions except reset callback. Not like other meson specific
callbacks, reset callback allocates drm_plane_state, so accessing
meson_plane_state from drm_plane state in other callbacks causes
out-of-bounds access. Fix plane state out-of-bounds access by using
meson specific reset callback using meson_plane_state based on
drm_atomic_helper_plane_reset().

This removes below kasan warning:
   BUG: KASAN: slab-out-of-bounds in kmemdup+0x4c/0xb0
   Read of size 128 at addr ffffffc005a710c0 by task enlightenment/4376
   ...
   [<ffffff90093959ec>] kmemdup+0x4c/0xb0
   [<ffffff900a7714e8>] meson_plane_duplicate_state+0x40/0x90
   [<ffffff9009d406d4>] drm_atomic_get_plane_state+0xc4/0x230
   [<ffffff9009cf6284>] __drm_atomic_helper_set_config+0xdc/0x788
   [<ffffff9009cf6a0c>] drm_atomic_helper_set_config+0xdc/0x178
   [<ffffff900a775df8>] meson_crtc_set_mode+0x40/0x68
   [<ffffff9009d22d54>] drm_mode_set_config_internal+0xf4/0x348
   [<ffffff9009d249ec>] drm_mode_setcrtc+0x1d4/0x910
   ...

   Allocated by task 1:
   ...
    kmem_cache_alloc_trace+0x20c/0x6c8
    drm_atomic_helper_plane_reset+0x6c/0xc8
    drm_mode_config_reset+0x7c/0x310
    am_meson_drm_bind+0x1fc/0x2f8
    try_to_bring_up_master.part.1+0x70/0x128
    component_master_add_with_match+0x1b8/0x230
    am_meson_drv_probe+0x3c8/0x410
   ...

Change-Id: Ie7bfd41d797a0782cffa45801629981c25b01561
Fixes commit 1f1efcfdd85d ("drm: add multi-layer support [1/1]")
Signed-off-by: Seung-Woo Kim <sw0312.kim@samsung.com>
drivers/amlogic/drm/meson_plane.c

index c7a2d07..08270f1 100644 (file)
@@ -292,6 +292,27 @@ meson_plane_duplicate_state(struct drm_plane *plane)
        return &meson_plane_state->base;
 }
 
+static void meson_plane_reset(struct drm_plane *plane)
+{
+       struct am_meson_plane_state *meson_plane_state;
+
+       if (plane->state) {
+               __drm_atomic_helper_plane_destroy_state(plane->state);
+
+               meson_plane_state = to_am_meson_plane_state(plane->state);
+               kfree(meson_plane_state);
+               plane->state = NULL;
+       }
+
+       meson_plane_state = kzalloc(sizeof(*meson_plane_state), GFP_KERNEL);
+
+       if (meson_plane_state) {
+               plane->state = &meson_plane_state->base;
+               plane->state->plane = plane;
+               plane->state->rotation = DRM_ROTATE_0;
+       }
+}
+
 static void meson_plane_destroy_state(struct drm_plane *plane,
                                           struct drm_plane_state *state)
 {
@@ -336,7 +357,7 @@ static const struct drm_plane_funcs am_osd_plane_funs = {
        .update_plane           = drm_atomic_helper_update_plane,
        .disable_plane          = drm_atomic_helper_disable_plane,
        .destroy                = drm_plane_cleanup,
-       .reset                  = drm_atomic_helper_plane_reset,
+       .reset                  = meson_plane_reset,
        .atomic_duplicate_state = meson_plane_duplicate_state,
        .atomic_destroy_state   = meson_plane_destroy_state,
        .atomic_set_property = meson_plane_atomic_set_property,