diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c index c138ddd10a3a..1e730bd6af32 100644 --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c @@ -387,6 +387,16 @@ static __poll_t dma_buf_poll(struct file *file, poll_table *poll) return events; } +static long _dma_buf_set_name(struct dma_buf *dmabuf, const char *name) +{ + spin_lock(&dmabuf->name_lock); + kfree(dmabuf->name); + dmabuf->name = name; + spin_unlock(&dmabuf->name_lock); + + return 0; +} + /** * dma_buf_set_name - Set a name to a specific dma_buf to track the usage. * It could support changing the name of the dma-buf if the same @@ -400,19 +410,35 @@ static __poll_t dma_buf_poll(struct file *file, poll_table *poll) * 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; if (IS_ERR(name)) return PTR_ERR(name); - spin_lock(&dmabuf->name_lock); - kfree(dmabuf->name); - dmabuf->name = name; - spin_unlock(&dmabuf->name_lock); + ret = _dma_buf_set_name(dmabuf, name); + if (ret) + kfree(name); - return 0; + return ret; } #if IS_ENABLED(CONFIG_SYNC_FILE) @@ -561,7 +587,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); #if IS_ENABLED(CONFIG_SYNC_FILE) case DMA_BUF_IOCTL_EXPORT_SYNC_FILE: diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h index 485b97f29697..99286d2c3d6a 100644 --- a/include/linux/dma-buf.h +++ b/include/linux/dma-buf.h @@ -653,6 +653,7 @@ int dma_buf_mmap(struct dma_buf *, struct vm_area_struct *, unsigned long); int dma_buf_vmap(struct dma_buf *dmabuf, struct iosys_map *map); void dma_buf_vunmap(struct dma_buf *dmabuf, struct iosys_map *map); +long dma_buf_set_name(struct dma_buf *dmabuf, const char *name); #ifdef CONFIG_DMABUF_CACHE /** * dma_buf_set_destructor - set the dma-buf's destructor