diff options
author | Dave Airlie <airlied@redhat.com> | 2018-10-04 18:39:01 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2018-10-04 18:39:04 -0400 |
commit | 3a9df1e9259362ed1ec321ce4229f1cd992355e6 (patch) | |
tree | e4e6592d3c361ba88c69d48f19a210f88323e767 | |
parent | d8938c981f58ee344687b7910a611ac345960045 (diff) | |
parent | 4d4c2d89913e2d891bd6a34b12050a2576e60525 (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.c | 35 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_fb_cma_helper.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_fb_helper.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_lease.c | 6 | ||||
-rw-r--r-- | include/drm/drm_client.h | 5 |
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) | |||
63 | EXPORT_SYMBOL(drm_client_close); | 63 | EXPORT_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 | */ |
78 | int drm_client_new(struct drm_device *dev, struct drm_client_dev *client, | 79 | int 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 | } |
112 | EXPORT_SYMBOL(drm_client_new); | 109 | EXPORT_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 | */ | ||
121 | void 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 | } | ||
129 | EXPORT_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 | ||
174 | err_client_put: | 176 | err_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 | ||
90 | int drm_client_new(struct drm_device *dev, struct drm_client_dev *client, | 90 | int 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); |
92 | void drm_client_release(struct drm_client_dev *client); | 92 | void drm_client_release(struct drm_client_dev *client); |
93 | void drm_client_add(struct drm_client_dev *client); | ||
93 | 94 | ||
94 | void drm_client_dev_unregister(struct drm_device *dev); | 95 | void drm_client_dev_unregister(struct drm_device *dev); |
95 | void drm_client_dev_hotplug(struct drm_device *dev); | 96 | void drm_client_dev_hotplug(struct drm_device *dev); |