Skip to content

Commit ea2aa97

Browse files
JeffyCNChristianKoenigAMD
authored andcommitted
drm/gem: Fix GEM handle release errors
Currently we are assuming a one to one mapping between dmabuf and GEM handle when releasing GEM handles. But that is not always true, since we would create extra handles for the GEM obj in cases like gem_open() and getfb{,2}(). A similar issue was reported at: https://lore.kernel.org/all/[email protected]/ Another problem is that the imported dmabuf might not always have gem_obj->dma_buf set, which would cause leaks in drm_gem_remove_prime_handles(). Let's fix these for now by using handle to find the exact map to remove. Signed-off-by: Jeffy Chen <[email protected]> Reviewed-by: Christian König <[email protected]> Signed-off-by: Christian König <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 258e483 commit ea2aa97

File tree

3 files changed

+15
-26
lines changed

3 files changed

+15
-26
lines changed

drivers/gpu/drm/drm_gem.c

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -168,21 +168,6 @@ void drm_gem_private_object_init(struct drm_device *dev,
168168
}
169169
EXPORT_SYMBOL(drm_gem_private_object_init);
170170

171-
static void
172-
drm_gem_remove_prime_handles(struct drm_gem_object *obj, struct drm_file *filp)
173-
{
174-
/*
175-
* Note: obj->dma_buf can't disappear as long as we still hold a
176-
* handle reference in obj->handle_count.
177-
*/
178-
mutex_lock(&filp->prime.lock);
179-
if (obj->dma_buf) {
180-
drm_prime_remove_buf_handle_locked(&filp->prime,
181-
obj->dma_buf);
182-
}
183-
mutex_unlock(&filp->prime.lock);
184-
}
185-
186171
/**
187172
* drm_gem_object_handle_free - release resources bound to userspace handles
188173
* @obj: GEM object to clean up.
@@ -253,7 +238,7 @@ drm_gem_object_release_handle(int id, void *ptr, void *data)
253238
if (obj->funcs->close)
254239
obj->funcs->close(obj, file_priv);
255240

256-
drm_gem_remove_prime_handles(obj, file_priv);
241+
drm_prime_remove_buf_handle(&file_priv->prime, id);
257242
drm_vma_node_revoke(&obj->vma_node, file_priv);
258243

259244
drm_gem_object_handle_put_unlocked(obj);

drivers/gpu/drm/drm_internal.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@ int drm_prime_fd_to_handle_ioctl(struct drm_device *dev, void *data,
7474

7575
void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv);
7676
void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv);
77-
void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private *prime_fpriv,
78-
struct dma_buf *dma_buf);
77+
void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv,
78+
uint32_t handle);
7979

8080
/* drm_drv.c */
8181
struct drm_minor *drm_minor_acquire(unsigned int minor_id);

drivers/gpu/drm/drm_prime.c

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -190,29 +190,33 @@ static int drm_prime_lookup_buf_handle(struct drm_prime_file_private *prime_fpri
190190
return -ENOENT;
191191
}
192192

193-
void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private *prime_fpriv,
194-
struct dma_buf *dma_buf)
193+
void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv,
194+
uint32_t handle)
195195
{
196196
struct rb_node *rb;
197197

198-
rb = prime_fpriv->dmabufs.rb_node;
198+
mutex_lock(&prime_fpriv->lock);
199+
200+
rb = prime_fpriv->handles.rb_node;
199201
while (rb) {
200202
struct drm_prime_member *member;
201203

202-
member = rb_entry(rb, struct drm_prime_member, dmabuf_rb);
203-
if (member->dma_buf == dma_buf) {
204+
member = rb_entry(rb, struct drm_prime_member, handle_rb);
205+
if (member->handle == handle) {
204206
rb_erase(&member->handle_rb, &prime_fpriv->handles);
205207
rb_erase(&member->dmabuf_rb, &prime_fpriv->dmabufs);
206208

207-
dma_buf_put(dma_buf);
209+
dma_buf_put(member->dma_buf);
208210
kfree(member);
209-
return;
210-
} else if (member->dma_buf < dma_buf) {
211+
break;
212+
} else if (member->handle < handle) {
211213
rb = rb->rb_right;
212214
} else {
213215
rb = rb->rb_left;
214216
}
215217
}
218+
219+
mutex_unlock(&prime_fpriv->lock);
216220
}
217221

218222
void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv)

0 commit comments

Comments
 (0)