]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - queue-4.14/drm-vmwgfx-don-t-double-free-the-mode-stored-in-par-set_mode.patch
dbda65d2a05319f5bb3789c5d1b223e1057d2835
[thirdparty/kernel/stable-queue.git] / queue-4.14 / drm-vmwgfx-don-t-double-free-the-mode-stored-in-par-set_mode.patch
1 From c2d311553855395764e2e5bf401d987ba65c2056 Mon Sep 17 00:00:00 2001
2 From: Thomas Zimmermann <tzimmermann@suse.de>
3 Date: Mon, 18 Mar 2019 15:47:58 +0100
4 Subject: drm/vmwgfx: Don't double-free the mode stored in par->set_mode
5
6 From: Thomas Zimmermann <tzimmermann@suse.de>
7
8 commit c2d311553855395764e2e5bf401d987ba65c2056 upstream.
9
10 When calling vmw_fb_set_par(), the mode stored in par->set_mode gets free'd
11 twice. The first free is in vmw_fb_kms_detach(), the second is near the
12 end of vmw_fb_set_par() under the name of 'old_mode'. The mode-setting code
13 only works correctly if the mode doesn't actually change. Removing
14 'old_mode' in favor of using par->set_mode directly fixes the problem.
15
16 Cc: <stable@vger.kernel.org>
17 Fixes: a278724aa23c ("drm/vmwgfx: Implement fbdev on kms v2")
18 Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
19 Reviewed-by: Deepak Rawat <drawat@vmware.com>
20 Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
21 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
22
23 ---
24 drivers/gpu/drm/vmwgfx/vmwgfx_fb.c | 12 +++---------
25 1 file changed, 3 insertions(+), 9 deletions(-)
26
27 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
28 +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
29 @@ -588,11 +588,9 @@ static int vmw_fb_set_par(struct fb_info
30 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
31 DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC)
32 };
33 - struct drm_display_mode *old_mode;
34 struct drm_display_mode *mode;
35 int ret;
36
37 - old_mode = par->set_mode;
38 mode = drm_mode_duplicate(vmw_priv->dev, &new_mode);
39 if (!mode) {
40 DRM_ERROR("Could not create new fb mode.\n");
41 @@ -603,11 +601,7 @@ static int vmw_fb_set_par(struct fb_info
42 mode->vdisplay = var->yres;
43 vmw_guess_mode_timing(mode);
44
45 - if (old_mode && drm_mode_equal(old_mode, mode)) {
46 - drm_mode_destroy(vmw_priv->dev, mode);
47 - mode = old_mode;
48 - old_mode = NULL;
49 - } else if (!vmw_kms_validate_mode_vram(vmw_priv,
50 + if (!vmw_kms_validate_mode_vram(vmw_priv,
51 mode->hdisplay *
52 DIV_ROUND_UP(var->bits_per_pixel, 8),
53 mode->vdisplay)) {
54 @@ -677,8 +671,8 @@ static int vmw_fb_set_par(struct fb_info
55 schedule_delayed_work(&par->local_work, 0);
56
57 out_unlock:
58 - if (old_mode)
59 - drm_mode_destroy(vmw_priv->dev, old_mode);
60 + if (par->set_mode)
61 + drm_mode_destroy(vmw_priv->dev, par->set_mode);
62 par->set_mode = mode;
63
64 drm_modeset_unlock_all(vmw_priv->dev);