diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c index d9948d58b3f4..0ee38382ba17 100644 --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c @@ -348,6 +348,25 @@ out: return events; } +static long _dma_buf_set_name(struct dma_buf *dmabuf, const char *name) +{ + long ret = 0; + + dma_resv_lock(dmabuf->resv, NULL); + if (!list_empty(&dmabuf->attachments)) { + ret = -EBUSY; + goto out_unlock; + } + spin_lock(&dmabuf->name_lock); + kfree(dmabuf->name); + dmabuf->name = name; + spin_unlock(&dmabuf->name_lock); + +out_unlock: + dma_resv_unlock(dmabuf->resv); + return ret; +} + /** * dma_buf_set_name - Set a name to a specific dma_buf to track the usage. * The name of the dma-buf buffer can only be set when the dma-buf is not @@ -363,7 +382,23 @@ out: * devices, return -EBUSY. * */ -static long dma_buf_set_name(struct dma_buf *dmabuf, const char __user *buf) +long dma_buf_set_name(struct dma_buf *dmabuf, const char *name) +{ + long ret = 0; + char *buf = kstrndup(name, DMA_BUF_NAME_LEN, GFP_KERNEL); + + if (!buf) + return -ENOMEM; + + ret = _dma_buf_set_name(dmabuf, buf); + if (ret) + kfree(buf); + + return ret; +} +EXPORT_SYMBOL_GPL(dma_buf_set_name); + +static long dma_buf_set_name_user(struct dma_buf *dmabuf, const char __user *buf) { char *name = strndup_user(buf, DMA_BUF_NAME_LEN); long ret = 0; @@ -371,19 +406,10 @@ static long dma_buf_set_name(struct dma_buf *dmabuf, const char __user *buf) if (IS_ERR(name)) return PTR_ERR(name); - dma_resv_lock(dmabuf->resv, NULL); - if (!list_empty(&dmabuf->attachments)) { - ret = -EBUSY; + ret = _dma_buf_set_name(dmabuf, name); + if (ret) kfree(name); - goto out_unlock; - } - spin_lock(&dmabuf->name_lock); - kfree(dmabuf->name); - dmabuf->name = name; - spin_unlock(&dmabuf->name_lock); -out_unlock: - dma_resv_unlock(dmabuf->resv); return ret; } @@ -428,7 +454,7 @@ static long dma_buf_ioctl(struct file *file, case DMA_BUF_SET_NAME_A: case DMA_BUF_SET_NAME_B: - return dma_buf_set_name(dmabuf, (const char __user *)arg); + return dma_buf_set_name_user(dmabuf, (const char __user *)arg); default: return -ENOTTY; diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h index 63ffe57a61d5..a9ad8cfdd8fd 100644 --- a/include/linux/dma-buf.h +++ b/include/linux/dma-buf.h @@ -623,6 +623,7 @@ int dma_buf_mmap(struct dma_buf *, struct vm_area_struct *, unsigned long); void *dma_buf_vmap(struct dma_buf *); void dma_buf_vunmap(struct dma_buf *, void *vaddr); +long dma_buf_set_name(struct dma_buf *dmabuf, const char *name); int dma_buf_get_flags(struct dma_buf *dmabuf, unsigned long *flags); int dma_buf_get_uuid(struct dma_buf *dmabuf, uuid_t *uuid);