dma-buf: Add support to set a destructor on a dma-buf

dma-buf destructor support is useful as it allows clients an opportunity
to undo any attributes, such as security attributes, they have applied to
the dma-buf's memory.

The destructor is called when the dma-buf is freed, if the destructor
returns an error the dma-buf's exporter release function is not called in
order to ensure that memory which has not been properly cleaned up isn't
returned to the system.

Change-Id: If2173b23b441157b3638110f02e2ff90ab6ad1aa
Signed-off-by: Liam Mark <lmark@codeaurora.org>
Signed-off-by: Swathi Sridhar <swatsrid@codeaurora.org>
[isaacm@codeaurora.org: resolve merge conflicts/qseecom redefinitions]
Signed-off-by: Isaac J. Manjarres <isaacm@codeaurora.org>
This commit is contained in:
Liam Mark 2019-02-21 11:56:18 -08:00 • committed by Isaac J. Manjarres
commit 236b06ac63
4 changed files with 82 additions and 8 deletions

View file

@ -41,6 +41,21 @@ config DEBUG_DMA_BUF_REF
matching the get/put call stacks. This feature consumes extra memory
in order to save the stack traces using STACKDEPOT.
config DMABUF_DESTRUCTOR_SUPPORT
bool "dmabuf destructor support"
default n
depends on DMA_SHARED_BUFFER
depends on QGKI
help
dma-buf destructor support is useful as it allows clients an
opportunity to undo any attributes, such as security attributes,
they have applied to the dma-buf's memory.
The destructor is called when the dma-buf is freed, if the destructor
returns an error the dma-buf's exporter release function is not
called in order to ensure that memory which has not been properly
cleaned up isn't returned to the system
config UDMABUF
bool "userspace dmabuf misc driver"
default n

View file

@ -54,10 +54,33 @@ static char *dmabuffs_dname(struct dentry *dentry, char *buffer, int buflen)
dentry->d_name.name, ret > 0 ? name : "");
}
#ifdef CONFIG_DMABUF_DESTRUCTOR_SUPPORT
static int dma_buf_invoke_dtor(struct dma_buf *dmabuf)
{
int ret = 0;
if (dmabuf->dtor) {
ret = dmabuf->dtor(dmabuf, dmabuf->dtor_data);
if (ret < 0)
pr_warn_ratelimited("Leaking dmabuf ino: %ld because destructor failed error: %d\n",
file_inode(dmabuf->file)->i_ino,
ret);
}
return ret;
}
#else
static inline int dma_buf_invoke_dtor(struct dma_buf *dmabuf)
{
return 0;
}
#endif
static void dma_buf_release(struct dentry *dentry)
{
struct msm_dma_buf *msm_dma_buf;
struct dma_buf *dmabuf;
int dtor_ret = 0;
dmabuf = dentry->d_fsdata;
msm_dma_buf = to_msm_dma_buf(dmabuf);
@ -78,7 +101,11 @@ static void dma_buf_release(struct dentry *dentry)
list_del(&dmabuf->list_node);
mutex_unlock(&db_list.lock);
dmabuf->ops->release(dmabuf);
dtor_ret = dma_buf_invoke_dtor(dmabuf);
if (!dtor_ret)
dmabuf->ops->release(dmabuf);
dma_buf_ref_destroy(msm_dma_buf);
if (dmabuf->resv == (struct dma_resv *)&dmabuf[1])

View file

@ -1229,13 +1229,6 @@ exit:
return ret;
}
typedef int (*dma_buf_destructor)(struct dma_buf *dmabuf, void *dtor_data);
static void dma_buf_set_destructor(struct dma_buf *dmabuf,
dma_buf_destructor dtor,
void *dtor_data)
{
}
static int qseecom_destroy_bridge_callback(
struct dma_buf *dmabuf, void *dtor_data)
{

View file

@ -350,6 +350,18 @@ struct dma_buf_ops {
int (*get_flags)(struct dma_buf *dmabuf, unsigned long *flags);
};
/**
* dma_buf_destructor - dma-buf destructor function
* @dmabuf: [in] pointer to dma-buf
* @dtor_data: [in] destructor data associated with this buffer
*
* The dma-buf destructor which is called when the dma-buf is freed.
*
* If the destructor returns an error the dma-buf's exporter release function
* won't be called.
*/
typedef int (*dma_buf_destructor)(struct dma_buf *dmabuf, void *dtor_data);
/**
* struct dma_buf - shared buffer object
* @size: size of the buffer
@ -394,6 +406,10 @@ struct dma_buf {
struct list_head list_node;
void *priv;
struct dma_resv *resv;
#ifdef CONFIG_DMABUF_DESTRUCTOR_SUPPORT
dma_buf_destructor dtor;
void *dtor_data;
#endif
/* poll support */
wait_queue_head_t poll;
@ -537,4 +553,27 @@ void dma_buf_vunmap(struct dma_buf *, void *vaddr);
int dma_buf_get_flags(struct dma_buf *dmabuf, unsigned long *flags);
int dma_buf_get_uuid(struct dma_buf *dmabuf, uuid_t *uuid);
#ifdef CONFIG_DMABUF_DESTRUCTOR_SUPPORT
/**
* dma_buf_set_destructor - set the dma-buf's destructor
* @dmabuf: [in] pointer to dma-buf
* @dma_buf_destructor [in] the destructor function
* @dtor_data: [in] destructor data associated with this buffer
*/
static inline int dma_buf_set_destructor(struct dma_buf *dmabuf,
dma_buf_destructor dtor,
void *dtor_data)
{
dmabuf->dtor = dtor;
dmabuf->dtor_data = dtor_data;
return 0;
}
#else
static inline int dma_buf_set_destructor(struct dma_buf *dmabuf,
dma_buf_destructor dtor,
void *dtor_data)
{
return -ENOTSUPP;
}
#endif
#endif /* __DMA_BUF_H__ */