public inbox for drm-ai-reviews@public-inbox.freedesktop.org
 help / color / mirror / Atom feed
From: Christian König <christian.koenig@amd.com>
To: Albert Esteve <aesteve@redhat.com>,
	Sumit Semwal <sumit.semwal@linaro.org>,
	Benjamin Gaignard <benjamin.gaignard@collabora.com>,
	Brian Starkey <Brian.Starkey@arm.com>,
	John Stultz <jstultz@google.com>,
	"T.J. Mercier" <tjmercier@google.com>,
	Shuah Khan <shuah@kernel.org>
Cc: linux-media@vger.kernel.org, dri-devel@lists.freedesktop.org,
	linaro-mm-sig@lists.linaro.org, linux-kernel@vger.kernel.org,
	linux-kselftest@vger.kernel.org, mripard@kernel.org
Subject: Re: [PATCH 1/2] dma-buf: add DMA_BUF_IOCTL_DERIVE for reduced-permission aliases
Date: Thu, 21 May 2026 14:30:18 +0200	[thread overview]
Message-ID: <bbcb0051-7969-45a5-847f-24e1c43f83dc@amd.com> (raw)
In-Reply-To: <20260521-dmabuf-limit-access-v1-1-26c01e27365a@redhat.com>

On 5/21/26 11:10, Albert Esteve wrote:
> When sharing a dma-buf between components of different trust levels,
> the allocator may need to hand out a read-only view of a buffer it
> holds with read-write access. Currently there is no mechanism to do
> this: the file flags set at allocation time are fixed for the
> lifetime of the dma-buf, and dup(2) and dup3(2) cannot change the
> access mode of the new fd.
> 
> Add DMA_BUF_IOCTL_DERIVE, which takes a struct dma_buf_derive carrying
> the desired access flags and returns a new file descriptor for the same
> buffer with those flags applied. Permission escalation is rejected with
> EACCES.
> 
> The new fd aliases the same struct dma_buf, same dma_resv, same exporter
> ops, same underlying memory. Importers that attach to either fd operate
> on the same object and observe the same fence timeline.
> 
> To support multiple struct file instances sharing one struct dma_buf,
> two small internal adjustments are required. First, move
> __dma_buf_list_del() to dma_buf_release() so that list removal fires
> exactly once when the dentry is destroyed. Second, update
> dma_buf_file_release() to call dma_buf_put() only for the files that
> are not primary dmabuf files, leaving the primary fd's refcount managed
> by the normal dentry lifecycle.


> Finally, enforce the access restriction in dma_buf_mmap_internal():
> a shared writable mapping (MAP_SHARED + PROT_WRITE) on a read-only fd
> is rejected with -EACCES. Without this check, O_RDONLY on a dma-buf
> fd would be cosmetic, as the VFS does not enforce f_mode for writable
> mmap on anonymous inodes.

Clear NAK to that since that would break the existing uAPI.

Regards,
Christian.

> 
> Signed-off-by: Albert Esteve <aesteve@redhat.com>
> ---
>  drivers/dma-buf/dma-buf.c    | 58 +++++++++++++++++++++++++++++++++++++++++++-
>  include/uapi/linux/dma-buf.h | 28 +++++++++++++++++++++
>  2 files changed, 85 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
> index 71f37544a5c61..34a3872365730 100644
> --- a/drivers/dma-buf/dma-buf.c
> +++ b/drivers/dma-buf/dma-buf.c
> @@ -180,6 +180,7 @@ static void dma_buf_release(struct dentry *dentry)
>  	 */
>  	BUG_ON(dmabuf->cb_in.active || dmabuf->cb_out.active);
>  
> +	__dma_buf_list_del(dmabuf);
>  	dmabuf->ops->release(dmabuf);
>  
>  	if (dmabuf->resv == (struct dma_resv *)&dmabuf[1])
> @@ -193,10 +194,13 @@ static void dma_buf_release(struct dentry *dentry)
>  
>  static int dma_buf_file_release(struct inode *inode, struct file *file)
>  {
> +	struct dma_buf *dmabuf = file->private_data;
> +
>  	if (!is_dma_buf_file(file))
>  		return -EINVAL;
>  
> -	__dma_buf_list_del(file->private_data);
> +	if (file != dmabuf->file)
> +		dma_buf_put(dmabuf);
>  
>  	return 0;
>  }
> @@ -232,6 +236,11 @@ static int dma_buf_mmap_internal(struct file *file, struct vm_area_struct *vma)
>  	if (!is_dma_buf_file(file))
>  		return -EINVAL;
>  
> +	if ((vma->vm_flags & VM_WRITE) &&
> +	    (vma->vm_flags & VM_SHARED) &&
> +	    !(file->f_mode & FMODE_WRITE))
> +		return -EACCES;
> +
>  	dmabuf = file->private_data;
>  
>  	/* check if buffer supports mmap */
> @@ -537,6 +546,50 @@ static long dma_buf_import_sync_file(struct dma_buf *dmabuf,
>  }
>  #endif
>  
> +static const struct file_operations dma_buf_fops;
> +
> +static int dma_buf_ioctl_derive(struct dma_buf *dmabuf, struct file *file,
> +				void __user *udata)
> +{
> +	struct dma_buf_derive params;
> +	struct file *new_file;
> +	int new_fd;
> +
> +	if (copy_from_user(&params, udata, sizeof(params)))
> +		return -EFAULT;
> +
> +	if (params.flags & ~(O_ACCMODE | O_CLOEXEC))
> +		return -EINVAL;
> +
> +	/* Escalating permissions is not allowed. */
> +	if ((params.flags & O_ACCMODE) == O_RDWR &&
> +	    !(file->f_mode & FMODE_WRITE))
> +		return -EACCES;
> +
> +	new_file = alloc_file_clone(dmabuf->file, params.flags, &dma_buf_fops);
> +	if (IS_ERR(new_file))
> +		return PTR_ERR(new_file);
> +
> +	get_dma_buf(dmabuf);
> +	new_file->private_data = dmabuf;
> +
> +	new_fd = get_unused_fd_flags(params.flags & O_CLOEXEC ? O_CLOEXEC : 0);
> +	if (new_fd < 0) {
> +		fput(new_file);
> +		return new_fd;
> +	}
> +
> +	params.fd = new_fd;
> +	if (copy_to_user(udata, &params, sizeof(params))) {
> +		put_unused_fd(new_fd);
> +		fput(new_file);
> +		return -EFAULT;
> +	}
> +
> +	fd_install(new_fd, new_file);
> +	return 0;
> +}
> +
>  static long dma_buf_ioctl(struct file *file,
>  			  unsigned int cmd, unsigned long arg)
>  {
> @@ -587,6 +640,9 @@ static long dma_buf_ioctl(struct file *file,
>  		return dma_buf_import_sync_file(dmabuf, (const void __user *)arg);
>  #endif
>  
> +	case DMA_BUF_IOCTL_DERIVE:
> +		return dma_buf_ioctl_derive(dmabuf, file, (void __user *)arg);
> +
>  	default:
>  		return -ENOTTY;
>  	}
> diff --git a/include/uapi/linux/dma-buf.h b/include/uapi/linux/dma-buf.h
> index e827c9d20c5d3..d0cf616228e55 100644
> --- a/include/uapi/linux/dma-buf.h
> +++ b/include/uapi/linux/dma-buf.h
> @@ -168,6 +168,33 @@ struct dma_buf_import_sync_file {
>  	__s32 fd;
>  };
>  
> +/**
> + * struct dma_buf_derive - Obtain a dma-buf fd with reduced access permissions
> + *
> + * Userspace can perform a DMA_BUF_IOCTL_DERIVE to obtain a second file
> + * descriptor for the same dma-buf with a subset of the calling fd's
> + * permissions.  This allows a producer holding read-write access to hand a
> + * read-only view to a less-privileged consumer without giving up its own
> + * write access or allocating a separate buffer.
> + *
> + * Unlike first-export ioctls, the new fd is not a re-export. It shares the
> + * same reservation object, exporter ops, and underlying memory as the
> + * original.
> + *
> + * The requested permissions must not exceed those of the calling fd.
> + */
> +struct dma_buf_derive {
> +	/**
> +	 * @flags: Requested access flags.
> +	 *
> +	 * Accepts O_RDONLY or O_RDWR, optionally combined with O_CLOEXEC.
> +	 * All other bits must be zero.
> +	 */
> +	__u32 flags;
> +	/** @fd: Returned file descriptor with the requested permissions */
> +	__s32 fd;
> +};
> +
>  #define DMA_BUF_BASE		'b'
>  #define DMA_BUF_IOCTL_SYNC	_IOW(DMA_BUF_BASE, 0, struct dma_buf_sync)
>  
> @@ -179,5 +206,6 @@ struct dma_buf_import_sync_file {
>  #define DMA_BUF_SET_NAME_B	_IOW(DMA_BUF_BASE, 1, __u64)
>  #define DMA_BUF_IOCTL_EXPORT_SYNC_FILE	_IOWR(DMA_BUF_BASE, 2, struct dma_buf_export_sync_file)
>  #define DMA_BUF_IOCTL_IMPORT_SYNC_FILE	_IOW(DMA_BUF_BASE, 3, struct dma_buf_import_sync_file)
> +#define DMA_BUF_IOCTL_DERIVE		_IOWR(DMA_BUF_BASE, 4, struct dma_buf_derive)
>  
>  #endif
> 


  reply	other threads:[~2026-05-21 12:30 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-21  9:10 [PATCH 0/2] dma-buf: add DMA_BUF_IOCTL_DERIVE for reduced-permission aliases Albert Esteve
2026-05-21  9:10 ` [PATCH 1/2] " Albert Esteve
2026-05-21 12:30   ` Christian König [this message]
2026-05-25 10:27   ` Claude review: " Claude Code Review Bot
2026-05-21  9:10 ` [PATCH 2/2] selftests: dma-buf: add DERIVE ioctl tests Albert Esteve
2026-05-25 10:27   ` Claude review: " Claude Code Review Bot
2026-05-21 12:28 ` [PATCH 0/2] dma-buf: add DMA_BUF_IOCTL_DERIVE for reduced-permission aliases Christian König
2026-05-21 13:01   ` Albert Esteve
2026-05-21 13:14     ` Christian König
2026-05-25 10:27 ` Claude review: " Claude Code Review Bot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=bbcb0051-7969-45a5-847f-24e1c43f83dc@amd.com \
    --to=christian.koenig@amd.com \
    --cc=Brian.Starkey@arm.com \
    --cc=aesteve@redhat.com \
    --cc=benjamin.gaignard@collabora.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=jstultz@google.com \
    --cc=linaro-mm-sig@lists.linaro.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=linux-media@vger.kernel.org \
    --cc=mripard@kernel.org \
    --cc=shuah@kernel.org \
    --cc=sumit.semwal@linaro.org \
    --cc=tjmercier@google.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox