aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2018-10-04 18:39:01 -0400
committerDave Airlie <airlied@redhat.com>2018-10-04 18:39:04 -0400
commit3a9df1e9259362ed1ec321ce4229f1cd992355e6 (patch)
treee4e6592d3c361ba88c69d48f19a210f88323e767
parentd8938c981f58ee344687b7910a611ac345960045 (diff)
parent4d4c2d89913e2d891bd6a34b12050a2576e60525 (diff)
Merge tag 'drm-misc-fixes-2018-10-04' of git://anongit.freedesktop.org/drm/drm-misc into drm-fixes
drm-misc-fixes for v4.19-rc7: - Fix use-after-free in drm_mode_create_lease_ioctl() - Fix crash in fbdev error path. Signed-off-by: Dave Airlie <airlied@redhat.com> From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/13b2c3ac-9a96-710e-ceb9-890af164f10e@linux.intel.com
-rw-r--r--drivers/gpu/drm/drm_client.c35
-rw-r--r--drivers/gpu/drm/drm_fb_cma_helper.c4
-rw-r--r--drivers/gpu/drm/drm_fb_helper.c4
-rw-r--r--drivers/gpu/drm/drm_lease.c6
-rw-r--r--include/drm/drm_client.h5
5 files changed, 38 insertions, 16 deletions
diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c
index baff50a4c234..df31c3815092 100644
--- a/drivers/gpu/drm/drm_client.c
+++ b/drivers/gpu/drm/drm_client.c
@@ -63,20 +63,21 @@ static void drm_client_close(struct drm_client_dev *client)
63EXPORT_SYMBOL(drm_client_close); 63EXPORT_SYMBOL(drm_client_close);
64 64
65/** 65/**
66 * drm_client_new - Create a DRM client 66 * drm_client_init - Initialise a DRM client
67 * @dev: DRM device 67 * @dev: DRM device
68 * @client: DRM client 68 * @client: DRM client
69 * @name: Client name 69 * @name: Client name
70 * @funcs: DRM client functions (optional) 70 * @funcs: DRM client functions (optional)
71 * 71 *
72 * This initialises the client and opens a &drm_file. Use drm_client_add() to complete the process.
72 * The caller needs to hold a reference on @dev before calling this function. 73 * The caller needs to hold a reference on @dev before calling this function.
73 * The client is freed when the &drm_device is unregistered. See drm_client_release(). 74 * The client is freed when the &drm_device is unregistered. See drm_client_release().
74 * 75 *
75 * Returns: 76 * Returns:
76 * Zero on success or negative error code on failure. 77 * Zero on success or negative error code on failure.
77 */ 78 */
78int drm_client_new(struct drm_device *dev, struct drm_client_dev *client, 79int drm_client_init(struct drm_device *dev, struct drm_client_dev *client,
79 const char *name, const struct drm_client_funcs *funcs) 80 const char *name, const struct drm_client_funcs *funcs)
80{ 81{
81 int ret; 82 int ret;
82 83
@@ -95,10 +96,6 @@ int drm_client_new(struct drm_device *dev, struct drm_client_dev *client,
95 if (ret) 96 if (ret)
96 goto err_put_module; 97 goto err_put_module;
97 98
98 mutex_lock(&dev->clientlist_mutex);
99 list_add(&client->list, &dev->clientlist);
100 mutex_unlock(&dev->clientlist_mutex);
101
102 drm_dev_get(dev); 99 drm_dev_get(dev);
103 100
104 return 0; 101 return 0;
@@ -109,13 +106,33 @@ err_put_module:
109 106
110 return ret; 107 return ret;
111} 108}
112EXPORT_SYMBOL(drm_client_new); 109EXPORT_SYMBOL(drm_client_init);
110
111/**
112 * drm_client_add - Add client to the device list
113 * @client: DRM client
114 *
115 * Add the client to the &drm_device client list to activate its callbacks.
116 * @client must be initialized by a call to drm_client_init(). After
117 * drm_client_add() it is no longer permissible to call drm_client_release()
118 * directly (outside the unregister callback), instead cleanup will happen
119 * automatically on driver unload.
120 */
121void drm_client_add(struct drm_client_dev *client)
122{
123 struct drm_device *dev = client->dev;
124
125 mutex_lock(&dev->clientlist_mutex);
126 list_add(&client->list, &dev->clientlist);
127 mutex_unlock(&dev->clientlist_mutex);
128}
129EXPORT_SYMBOL(drm_client_add);
113 130
114/** 131/**
115 * drm_client_release - Release DRM client resources 132 * drm_client_release - Release DRM client resources
116 * @client: DRM client 133 * @client: DRM client
117 * 134 *
118 * Releases resources by closing the &drm_file that was opened by drm_client_new(). 135 * Releases resources by closing the &drm_file that was opened by drm_client_init().
119 * It is called automatically if the &drm_client_funcs.unregister callback is _not_ set. 136 * It is called automatically if the &drm_client_funcs.unregister callback is _not_ set.
120 * 137 *
121 * This function should only be called from the unregister callback. An exception 138 * This function should only be called from the unregister callback. An exception
diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c
index 9da36a6271d3..9ac1f2e0f064 100644
--- a/drivers/gpu/drm/drm_fb_cma_helper.c
+++ b/drivers/gpu/drm/drm_fb_cma_helper.c
@@ -160,7 +160,7 @@ struct drm_fbdev_cma *drm_fbdev_cma_init(struct drm_device *dev,
160 160
161 fb_helper = &fbdev_cma->fb_helper; 161 fb_helper = &fbdev_cma->fb_helper;
162 162
163 ret = drm_client_new(dev, &fb_helper->client, "fbdev", NULL); 163 ret = drm_client_init(dev, &fb_helper->client, "fbdev", NULL);
164 if (ret) 164 if (ret)
165 goto err_free; 165 goto err_free;
166 166
@@ -169,6 +169,8 @@ struct drm_fbdev_cma *drm_fbdev_cma_init(struct drm_device *dev,
169 if (ret) 169 if (ret)
170 goto err_client_put; 170 goto err_client_put;
171 171
172 drm_client_add(&fb_helper->client);
173
172 return fbdev_cma; 174 return fbdev_cma;
173 175
174err_client_put: 176err_client_put:
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 16ec93b75dbf..515a7aec57ac 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -3218,12 +3218,14 @@ int drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp)
3218 if (!fb_helper) 3218 if (!fb_helper)
3219 return -ENOMEM; 3219 return -ENOMEM;
3220 3220
3221 ret = drm_client_new(dev, &fb_helper->client, "fbdev", &drm_fbdev_client_funcs); 3221 ret = drm_client_init(dev, &fb_helper->client, "fbdev", &drm_fbdev_client_funcs);
3222 if (ret) { 3222 if (ret) {
3223 kfree(fb_helper); 3223 kfree(fb_helper);
3224 return ret; 3224 return ret;
3225 } 3225 }
3226 3226
3227 drm_client_add(&fb_helper->client);
3228
3227 fb_helper->preferred_bpp = preferred_bpp; 3229 fb_helper->preferred_bpp = preferred_bpp;
3228 3230
3229 drm_fbdev_client_hotplug(&fb_helper->client); 3231 drm_fbdev_client_hotplug(&fb_helper->client);
diff --git a/drivers/gpu/drm/drm_lease.c b/drivers/gpu/drm/drm_lease.c
index b54fb78a283c..b82da96ded5c 100644
--- a/drivers/gpu/drm/drm_lease.c
+++ b/drivers/gpu/drm/drm_lease.c
@@ -566,14 +566,14 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev,
566 lessee_priv->is_master = 1; 566 lessee_priv->is_master = 1;
567 lessee_priv->authenticated = 1; 567 lessee_priv->authenticated = 1;
568 568
569 /* Hook up the fd */
570 fd_install(fd, lessee_file);
571
572 /* Pass fd back to userspace */ 569 /* Pass fd back to userspace */
573 DRM_DEBUG_LEASE("Returning fd %d id %d\n", fd, lessee->lessee_id); 570 DRM_DEBUG_LEASE("Returning fd %d id %d\n", fd, lessee->lessee_id);
574 cl->fd = fd; 571 cl->fd = fd;
575 cl->lessee_id = lessee->lessee_id; 572 cl->lessee_id = lessee->lessee_id;
576 573
574 /* Hook up the fd */
575 fd_install(fd, lessee_file);
576
577 DRM_DEBUG_LEASE("drm_mode_create_lease_ioctl succeeded\n"); 577 DRM_DEBUG_LEASE("drm_mode_create_lease_ioctl succeeded\n");
578 return 0; 578 return 0;
579 579
diff --git a/include/drm/drm_client.h b/include/drm/drm_client.h
index 989f8e52864d..971bb7853776 100644
--- a/include/drm/drm_client.h
+++ b/include/drm/drm_client.h
@@ -87,9 +87,10 @@ struct drm_client_dev {
87 struct drm_file *file; 87 struct drm_file *file;
88}; 88};
89 89
90int drm_client_new(struct drm_device *dev, struct drm_client_dev *client, 90int drm_client_init(struct drm_device *dev, struct drm_client_dev *client,
91 const char *name, const struct drm_client_funcs *funcs); 91 const char *name, const struct drm_client_funcs *funcs);
92void drm_client_release(struct drm_client_dev *client); 92void drm_client_release(struct drm_client_dev *client);
93void drm_client_add(struct drm_client_dev *client);
93 94
94void drm_client_dev_unregister(struct drm_device *dev); 95void drm_client_dev_unregister(struct drm_device *dev);
95void drm_client_dev_hotplug(struct drm_device *dev); 96void drm_client_dev_hotplug(struct drm_device *dev);