[PATCH] dma-buf: fix dma_buf_export init order
Charan Teja Kalla
quic_charante at quicinc.com
Tue Dec 6 17:12:01 UTC 2022
Thanks Christian for this nice cleanup!!
On 12/6/2022 8:42 PM, Christian König wrote:
> @@ -638,10 +630,21 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
> if (!try_module_get(exp_info->owner))
> return ERR_PTR(-ENOENT);
>
> + file = dma_buf_getfile(exp_info->size, exp_info->flags);
> + if (IS_ERR(file)) {
> + ret = PTR_ERR(file);
> + goto err_module;
> + }
> +
> + if (!exp_info->resv)
> + alloc_size += sizeof(struct dma_resv);
> + else
> + /* prevent &dma_buf[1] == dma_buf->resv */
> + alloc_size += 1;
> dmabuf = kzalloc(alloc_size, GFP_KERNEL);
> if (!dmabuf) {
> ret = -ENOMEM;
> - goto err_module;
> + goto err_file;
> }
>
> dmabuf->priv = exp_info->priv;
> @@ -653,44 +656,36 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
> init_waitqueue_head(&dmabuf->poll);
> dmabuf->cb_in.poll = dmabuf->cb_out.poll = &dmabuf->poll;
> dmabuf->cb_in.active = dmabuf->cb_out.active = 0;
> + mutex_init(&dmabuf->lock);
> + INIT_LIST_HEAD(&dmabuf->attachments);
>
> if (!resv) {
> - resv = (struct dma_resv *)&dmabuf[1];
> - dma_resv_init(resv);
> + dmabuf->resv = (struct dma_resv *)&dmabuf[1];
> + dma_resv_init(dmabuf->resv);
> + } else {
> + dmabuf->resv = resv;
> }
> - dmabuf->resv = resv;
>
> - file = dma_buf_getfile(dmabuf, exp_info->flags);
> - if (IS_ERR(file)) {
> - ret = PTR_ERR(file);
> + ret = dma_buf_stats_setup(dmabuf, file);
> + if (ret)
> goto err_dmabuf;
> - }
>
> + file->private_data = dmabuf;
> + file->f_path.dentry->d_fsdata = dmabuf;
> dmabuf->file = file;
>
> - mutex_init(&dmabuf->lock);
> - INIT_LIST_HEAD(&dmabuf->attachments);
> -
> mutex_lock(&db_list.lock);
> list_add(&dmabuf->list_node, &db_list.head);
> mutex_unlock(&db_list.lock);
>
> - ret = dma_buf_stats_setup(dmabuf);
> - if (ret)
> - goto err_sysfs;
> -
> return dmabuf;
>
> -err_sysfs:
> - /*
> - * Set file->f_path.dentry->d_fsdata to NULL so that when
> - * dma_buf_release() gets invoked by dentry_ops, it exits
> - * early before calling the release() dma_buf op.
> - */
> - file->f_path.dentry->d_fsdata = NULL;
> - fput(file);
> err_dmabuf:
> + if (!resv)
> + dma_resv_fini(dmabuf->resv);
> kfree(dmabuf);
> +err_file:
> + fput(file);
This fput() still endup in calling the dma_buf_file_release() where
there are no checks before accessing the file->private_data(=dmabuf)
which can result in null pointer access. Am I missing something trivial?
> err_module:
> module_put(exp_info->owner);
> return ERR_PTR(ret);
> -- 2.34.1
More information about the dri-devel
mailing list