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

Reply via email to