drm: Don't free a struct never allocated by drm_gem_fb_init()
authorAndrzej Pietrasiewicz <andrzej.p@collabora.com>
Wed, 15 Apr 2020 17:20:24 +0000 (19:20 +0200)
committerAndrzej Pietrasiewicz <andrzej.p@collabora.com>
Thu, 16 Apr 2020 11:44:29 +0000 (13:44 +0200)
drm_gem_fb_init() is passed the fb and never allocates it, so it should be
not the one freeing it. As it is now the second call to kfree() is possible
with the same fb. Coverity reported the following:

*** CID 1492613:  Memory - corruptions  (USE_AFTER_FREE)
/drivers/gpu/drm/drm_gem_framebuffer_helper.c: 230 in drm_gem_fb_create_with_funcs()
224      fb = kzalloc(sizeof(*fb), GFP_KERNEL);
225      if (!fb)
226      return ERR_PTR(-ENOMEM);
227
228      ret = drm_gem_fb_init_with_funcs(dev, fb, file, mode_cmd, funcs);
229      if (ret) {
vvv     CID 1492613:  Memory - corruptions  (USE_AFTER_FREE)
vvv     Calling "kfree" frees pointer "fb" which has already been freed. [Note: The source code implementation of the function has been overridden by a user model.]
230      kfree(fb);
231      return ERR_PTR(ret);
232      }
233
234      return fb;
235     }

drm_gem_fb_init_with_funcs() calls drm_gem_fb_init()
drm_gem_fb_init() calls kfree(fb)

Reported-by: coverity-bot <keescook+coverity-bot@chromium.org>
Addresses-Coverity-ID: 1492613 ("Memory - corruptions")
Fixes: f2b816d78a94 ("drm/core: Allow drivers allocate a subclass of struct drm_framebuffer")
Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: https://patchwork.freedesktop.org/patch/msgid/20200415172024.24004-1-andrzej.p@collabora.com
drivers/gpu/drm/drm_gem_framebuffer_helper.c

index cac15294aef61119a7979bb7ee62e0c59c1f83af..ccc2c71fa49140915928335c5da8e5460d337a9f 100644 (file)
@@ -76,10 +76,8 @@ drm_gem_fb_init(struct drm_device *dev,
                fb->obj[i] = obj[i];
 
        ret = drm_framebuffer_init(dev, fb, funcs);
-       if (ret) {
+       if (ret)
                drm_err(dev, "Failed to init framebuffer: %d\n", ret);
-               kfree(fb);
-       }
 
        return ret;
 }