[bug report] drm/msm: Fix submit error-path leaks

Dan Carpenter dan.carpenter at linaro.org
Tue Jul 15 19:25:14 UTC 2025


Hello Rob Clark,

Commit 68dc6c2d5eec ("drm/msm: Fix submit error-path leaks") from May
9, 2023 (linux-next), leads to the following Smatch static checker
warning:

drivers/gpu/drm/msm/msm_gem_submit.c:816 msm_ioctl_gem_submit() warn: fd used after fd_install() 'out_fence_fd'
drivers/gpu/drm/msm/msm_gem_submit.c:818 msm_ioctl_gem_submit() warn: fd used after fd_install() 'sync_file->file'

drivers/gpu/drm/msm/msm_gem_submit.c
    751                 WARN_ON(ret);
    752         } else {
    753                 /*
    754                  * Allocate an id which can be used by WAIT_FENCE ioctl to map
    755                  * back to the underlying fence.
    756                  */
    757                 submit->fence_id = idr_alloc_cyclic(&queue->fence_idr,
    758                                                     submit->user_fence, 1,
    759                                                     INT_MAX, GFP_NOWAIT);
    760         }
    761 
    762         spin_unlock(&queue->idr_lock);
    763         idr_preload_end();
    764 
    765         if (submit->fence_id < 0) {
    766                 ret = submit->fence_id;
    767                 submit->fence_id = 0;
    768         }
    769 
    770         if (ret == 0 && args->flags & MSM_SUBMIT_FENCE_FD_OUT) {
    771                 sync_file = sync_file_create(submit->user_fence);
    772                 if (!sync_file) {
    773                         ret = -ENOMEM;
    774                 } else {
    775                         fd_install(out_fence_fd, sync_file->file);
                                           ^^^^^^^^^^^^
Once we call fd_install() the file is exposed to userspace and they can make
the fd point to a different file.

    776                         args->fence_fd = out_fence_fd;
    777                 }
    778         }
    779 
    780         if (ret)
    781                 goto out;
    782 
    783         submit_attach_object_fences(submit);
    784 
    785         if (msm_context_is_vmbind(ctx)) {
    786                 /*
    787                  * If we are not using VM_BIND, submit_pin_vmas() will validate
    788                  * just the BOs attached to the submit.  In that case we don't
    789                  * need to validate the _entire_ vm, because userspace tracked
    790                  * what BOs are associated with the submit.
    791                  */
    792                 ret = drm_gpuvm_validate(submit->vm, &submit->exec);
    793                 if (ret)
    794                         goto out;
    795         }
    796 
    797         /* The scheduler owns a ref now: */
    798         msm_gem_submit_get(submit);
    799 
    800         msm_rd_dump_submit(priv->rd, submit, NULL);
    801 
    802         drm_sched_entity_push_job(&submit->base);
    803 
    804         args->fence = submit->fence_id;
    805         queue->last_fence = submit->fence_id;
    806 
    807         msm_syncobj_reset(syncobjs_to_reset, args->nr_in_syncobjs);
    808         msm_syncobj_process_post_deps(post_deps, args->nr_out_syncobjs, submit->user_fence);
    809 
    810 out:
    811         submit_cleanup(submit, !!ret);
    812 out_unlock:
    813         mutex_unlock(&queue->lock);
    814 out_post_unlock:
    815         if (ret && (out_fence_fd >= 0)) {
--> 816                 put_unused_fd(out_fence_fd);
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^
So this put_unused_fd() could potentially do something to the wrong file.
Traditionally, we either do the fd_install() last or we just leak until the
process dies and all the files are released.

(Hand wavey because I'm not sure how all this works exactly)

    817                 if (sync_file)
    818                         fput(sync_file->file);
    819         }
    820 
    821         if (!IS_ERR_OR_NULL(submit)) {
    822                 msm_gem_submit_put(submit);
    823         } else {
    824                 /*
    825                  * If the submit hasn't yet taken ownership of the queue
    826                  * then we need to drop the reference ourself:
    827                  */
    828                 msm_submitqueue_put(queue);
    829         }
    830         if (!IS_ERR_OR_NULL(post_deps)) {
    831                 for (i = 0; i < args->nr_out_syncobjs; ++i) {
    832                         kfree(post_deps[i].chain);
    833                         drm_syncobj_put(post_deps[i].syncobj);
    834                 }
    835                 kfree(post_deps);
    836         }
    837 
    838         if (!IS_ERR_OR_NULL(syncobjs_to_reset)) {
    839                 for (i = 0; i < args->nr_in_syncobjs; ++i) {
    840                         if (syncobjs_to_reset[i])
    841                                 drm_syncobj_put(syncobjs_to_reset[i]);
    842                 }
    843                 kfree(syncobjs_to_reset);
    844         }
    845 
    846         return ret;
    847 }

regards,
dan carpenter


More information about the dri-devel mailing list