Hi Laurent,
Sorry for the late reply. Thank you very much for noticing the issue.
+static struct dma_buf *vb2_dc_get_dmabuf(void *buf_priv) +{
- struct vb2_dc_buf *buf = buf_priv;
- struct dma_buf *dbuf;
- if (buf->dma_buf)
return buf->dma_buf;
Can't there be a race condition here if the user closes the DMABUF file handle before vb2 core calls dma_buf_fd() ?
The user cannot access the file until it is associated with a file descriptor. How can the user close it? Could you give me a more detailed description of this potential race condition?
Let's assume the V4L2 buffer has already been exported once. buf->dma_buf is set to a non-NULL value, and the application has an open file handle for the buffer. The application then tries to export the buffer a second time. vb2_dc_get_dmabuf() gets called, checks buf->dma_buf and returns it as it's non-NULL. Right after that, before the vb2 core calls dma_buf_fd() on the struct dma_buf, the application closes the file handle to the exported buffer. The struct dma_buf object gets freed, as the reference count drops to 0.
I am not sure if reference counter drops to 0 in this case. Notice that after first dma_buf_export the dma_buf's refcnt is 1, after first dma_buf_fd it goes to 2. After closing a file handle the refcnt drops back to 1 so the file (and dma_buf) is not released. Therefore IMO there no dangling pointer issue.
However it looks that there is a circular reference between vb2_dc_buf and dma_buf. vb2_dc_buf::dma_buf is pointing to dma_buf with reference taken at dma_buf_export. On the other hand the dma_buf->priv is pointing to vb2_dc_buf with reference taken at atomic_inc(&buf->refcount) in vb2_dc_get_dmabuf.
The circular reference leads into resource leakage. The problem could be fixed by dropping caching of dma_buf pointer. The new dma_buf would be created and exported at every export event. The dma_buf_put would be called in vb2_expbuf just after successful dma_buf_fd.
Do you have any ideas how I could deal with resource leakage/dangling problems without creating a new dma_buf instance at every export event?
Regards, Tomasz Stanislawski
vb2 core will then try to call dma_buf_fd() on a dma_buf object that has been freed.
- /* dmabuf keeps reference to vb2 buffer */
- atomic_inc(&buf->refcount);
- dbuf = dma_buf_export(buf, &vb2_dc_dmabuf_ops, buf->size, 0);
- if (IS_ERR(dbuf)) {
atomic_dec(&buf->refcount);
return NULL;
- }
- buf->dma_buf = dbuf;
- return dbuf;
+}