From nobody Mon Sep 28 21:52:48 2026 Received: from mail-pg1-f169.google.com (mail-pg1-f169.google.com [209.85.215.169]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5EE9D32470E for ; Mon, 17 Aug 2026 05:05:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.169 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786943117; cv=none; b=dTvPJ0GHuE6TdGZSsj5F/0S4YIRkeRzZzEvjIDBiZlOkYSJRokNW9kss6mWl4lGG+o6hYP16/AfLwgUpOopPy8bQ3Y30NAC3oelxHiHw+TVCtzNVmt9kvl3hOF9j84MZbqlZQ+OfjOIgxZ4B649po85hzciT+QIqG0cdLyT5gtI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786943117; c=relaxed/simple; bh=KsN2NJemOVK+q8gWtoYQXOOV0uMG84DgAIswe9hxUCk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=iAKwp1XC0WJ7h4JV+LTudwIvmp/uVwDTgpde0oNK8MxqThpkJvRij6feNQASFZXEVb2RTXalhVCT0ExTV8FNWNtIVkaY4e2A2kMqRisiscJjGMXm3XXKAHx5OpLD3gTnwLBsbT+P4jUGMrrNBV2SPbCt+jV5VypVa4Mq2XakucA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=aIjxrcsC; arc=none smtp.client-ip=209.85.215.169 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="aIjxrcsC" Received: by mail-pg1-f169.google.com with SMTP id 41be03b00d2f7-cbeeaac53a9so2950903a12.1 for ; Sun, 16 Aug 2026 22:05:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1786943114; x=1787547914; darn=vger.kernel.org; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:from:to:cc:subject :date:message-id:reply-to:content-type; bh=iopxSAPngaesoWpELP4kESRIlD5BFKpXn69XPl76vs4=; b=aIjxrcsCEliYLnoWcxqcgO32XWgY4kZOC1+3krERYQnZMpr6iuURZ6nyzmvJkQMWJq IoAxzIot6BjOnqN1A17EG1WOZ4Ty+rbLTbPl5IUL43FkUwRCqL0tZMUT72JaQq+C0ELq H4RgMjWg8RTpwS/JMWAu3/ShMgWjJ5bhYzlzGYPdyi5Fb+7Asco3398Xw7gNCl/y2DP5 KMt5uKZ1JVQ/OzArFC3Vm6eh/3kGab1xcbn0q6bRUKlH8sTdu8X8D1mRqwlthewIx3Gm WgYbev3kuHs3pOT0jp+LvA6E/pGQYtwK6AbaHkyAk4O9a7pyasGLKjbaHqK2q0dS36DK Uclw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786943114; x=1787547914; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=iopxSAPngaesoWpELP4kESRIlD5BFKpXn69XPl76vs4=; b=dfcU6rwmo0cdsIrJlZxt/gxrZBaztGBAFmoHpkjOn881EFIqIHXJZUxyg6CMjMC88K iLGXhNguimA2qUg5nriC6cDwNF+sFKbRu7hZPn3QFtVaz3JQD/BW93MgNwBpTIHOjPTO y4mjSablv0I9CWp+Lfwz8FOQP6aF3x9ozGpKZHdGmSdkUyIXv/HRPiuBpRuVY5A6kFlb WDj955Kj5dAQYoiT0NxVP9Dgv8tjEeXM0zeWWzGdqLbHO3k6T1yb/hcUtg/cH76mq7Wp FV0vQNIdMUBySOCcVrgRnZKCpmnByAx9vQmYu7gC6WP5j/+ZNfVIFBY4dm05pSYcU8Uc Ie8w== X-Forwarded-Encrypted: i=1; AHgh+Rq5YNIZJd8B6gQaY/22xG1cSh/Kpd8afpXOqJOL4EnU52sjKw1ktqnfbOxE576fhFjvwAmllwhkZRffYr4=@vger.kernel.org X-Gm-Message-State: AOJu0Ywhikmvp3/Wx0TslLx4T7np4mqe1Kxnh7U97xBWtB0zxrLZwVi6 tMKybrKQRF+3XY0a47nr+QABmbtbA9fVqibgixivicT+JQduWhkHG0H0 X-Gm-Gg: AR+sD12vGikxcqDGRZvGBZsvZizoUBFF4m6N58fS6F/zQFL2+85mv8FjRqGer2U/eHs w3ZIKnSovP7SjxNi/Txhs3LIYmuKT7V2d9QRorxF01bflUV1vT/ijIlyB2950a2PAaiE8tLU/Q2 zCiBhDGsQX5rMJYvdU/5CtvcnMd+Y5h9wh7K6PifM6kbsVtf7mKVwqcqFCBeE632YgTi4mEreTr +BDc74czmds9PD/s6vAiR8MmL5nnVDowaHp/HtzUcmSbsC4d1RolvirRZuXw4bIAMwZaaqpB3Kj GuRBakN37ytM7e55Zm51Gf0xnF3BK5X5xHyQR12VSmtLmvbcAA+OmrdM4LODQgzDQe0wiHQqQRS CxemENmAubtCMj5/YkyLWStvTm6VFBE8H1OThiTE1QtHqVjBFEEUC+/BGMJXbSDypybrqL8Jmho RbiGsQUPzszXkfV883Bu5neUiHMbTOigadWGV5f698zyAHhRXk91ubkv4ufWmTxtU0 X-Received: by 2002:a05:6a00:3699:b0:846:bc60:5bf7 with SMTP id d2e1a72fcca58-84fddf9180cmr25131878b3a.6.1786943113562; Sun, 16 Aug 2026 22:05:13 -0700 (PDT) Received: from baineng-pc.. ([117.133.183.252]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-8517d267310sm2131036b3a.53.2026.08.16.22.05.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 16 Aug 2026 22:05:13 -0700 (PDT) From: Baineng Shou To: Sumit Semwal , =?UTF-8?q?Christian=20K=C3=B6nig?= , "T . J . Mercier" , Benjamin Gaignard , Brian Starkey , John Stultz , Sandeep Patil , "Andrew F . Davis" , Srinivas Kandagatla , David Airlie , Simona Vetter Cc: stable@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-media@vger.kernel.org, linaro-mm-sig@lists.linaro.org, linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, Baineng Shou Subject: [PATCH v7 1/4] dma-buf: dma-heap: don't publish fd before copy_to_user() succeeds Date: Mon, 17 Aug 2026 13:04:54 +0800 Message-Id: <20260817050457.1005285-2-shoubaineng@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260817050457.1005285-1-shoubaineng@gmail.com> References: <20260817050457.1005285-1-shoubaineng@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable DMA_HEAP_IOCTL_ALLOC allocates a dma-buf and installs an fd into the caller's fd table via dma_buf_fd() -> fd_install() before dma_heap_ioctl() copies the result back to userspace. If the trailing copy_to_user() fails, userspace never learns the fd number, but the fd (and the underlying dma-buf reference) are already visible to other threads in the same process and are leaked for the lifetime of the process. The obvious "close it on the failure path" fix is unsafe: once fd_install() has run, another thread can already dup() the fd, send it via SCM_RIGHTS, or close() it and let its number be reused, so a subsequent close_fd() from the ioctl path can operate on an unrelated file. This was pointed out by Christian K=C3=B6nig on v1 [1]. Restructure the allocation path so that fd_install() is the last, unfailable step of a successful ioctl: 1. heap->ops->allocate() creates the dma_buf. 2. get_unused_fd_flags() reserves an fd number in the caller's fd table without publishing it, so no other thread can observe it. 3. copy_to_user() delivers the fd number to userspace; on failure the fd is returned with put_unused_fd() and the dma_buf reference is dropped with dma_buf_put(), leaving no user- visible state behind. 4. dma_buf_fd_install() publishes the fd and emits the trace_dma_buf_fd tracepoint -- from here on the ioctl cannot fail. A new dma_buf_fd_install() helper is introduced in dma-buf.c to wrap fd_install() together with the DMA_BUF_TRACE() call, preserving the export tracing that dma_buf_fd() provides. dma_heap_ioctl_allocate() is refactored to return the struct dma_buf * directly (returning ERR_PTR on failure) so the caller holds the dmabuf reference across steps 3 and 4. The failure at step 3 is easily reachable from userspace: pass a struct dma_heap_allocation_data that lives in a page whose protection is flipped to PROT_READ between copy_from_user() and copy_to_user() (e.g. via mprotect()). Before this change each such ioctl leaks one dmabuf fd; after it, the fd table is unchanged on failure and only /dev/dma_heap/ remains open. No UAPI or heap-driver interface change. [1] https://lore.kernel.org/dri-devel/175e98de-f414-47d7-81c1-c0fe0a8f7f62@= amd.com/ Fixes: c02a81fba74f ("dma-buf: Add dma-buf heaps framework") Cc: stable@vger.kernel.org Reviewed-by: T.J. Mercier Acked-by: Christian K=C3=B6nig Acked-by: Sumit Semwal Signed-off-by: Baineng Shou --- drivers/dma-buf/dma-buf.c | 20 ++++++++++ drivers/dma-buf/dma-heap.c | 80 +++++++++++++++++++------------------- include/linux/dma-buf.h | 1 + 3 files changed, 61 insertions(+), 40 deletions(-) diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c index d504c636dc29..4c9add51f9ef 100644 --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c @@ -803,6 +803,26 @@ int dma_buf_fd(struct dma_buf *dmabuf, int flags) } EXPORT_SYMBOL_NS_GPL(dma_buf_fd, "DMA_BUF"); =20 +/** + * dma_buf_fd_install - install a reserved fd for a dma-buf + * @dmabuf: [in] pointer to dma_buf + * @fd: [in] fd reserved with get_unused_fd_flags() + * + * Publishes a previously reserved fd into the caller's fd table. + * Must only be called after all fallible work (e.g. copy_to_user) + * has succeeded, as it cannot be undone safely once called. + * + * The caller is responsible for having emitted the trace event + * (via dma_buf_fd() or get_unused_fd_flags() + this function) + * before calling this. + */ +void dma_buf_fd_install(struct dma_buf *dmabuf, int fd) +{ + DMA_BUF_TRACE(trace_dma_buf_fd, dmabuf, fd); + fd_install(fd, dmabuf->file); +} +EXPORT_SYMBOL_NS_GPL(dma_buf_fd_install, "DMA_BUF"); + /** * dma_buf_get - returns the struct dma_buf related to an fd * @fd: [in] fd associated with the struct dma_buf to be returned diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c index a76bf3f8b071..43c32fb28313 100644 --- a/drivers/dma-buf/dma-heap.c +++ b/drivers/dma-buf/dma-heap.c @@ -55,33 +55,6 @@ MODULE_PARM_DESC(mem_accounting, "Enable cgroup-based memory accounting for dma-buf heap allocations (de= fault=3Dfalse)."); EXPORT_SYMBOL_NS_GPL(mem_accounting, "DMA_BUF_HEAP"); =20 -static int dma_heap_buffer_alloc(struct dma_heap *heap, size_t len, - u32 fd_flags, - u64 heap_flags) -{ - struct dma_buf *dmabuf; - int fd; - - /* - * Allocations from all heaps have to begin - * and end on page boundaries. - */ - len =3D PAGE_ALIGN(len); - if (!len) - return -EINVAL; - - dmabuf =3D heap->ops->allocate(heap, len, fd_flags, heap_flags); - if (IS_ERR(dmabuf)) - return PTR_ERR(dmabuf); - - fd =3D dma_buf_fd(dmabuf, fd_flags); - if (fd < 0) { - dma_buf_put(dmabuf); - /* just return, as put will call release and that will free */ - } - return fd; -} - static int dma_heap_open(struct inode *inode, struct file *file) { struct dma_heap *heap; @@ -99,30 +72,42 @@ static int dma_heap_open(struct inode *inode, struct fi= le *file) return 0; } =20 -static long dma_heap_ioctl_allocate(struct file *file, void *data) +static struct dma_buf *dma_heap_ioctl_allocate(struct file *file, void *da= ta) { struct dma_heap_allocation_data *heap_allocation =3D data; struct dma_heap *heap =3D file->private_data; + struct dma_buf *dmabuf; int fd; + size_t len; =20 if (heap_allocation->fd) - return -EINVAL; + return ERR_PTR(-EINVAL); =20 if (heap_allocation->fd_flags & ~DMA_HEAP_VALID_FD_FLAGS) - return -EINVAL; + return ERR_PTR(-EINVAL); =20 if (heap_allocation->heap_flags & ~DMA_HEAP_VALID_HEAP_FLAGS) - return -EINVAL; + return ERR_PTR(-EINVAL); + + len =3D PAGE_ALIGN(heap_allocation->len); + if (!len) + return ERR_PTR(-EINVAL); + + dmabuf =3D heap->ops->allocate(heap, len, heap_allocation->fd_flags, + heap_allocation->heap_flags); =20 - fd =3D dma_heap_buffer_alloc(heap, heap_allocation->len, - heap_allocation->fd_flags, - heap_allocation->heap_flags); - if (fd < 0) - return fd; + if (IS_ERR(dmabuf)) + return dmabuf; + + fd =3D get_unused_fd_flags(heap_allocation->fd_flags); + if (fd < 0) { + dma_buf_put(dmabuf); + return ERR_PTR(fd); + } =20 heap_allocation->fd =3D fd; =20 - return 0; + return dmabuf; } =20 static unsigned int dma_heap_ioctl_cmds[] =3D { @@ -138,6 +123,8 @@ static long dma_heap_ioctl(struct file *file, unsigned = int ucmd, unsigned int in_size, out_size, drv_size, ksize; int nr =3D _IOC_NR(ucmd); int ret =3D 0; + int fd; + struct dma_buf *dmabuf; =20 if (nr >=3D ARRAY_SIZE(dma_heap_ioctl_cmds)) return -EINVAL; @@ -174,15 +161,28 @@ static long dma_heap_ioctl(struct file *file, unsigne= d int ucmd, =20 switch (kcmd) { case DMA_HEAP_IOCTL_ALLOC: - ret =3D dma_heap_ioctl_allocate(file, kdata); + dmabuf =3D dma_heap_ioctl_allocate(file, kdata); + + if (IS_ERR(dmabuf)) { + ret =3D PTR_ERR(dmabuf); + break; + } + + fd =3D ((struct dma_heap_allocation_data *)kdata)->fd; + if (copy_to_user((void __user *)arg, kdata, out_size) !=3D 0) { + put_unused_fd(fd); + dma_buf_put(dmabuf); + ret =3D -EFAULT; + } else { + dma_buf_fd_install(dmabuf, fd); + } + break; default: ret =3D -ENOTTY; goto err; } =20 - if (copy_to_user((void __user *)arg, kdata, out_size) !=3D 0) - ret =3D -EFAULT; err: if (kdata !=3D stack_kdata) kfree(kdata); diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h index d1203da56fc5..d15b2b31d3c9 100644 --- a/include/linux/dma-buf.h +++ b/include/linux/dma-buf.h @@ -567,6 +567,7 @@ void dma_buf_unpin(struct dma_buf_attachment *attach); struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info); =20 int dma_buf_fd(struct dma_buf *dmabuf, int flags); +void dma_buf_fd_install(struct dma_buf *dmabuf, int fd); struct dma_buf *dma_buf_get(int fd); void dma_buf_put(struct dma_buf *dmabuf); =20 --=20 2.34.1 From nobody Mon Sep 28 21:52:48 2026 Received: from mail-pf1-f174.google.com (mail-pf1-f174.google.com [209.85.210.174]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0656832D0E3 for ; Mon, 17 Aug 2026 05:05:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786943120; cv=none; b=MX3UXcyk1TOtTssYMcizybX7JmwSebxkHeQdXaKXQQmigGcUx4fCEAh9CXGGZ1OqT9qpYZ7KUzYzd9jUfo7CYQ+iGuLVQ6hVtBslsxfSsAIgo5r9eoJ5MzYBlX9IjMGvt0ydf6ihMvVW+EQCuVtOF03+X58e5azwXfu7Jqrsl/M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786943120; c=relaxed/simple; bh=ErYC+NBUB1uSMVe7dsSUwt3ETggiJBFdGT3p09rSUlA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=L1iqM+XubinXmhJvcRT7fE06luZCdX0UC+RxGa1aj83MJRVcey62KB4laPZToxOX7y0EHD9cejofGMRwNszV0mzJ1QYQz/coMTanPVJD/pZrgfhM9vfwXCNkP5iK9MdZdPCPKpu22G9RpWm2NvjDYjgoCDRIl7JyGbKVE7PRjz4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=O2iYdAev; arc=none smtp.client-ip=209.85.210.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="O2iYdAev" Received: by mail-pf1-f174.google.com with SMTP id d2e1a72fcca58-84e3007a2b7so2469300b3a.0 for ; Sun, 16 Aug 2026 22:05:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1786943118; x=1787547918; darn=vger.kernel.org; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:from:to:cc:subject :date:message-id:reply-to:content-type; bh=wA2XmPl+hovwGxL3ai/U+yA7AWOU/owR4IcUEcMXDYY=; b=O2iYdAevYt5f4khFQNgP5bu5iMekzcpaFVoh/eGfulEMTn9UNF+KYNGAj56vk/Xe5J uOOqtzH0EO6K7p8vNfUw9vJWjI/iHDdhutTGn/6TjBk1+WPzXKvgDVijfWZZBruDW4tR nkMWI+ZGTIV3paoQSx9VO+ExdUsk3Qrq9vn3DnRlS9mrNyNM7ynhOx1ClzwwlaNY90w9 RB5dg73VoVq7hJs4DkKG2nQMvrHPNYxqdxCe0l6aIcFQNVNgkirANDhegr6HaKDjeaPw PGrcJ85cMgQamjtj6dErJWJoJ/339Q8MGelQnQYEvPbEl8D0pDsCaqEpJHsXVXv50CwL dB0w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786943118; x=1787547918; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=wA2XmPl+hovwGxL3ai/U+yA7AWOU/owR4IcUEcMXDYY=; b=DG3nudbE8NLKpEIcesrhjyY15mfzN0truRv7sBuAX5MvKpu9CnCZgQb7OZA3MwkRu3 SzFAKJVZgNd/IzJxB44+Xxd2qUbXVCdH0qL5j3LAunvAPi0crC2YDSgh2UlfrLCj9AF0 jkZORGYDviV06diAT/fRKoCvRkEGUn15Qg8xuMAFZzoyAMnzR5WejB1K7rLSD6Tgt81a bFj11DTDjmBqF8crj6Gl/rcqdDYjmYng+VOvCaq7rVPJ+qElHlxIRcpa7gRQFEjN0HXH 5HrwjdNV4u7PNA/fWqwCyJXcp2F3bL/cn+V+opnaIo/w/O879un9+9FU9aKuyqiXkDkg TBMA== X-Forwarded-Encrypted: i=1; AHgh+RpRpsSBLRrbV0vV10yNDaVY05Y2iM/TK5phIuoWYMy3CDniLgG4tHWbkBl3qspIVh2/B7l2xUizRgeIimo=@vger.kernel.org X-Gm-Message-State: AOJu0YzsR6V6gwtsI27t98z3Kz0oyuZEFLq0vhpTObXpCoBBWPoQ7pDX PsTM2/iOgW8DcC5Rc13q4tAG6xB2JsEAl9p1hwemN2FCi+EXYyS+TCtw X-Gm-Gg: AR+sD10Z0KKKIeibH5ynQL55R4uUnwHh/ou6Em1lJYoPzxuohqv1J9vTW5EOJJs7bVF MjkUVtsGfwVn7w9P5lzJe0NA7+bFMMp7RdSseIPVSKpqqeAJrpxHcUtyMDMPYKWQzpE+dT8qm1k odi9YkEk5qUXLhphymaZlzIMlbGMw5H+adVHt+OPrWILRiy0LkIle4qIlDdUBGZn8Zktm/lVe48 ZbhNu07WyJl8ZMQW61H3cj4UHJWM0xx5zqLGgA4XPWlN6lUTnWkqXzWBC203gTOQO0VrlyJj2tb D43nNCqPwkSihVtpuPU6Ja1zeYqKYTXNJSjSnBed9qGQ5LxAHyOgjsbyvu3PvxTtknEL08emEZt 4r2IuB2oDuqCNkuEe8nDqIgkbjBqtd+eMEwcsk8l35OIsKlB0i0OsTLou0to5Vmca9+D5LPcJTP wHQORUn0hax+NtMxwXXKM+Ich4xUBQlir/DtXhWv04dgjjw8dOP1SAZiNDg6esEIuN X-Received: by 2002:a05:6a00:94fb:b0:842:5da3:9b89 with SMTP id d2e1a72fcca58-84fde3e397cmr21923062b3a.38.1786943118310; Sun, 16 Aug 2026 22:05:18 -0700 (PDT) Received: from baineng-pc.. ([117.133.183.252]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-8517d267310sm2131036b3a.53.2026.08.16.22.05.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 16 Aug 2026 22:05:18 -0700 (PDT) From: Baineng Shou To: Sumit Semwal , =?UTF-8?q?Christian=20K=C3=B6nig?= , "T . J . Mercier" , Benjamin Gaignard , Brian Starkey , John Stultz , Sandeep Patil , "Andrew F . Davis" , Srinivas Kandagatla , David Airlie , Simona Vetter Cc: stable@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-media@vger.kernel.org, linaro-mm-sig@lists.linaro.org, linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, Baineng Shou Subject: [PATCH v7 2/4] misc: fastrpc: don't publish fd before copy_to_user() succeeds Date: Mon, 17 Aug 2026 13:04:55 +0800 Message-Id: <20260817050457.1005285-3-shoubaineng@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260817050457.1005285-1-shoubaineng@gmail.com> References: <20260817050457.1005285-1-shoubaineng@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable fastrpc_ioctl_alloc_dmabuf() calls dma_buf_fd() which installs the fd into the caller's fd table before copy_to_user() copies the fd number back to userspace. If copy_to_user() fails, the fd is already visible to other threads in the same process but the ioctl returns -EFAULT. The existing comment in the code even acknowledges the problem: "The usercopy failed, but we can't do much about it, as dma_buf_fd() already called fd_install()..." Now that dma_buf_fd_install() is available (introduced to fix the same issue in dma-heap), apply the same pattern here: reserve the fd with get_unused_fd_flags(), attempt copy_to_user(), and only on success call dma_buf_fd_install() to publish it atomically with the tracepoint. On copy_to_user() failure, put_unused_fd() and dma_buf_put() cleanly unwind without any user-visible side effects. Fixes: 6cffd79504ce ("misc: fastrpc: Add support for dmabuf exporter") Cc: stable@vger.kernel.org Acked-by: Christian K=C3=B6nig Acked-by: Sumit Semwal Signed-off-by: Baineng Shou --- drivers/misc/fastrpc.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index f3a49384586d..c5143cd25767 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -1709,24 +1709,20 @@ static int fastrpc_dmabuf_alloc(struct fastrpc_user= *fl, char __user *argp) return err; } =20 - bp.fd =3D dma_buf_fd(buf->dmabuf, O_ACCMODE); + bp.fd =3D get_unused_fd_flags(O_ACCMODE); if (bp.fd < 0) { dma_buf_put(buf->dmabuf); - return -EINVAL; + return bp.fd; } =20 if (copy_to_user(argp, &bp, sizeof(bp))) { - /* - * The usercopy failed, but we can't do much about it, as - * dma_buf_fd() already called fd_install() and made the - * file descriptor accessible for the current process. It - * might already be closed and dmabuf no longer valid when - * we reach this point. Therefore "leak" the fd and rely on - * the process exit path to do any required cleanup. - */ + put_unused_fd(bp.fd); + dma_buf_put(buf->dmabuf); return -EFAULT; } =20 + dma_buf_fd_install(buf->dmabuf, bp.fd); + return 0; } =20 --=20 2.34.1 From nobody Mon Sep 28 21:52:48 2026 Received: from mail-pg1-f171.google.com (mail-pg1-f171.google.com [209.85.215.171]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CC0AF314A6F for ; Mon, 17 Aug 2026 05:05:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786943125; cv=none; b=RYFB9hEwSC7zO18SDzhYKYwVd38VIpt68sHAp1sp1ST2JAkNpVcBkDHMeCLZ+Skvgev+iiFBzheZYxAMudC3uzcx5G095qGoKQFD7PvY/VtYp596EqpEukkW+R75SX5HSIWgSAUDh44e0wf2IcN8Ge5dJupYg+8fyixAdGS7iZo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786943125; c=relaxed/simple; bh=XyfkbQZ7xpA0fIVTmvCcxzb8iQyPGQl8C+uZaIEtryE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=C6Z52lGTEXnxyJbQFHH7Okg34OaA69dY0EyHcbCxFiY15EkZE0BiZFa6kCPeKLQKQyY9+SjVKhIY62Vw0ZwQPGrda0Bie+JsGmv/p72GrngIJdNE+X7YC019EicmaqNVJeoXSkCkOCnwqJfJlsvUNfwp5Jk9744CdWuXJ67ihjs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=nqrjZPQn; arc=none smtp.client-ip=209.85.215.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="nqrjZPQn" Received: by mail-pg1-f171.google.com with SMTP id 41be03b00d2f7-cb5b8572b70so3483996a12.2 for ; Sun, 16 Aug 2026 22:05:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1786943123; x=1787547923; darn=vger.kernel.org; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:from:to:cc:subject :date:message-id:reply-to:content-type; bh=TnRbd61Koh8fAk6B/yQ0KzLTDaUh5Tr2u2+ZL0OT4NI=; b=nqrjZPQn4gWg1T2uIQD03HRwSp6nNMs9LOYTJbOnJvcvLViv1OR6BPI2tFwbj4G6wq 3KXdtiSKS7VC0OZtN7ZlbIxt4kx4xven1VX3AXJVx3RYzhpdMiKuN2v+2ujlgwJATzpg 3LG7UPZCkWQAFWHemuZRJ/Bte3pc3pGYwL6596KHckUGuRqUZdXgmVB1Tuhgmi2vCyFJ d7blS8iHjAAPC4SjmwWGllS2QA1d/OKynrSD8SIBmvnp2Wmr4mwcALiwEjQ4HI0dhrYF n0tUhcEW4HiEDsNk+aqq4W87BmlTBMlnO9xSk8g6hmC5+rfeax+RUce+15rn2f22Gbg7 W7fA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786943123; x=1787547923; h=content-transfer-encoding:content-type:mime-version:references :in-reply-to:message-id:date:subject:cc:to:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=TnRbd61Koh8fAk6B/yQ0KzLTDaUh5Tr2u2+ZL0OT4NI=; b=AYCd0tmrEJg7AbMVle6AIChD2rFkrMEUe+wL1/ik2xJNpu/0NccMHXJHnhhGDnInRl f1xjIyZdvj4IDkOxl8asDi0JR1Zh3bxb3ItaiRTDt6KD4yyrtxzGbRlTVo3QBv0ujHPo iconvq+SggiR2AAcBA5ktacW9K52jfVnLsppjlegq/q05LkVviLuBbeNgvSZ4mk7CufM GrtKq4bedPlmg674P868KaIWZKf5/caguOIRN9XcoevJgIkRKPx1u7uUfv9dOdBdwsl3 //0QztNXqMJ6rPmoxsRqHhCA6ZSqe6KLxqdVF5cYMrezMswy10hEfV3yMGyB8S51F5Q/ dLZw== X-Forwarded-Encrypted: i=1; AHgh+Ro+c64wVn0D+GMMW9mZMEKZfRPtdV/6IEjv45PriKQBgALtgz3QGBTsDUOnAhx/4hEjTFx04gXwTg8mhfE=@vger.kernel.org X-Gm-Message-State: AOJu0Yy6JYlYI7CxGvX5PbUhotDrnXxhnUG9fFbefjB2HtqKeC9kU/bt hsnj2dFnm481aTQ5XJBS82+B90aonv5EVFI/dDKN5z66JbjTQ6FGqaHK X-Gm-Gg: AR+sD11d4pmGKQPtSL2Asimn/Amy2jQa2S3vqJE8iyv0clWRWOBP6NQikTh55uac0hK gpipC4VGY7BHCiuL5aEyOAuc0Eyabcn17naaUhN/nGf8furBltreMaLdl2Wsn9XzuJpxP5luaLt sS7d6d2rNkKQFKD7yWyuT9A7EmXptL3iF1L2cIbp45/ABvgLoFFrHcHmP/nLZy6y/IYs9v1XgQZ IAorbm3XX9pVPI+NIiyvFPNbct/Im63awkpBMQVDjbQeKplqPBrHSscW8YJAuM2JBQACVTl0qe2 7Eygjvx130wyobIwpbQwlHecKg2ujWer7IiqkB/j9+c+KDeanBESnPpljNqcMeF+VxC2gN9geCm mPwntOhG0+M389ezma3Md3ETxTg2uJUEFVmTTSMb4Xg4N7gU4zIekRKkBmT+1iyqEgKoWyHyKIw undRe5jmo9eM2XidzNltN0QzMudrL4EEObNg4CsQ+kWyDfrkyiQQ3iJUeTYCAHluM+tRdU2DsCh dY= X-Received: by 2002:a05:6a00:3907:b0:847:e791:d5c5 with SMTP id d2e1a72fcca58-84fde2ded84mr22165983b3a.35.1786943123096; Sun, 16 Aug 2026 22:05:23 -0700 (PDT) Received: from baineng-pc.. ([117.133.183.252]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-8517d267310sm2131036b3a.53.2026.08.16.22.05.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 16 Aug 2026 22:05:22 -0700 (PDT) From: Baineng Shou To: Sumit Semwal , =?UTF-8?q?Christian=20K=C3=B6nig?= , "T . J . Mercier" , Benjamin Gaignard , Brian Starkey , John Stultz , Sandeep Patil , "Andrew F . Davis" , Srinivas Kandagatla , David Airlie , Simona Vetter Cc: stable@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-media@vger.kernel.org, linaro-mm-sig@lists.linaro.org, linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, Baineng Shou Subject: [PATCH v7 3/4] drm/prime: use dma_buf_fd_install() to preserve export tracing Date: Mon, 17 Aug 2026 13:04:56 +0800 Message-Id: <20260817050457.1005285-4-shoubaineng@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260817050457.1005285-1-shoubaineng@gmail.com> References: <20260817050457.1005285-1-shoubaineng@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable drm_gem_prime_handle_to_fd() open-codes fd reservation and install using get_unused_fd_flags() + fd_install() directly. This bypasses the DMA_BUF_TRACE() call that dma_buf_fd() emits, so observability tools relying on the trace_dma_buf_fd tracepoint silently miss all DRM PRIME exports. Replace the bare fd_install() with dma_buf_fd_install(), which wraps fd_install() together with DMA_BUF_TRACE(), restoring full tracepoint coverage. No functional change; the fd lifecycle (get_unused_fd_flags =E2=86=92 work =E2=86=92 install) is already correct. Note: this patch depends on dma_buf_fd_install() introduced in "dma-buf: dma-heap: don't publish fd before copy_to_user() succeeds" [1]. [1] https://lore.kernel.org/dri-devel/20260714114654.3885457-2-shoubaineng@= gmail.com/ Suggested-by: Christian K=C3=B6nig Acked-by: Sumit Semwal Signed-off-by: Baineng Shou --- drivers/gpu/drm/drm_prime.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c index 9b44c78cd77f..fe3436d1235d 100644 --- a/drivers/gpu/drm/drm_prime.c +++ b/drivers/gpu/drm/drm_prime.c @@ -524,7 +524,7 @@ int drm_gem_prime_handle_to_fd(struct drm_device *dev, return PTR_ERR(dmabuf); } =20 - fd_install(fd, dmabuf->file); + dma_buf_fd_install(dmabuf, fd); *prime_fd =3D fd; return 0; } --=20 2.34.1 From nobody Mon Sep 28 21:52:48 2026 Received: from mail-pg1-f173.google.com (mail-pg1-f173.google.com [209.85.215.173]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B476232B116 for ; Mon, 17 Aug 2026 05:05:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786943130; cv=none; b=Upg+/GPAlUwAQ28q/Jx0nfLi5BCtg9Pzjw+rrxCaJiq44R/+Q15MFR8mbKFkEoBUIjLGG8wscG47sPGgImxcDEDZuHetqwbRM/SE7PXaJfXjsLqGCg7YZ62e57L2E32Ap7/+aLhFQO7QuxzauMt/BuRDDF+fNffU1wmWbbOoNUM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786943130; c=relaxed/simple; bh=75OpRWLkQ/Xc518yrBO/o+kJMGpZhe1F2xhM+Ifk9Tw=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=ZR4eoSJwaGegVUEiU7LUPCNUvYGGq8jTkdiuoRyb95H4oJ9MQVhHMJbAEi+dfbMH+MxP/nNj2SiUYoGZD9afeQ4nrNP35AT3xICpeB4mN/F1L5SCvD+ZQ1LM9RrgNZZcfXFTd4d9zrWSM9/rFcBYVfVx28dhYL4o7vK1oogXTtA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=qz4k9VEJ; arc=none smtp.client-ip=209.85.215.173 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="qz4k9VEJ" Received: by mail-pg1-f173.google.com with SMTP id 41be03b00d2f7-cbb7926836eso1952122a12.3 for ; Sun, 16 Aug 2026 22:05:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1786943128; x=1787547928; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=ziVl5gmafK8z7JTYijjTnWVXlXKGtu8Xos512S76WIk=; b=qz4k9VEJPi7zbcrAfEsUrme08mFIqGYO+trxS30HF7DR/HMNtqn8ELA8gUlfy7t4kk A2RyMTWcLEPy9Lmg0GNga8nNjHRYCUDkzutLSfLQTa3dAnx7gkOUYUAxSTkIncUew/5E QH2l34t+J2F8vbkQ2ZXzmd22BG2vHQIVhsZ88FWneWjHhR14PI0fGQKVqQ8e1wwSucYW rcGUQ3cBJVxZjLOxAAp6SEyyBcLmPvVntIGX8X672IoDJmHirMyYf4Tm5JDlYw+tEaFL SBByfA5m3Anb9BNtqKcs2wKwgkZ00qJ2znZFWw4o5bhgl25TRWvwyUUB2K5WW3+JF8xr 0Vnw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786943128; x=1787547928; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=ziVl5gmafK8z7JTYijjTnWVXlXKGtu8Xos512S76WIk=; b=TI+uEUrYMW4ZVFR3KUezr1Kumr7SwNzcouYfenSI/DaZzGOT7LrFqMeg+eTRdorCmF VzFy5lZZkw5Vo5cZwcwYEZajn9pHJhe/5Z65L8Frgt3slcfJPe6obhIA5Fu9VTX7ONxl MGYYXqeB8sSw30yt4acY9+8OjeIizGnWIBJkO+xguUff77D7YtGb5Cs6DpJfvN5MT9AA jJw1EEQBUS0/S3+F3bvjrq29SoKGfSov1LDGcyhTvCtskT+Ewep+cYtf7Fj+POXrefXM 8i8ZF0VzA0fZsgl50y6AqPK/KhhPgz8yGe+awYK+1D90ClS7edSOwCIARrBuASb0f/zt nMcQ== X-Forwarded-Encrypted: i=1; AHgh+RpVvALju1og7X415iY2j5vDaYlEjYmiYTMqNnZo4bS/wWzF/w/wPY8FIShTR2sIBJXtMZDZ/+rdc9KCJK0=@vger.kernel.org X-Gm-Message-State: AOJu0YxQGmf+pGWRZoOOhpwQF5ILgaCtKrixPadWsr8MkmaBjQlLwfxn 8v6BNEDyfDEl4yR69AxRL3OzU11Dwbh+bxLx/qej6iHVCcOCHeqCf9Wg X-Gm-Gg: AR+sD12kpLXki2lnC8ShmLoL08hauvEXHgoE/r1pZOixaxJKOFy0/l7n9gkx9JkweAb huVMUpToPCJ3L6iQb9bH0yEqbBgK3X+KO/vaBwp4NJOeXYiAH0vcWOWrDF/Ep2DKt00DS9B3hQ9 ZtRWTvkMDKLbq1nBJplV8Hxp3AZXxag/Ymt0SABuY+LoNurpO3AK+R5egI6zeLey/fneTUcAHnf jdvXN/8QIWvXRyFwmK9qLp6g9ddzQQA56FUSd6eRVfGa+/jXXnEAifzhXIbXXZ/t4dN0Y2iQ93X heuiOavhBF9eNGczuCMZSact93+ppSeBzCKbgM4ukdtoHpmT4nWlyVyXe7zZXoagOnJJLQ9FY01 uDdMdFV6KL53T/YfDgm20YjVRt+APZm1XgjDBQXzGV/0xvplZDM5Remiq4s8xYypfnKTvDKI+Hb Av0kt/ytfHOAVQY96ylxZm6DwBUNKkUTzWUQ8cJHB0xUWCAkhyS6usD/WFEpRwN1rC X-Received: by 2002:a05:6a00:1f03:b0:846:bc81:3e29 with SMTP id d2e1a72fcca58-84fde365255mr23307379b3a.2.1786943127867; Sun, 16 Aug 2026 22:05:27 -0700 (PDT) Received: from baineng-pc.. ([117.133.183.252]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-8517d267310sm2131036b3a.53.2026.08.16.22.05.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 16 Aug 2026 22:05:27 -0700 (PDT) From: Baineng Shou To: Sumit Semwal , =?UTF-8?q?Christian=20K=C3=B6nig?= , "T . J . Mercier" , Benjamin Gaignard , Brian Starkey , John Stultz , Sandeep Patil , "Andrew F . Davis" , Srinivas Kandagatla , David Airlie , Simona Vetter Cc: stable@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-media@vger.kernel.org, linaro-mm-sig@lists.linaro.org, linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, Baineng Shou Subject: [PATCH v7 4/4] selftests: dmabuf-heaps: add fd-leak-on-EFAULT regression test Date: Mon, 17 Aug 2026 13:04:57 +0800 Message-Id: <20260817050457.1005285-5-shoubaineng@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260817050457.1005285-1-shoubaineng@gmail.com> References: <20260817050457.1005285-1-shoubaineng@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add a test case that verifies no file descriptor is leaked when DMA_HEAP_IOCTL_ALLOC succeeds internally but copy_to_user() fails to deliver the fd number back to userspace. The failure is triggered by placing the ioctl argument in a private anonymous page and flipping it to PROT_READ (via mprotect) between the kernel's copy_from_user() and copy_to_user() calls. With the buggy kernel the ioctl returns -EFAULT but leaves an extra open fd in the process's fd table; with the fixed kernel the fd count is unchanged. This serves as a regression test for: "dma-buf: dma-heap: don't publish fd before copy_to_user() succeeds" Suggested-by: Sumit Semwal Reviewed-by: T.J. Mercier Acked-by: Sumit Semwal Signed-off-by: Baineng Shou --- .../selftests/dmabuf-heaps/dmabuf-heap.c | 113 +++++++++++++++++- 1 file changed, 112 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c b/tools/tes= ting/selftests/dmabuf-heaps/dmabuf-heap.c index fc9694fc4e89..1d49df671919 100644 --- a/tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c +++ b/tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c @@ -390,6 +390,116 @@ static void test_alloc_errors(char *heap_name) close(heap_fd); } =20 +/* + * count_open_fds - return the number of open file descriptors. + * + * The fd opened by opendir() itself is counted, but since it is opened + * and closed within each call, it cancels out when comparing two counts. + * Returns -1 on error. + */ +static int count_open_fds(void) +{ + DIR *d =3D opendir("/proc/self/fd"); + struct dirent *de; + int count =3D 0; + + if (!d) + return -1; + + while ((de =3D readdir(d))) + if (de->d_name[0] !=3D '.') + count++; + closedir(d); + return count; +} + +/* + * test_alloc_no_fd_leak_on_efault - verify no fd is leaked when + * copy_to_user() fails during DMA_HEAP_IOCTL_ALLOC. + * + * The bug: dma_buf_fd() called fd_install() before copy_to_user(). + * If copy_to_user() then failed (e.g. via mprotect), the fd was + * silently installed in the fd table but never returned to userspace. + * + * The fix: reserve the fd with get_unused_fd_flags() first, attempt + * copy_to_user(), and only call fd_install() on success. + * + * We trigger the failure by placing the ioctl argument in a private + * anonymous page and flipping it to PROT_READ before the ioctl. + * Inside the kernel, copy_from_user() reads from the page (reads are + * allowed under PROT_READ, so it succeeds), but copy_to_user() that + * writes the fd number back faults, returning -EFAULT. We then + * count open file descriptors before and after; with the bug an extra + * fd is left in the table. + */ +static void test_alloc_no_fd_leak_on_efault(char *heap_name) +{ + int heap_fd =3D -1; + int fd_before, fd_after; + int ret; + long page_size; + struct dma_heap_allocation_data *req; + + ksft_print_msg("Testing fd leak when copy_to_user() fails:\n"); + + heap_fd =3D dmabuf_heap_open(heap_name); + + page_size =3D sysconf(_SC_PAGESIZE); + + /* + * Place the ioctl argument in its own private anonymous page so + * we can flip its protection independently. + */ + req =3D mmap(NULL, page_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (req =3D=3D MAP_FAILED) { + ksft_test_result_fail("mmap failed: %s\n", strerror(errno)); + goto out; + } + + memset(req, 0, sizeof(*req)); + req->len =3D page_size; + req->fd_flags =3D O_RDWR | O_CLOEXEC; + + fd_before =3D count_open_fds(); + if (fd_before < 0) { + ksft_test_result_fail("count_open_fds: %s\n", strerror(errno)); + munmap(req, page_size); + goto out; + } + + /* + * Make the page read-only so copy_to_user() will fault. The + * ioctl must fail with -1; if it returns success the test setup + * is broken (mprotect is synchronous, so there is no race). + */ + mprotect(req, page_size, PROT_READ); + + ret =3D ioctl(heap_fd, DMA_HEAP_IOCTL_ALLOC, req); + + /* Re-allow writes so munmap can clean up */ + mprotect(req, page_size, PROT_READ | PROT_WRITE); + munmap(req, page_size); + + if (ret !=3D -1) { + ksft_test_result_fail("ioctl returned %d, expected -1 EFAULT\n", + ret); + goto out; + } + + fd_after =3D count_open_fds(); + if (fd_after < 0) { + ksft_test_result_fail("count_open_fds: %s\n", strerror(errno)); + goto out; + } + + ksft_test_result(fd_before =3D=3D fd_after, + "fd leak on EFAULT: before=3D%d after=3D%d\n", + fd_before, fd_after); +out: + close(heap_fd); +} + static int numer_of_heaps(void) { DIR *d =3D opendir(DEVPATH); @@ -420,7 +530,7 @@ int main(void) return KSFT_SKIP; } =20 - ksft_set_plan(11 * numer_of_heaps()); + ksft_set_plan(12 * numer_of_heaps()); =20 while ((dir =3D readdir(d))) { if (!strncmp(dir->d_name, ".", 2)) @@ -435,6 +545,7 @@ int main(void) test_alloc_zeroed(dir->d_name, ONE_MEG); test_alloc_compat(dir->d_name); test_alloc_errors(dir->d_name); + test_alloc_no_fd_leak_on_efault(dir->d_name); } closedir(d); =20 --=20 2.34.1