From nobody Wed Sep 30 18:00:38 2026 Received: from mail-pf1-f172.google.com (mail-pf1-f172.google.com [209.85.210.172]) (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 F2DD941DDFD for ; Fri, 7 Aug 2026 10:12:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786097525; cv=none; b=MyzcvRhWMPxP6the+D+LEVe8/HFwQK66pRDpZyAoXjaU6IE8VkUokAHd1EeLQ3Zk8CF/qIX6xv9dfmSluSXSv+u33kUUH0NUiR8opeXnGSF8kmCHmMb8w3SyKcfJ0+bTe7iO3BTED4hB1/M9CwYZw9g++XrTJa2ofuYnbdJ1r/M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786097525; c=relaxed/simple; bh=lb5lsOeFj44VvYqr0e5zyDhlpbvgh8japzWZ8lWhj9k=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=PPSYVLjw6MwFBhEbcBLG5BpyhL7gyG6rxX/EB9hrYz1KZUiPhj3nX8dsAYt+/BNkdS22Mir9ogP35cFuym6BgcwVcyasP04gsV5PnMqrw8+LMA0EUpUmqUuG0B8M8mS11Vipoy1IWfmJeFfd+UHJLiL+RJYIAXbGCJyBmZtZG0w= 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=aEFCj3G+; arc=none smtp.client-ip=209.85.210.172 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="aEFCj3G+" Received: by mail-pf1-f172.google.com with SMTP id d2e1a72fcca58-84a2c90e383so1484573b3a.0 for ; Fri, 07 Aug 2026 03:12:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1786097523; x=1786702323; 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=8IRM8cZuTQT295+YDoKUSZ1109m/5RG3rOLisZSSj50=; b=aEFCj3G+erGatnpfzZVslj1rY8fdhJb2ray9rg9mxUa55xeuNXk28Fz8hp7VdGVsoR URhM5/DKpY9T1RUv+FksJYgwROzO6zW0CXdqdCgd4NfiGvmLreeYGl0V7WwIaWqv0zLV /wHBUwhnq7XVj/qCaQWYVXC+mwNjuHbnvRKuPd0tYlEWQr3xJLaT7gkA9vCFmfHruo81 MIEQYu16v+9n3gXR4b4Wu1vNw7z0a6Os27SRwg+VaTTLshlT7sRYDWiu1KhnSLKmbeu1 QMOBcErT9K+T3tf7tkoscVSV7KYC0DvmpVD1QyZuryJYqePxptkGvOYLpRrQtd+RsPec kO/Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786097523; x=1786702323; 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=8IRM8cZuTQT295+YDoKUSZ1109m/5RG3rOLisZSSj50=; b=ScI5udgdDT1XdiYcgz0MZ9x472DF/05VgwS2AG+Rw1TLj8ql5P0K1Kmzbat8HXKv8c QSZ/n7CiUS8+5jm1yheKsU/uwk3cScpQC/y5O74am2bZeYJuGVD9cj+WVDnc4VS3sZjb ICiIPOe1XZPjuVh7k0H28y/AJbggOvkFTHWrb5Xf8R3+kImnNg/6pi//CEnQdcempsen Q/LYxVU8apfAWZaOiMYDApa3k5T8DIFq6dCt0fhqnt+LUAtEvYpO14saLUwNRxHmBTAh WZ/FSp3SA3B5iCKbQ6Tx6HE4tW7axSMLMYASpIaQNT9+ipDt+12yEAOrCtrXO2AKHHWI OxrA== X-Forwarded-Encrypted: i=1; AHgh+RpUPgLYMOXh4194hsa0kTspVWu6upfono8I0BDFHEA60icXsPhwO3cL0oJ2vo8bAzhr83nk6TDq4IyVigo=@vger.kernel.org X-Gm-Message-State: AOJu0YyFWNuadhBNFG0cWPhaScPwECLqRSxyJt9lCBOQvjW4W2UOD8V+ XHdL98nHe6+9p1Hj2eID+rZWJF8plbE28g2kj8E7LdM5sasBLM3SCArT X-Gm-Gg: AR+sD109cBTkLx0bzZ2qh84/tOk2jNvuZZ7Mn543R+nqNpiu3uOGFFwYkaXjMtVamc4 xT2Fb3qPxK54fOCgGRph8SRnTPBOR9wPPrpHlynMoZrovkz0x9uGnfJOZ52yzl6tG+aFyirMBwn 2YLmEqgFDA353f9jDv9lJKJ0ERDt0hyJikKWKXOzoZg+iH8NL8lo5LwjoNylsX+hiNgptXs8xXI 2NP277om+Rk1WJTyqbRn6VQpK2htJFESelQZ59rspCo/gkSiBe0UoJ7v1nGVtpw3GkQ92xpduM/ YEMCAFMY5fD+wx8pTMq38Ig6g4sD59/aH7QfhkIWIU+T29UxrQjiauwjYb1ZADofwdGhgWZ3gGI hZbNa5qYBLEv4NyZKf9ZRQ3YNmcj1+2uyChjQ5egVBA1hte619lMWOmlUqDXsSXYdbefZZKBjkr QRPCW3tSECvG1fvKMQ+C3L6F07M4jldKSCtv1jemj00wrG0yYDlW3awR8nDvhjVl2Y X-Received: by 2002:a05:6a00:2ea5:b0:84f:3dc2:31c3 with SMTP id d2e1a72fcca58-84f47dd0b04mr11913332b3a.15.1786097523035; Fri, 07 Aug 2026 03:12:03 -0700 (PDT) Received: from baineng-pc.. ([117.133.183.252]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-84f5a5528adsm797510b3a.45.2026.08.07.03.11.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Aug 2026 03:12:02 -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 v6 1/4] dma-buf: dma-heap: don't publish fd before copy_to_user() succeeds Date: Fri, 7 Aug 2026 18:11:37 +0800 Message-Id: <20260807101140.1357218-2-shoubaineng@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260807101140.1357218-1-shoubaineng@gmail.com> References: <20260807101140.1357218-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 Signed-off-by: Baineng Shou Acked-by: Sumit Semwal --- 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 Wed Sep 30 18:00:38 2026 Received: from mail-pf1-f173.google.com (mail-pf1-f173.google.com [209.85.210.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 B5AD2422E2E for ; Fri, 7 Aug 2026 10:12:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786097536; cv=none; b=SSMv8acQOr8pS/eM9cfkxY6mGKnbfRV33Q4n+t71rW+IDru4Tt9wzNcI+cTrOlN3JAvoVcHw5O/Oz+3hlLPcU3v1coobKHSPWlnsFwK0olNe1VwcLrFPq7Z8ToiqW8Yn424gqpLa0qLGCITrEUOP9Iish91jEB1UKWMQd8u6kk8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786097536; c=relaxed/simple; bh=2Wi3i4Vjg7+AxOlXMBs+6tkx40vpBZwTeE7t+8e81gs=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=CratnAUDuAW+TZS1Ewi4Tg4fyCU5F0JuBjJ3skKudAJc9GZujuSP2nSaygTkimEfm2naMJxlFnSlOb9tQlLrAwm1wUxzPRP2zpTUc+wfHQYNxljWARu4pOfpTH7gQH5h/wYlKIcQrcrzyUIJ+Cmy+EFv7PwqfyjrZOhGyNhaDQQ= 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=puvvLBL7; arc=none smtp.client-ip=209.85.210.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="puvvLBL7" Received: by mail-pf1-f173.google.com with SMTP id d2e1a72fcca58-848479c9bd5so2910367b3a.3 for ; Fri, 07 Aug 2026 03:12:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1786097534; x=1786702334; 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=3EaYXPThWNdkG4MwcQhWQJEAKHoDeZpU3BU1Rq69yw8=; b=puvvLBL7zbmfgGrJ8iirK48syq6zTRzaACoVhgnLqWomGJRuomlXJhC1CGW50Od4FJ TyR8SrHBiHeFmHzyylwWz9V/LMX9I7fexp1sxgRGgPfeAP0DjuhbG0vJj+9R2qiCrz3y E5EKU7ue24vQhsG+nRX2l/p0U1WBxkb8F5RozkKcAb6EhOhHXOKRZ2JSPKfI3zPxQ0DM kKABw/AC9OJSh5DfYmqU/Gza3o15dq+lbm4sPtM6hINu87pPtnMcHL01SJw8MuUVlafc 1eHolMs/ySrVXlMsKPZlgGZgc3mRjOyVrV1g/L4XXiPnal6C4LlR/YnN6c+1EED+DR4z bSHA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786097534; x=1786702334; 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=3EaYXPThWNdkG4MwcQhWQJEAKHoDeZpU3BU1Rq69yw8=; b=BF+FnisfDhbfC6oG52CUTUrvjY7kPaiVYYuGncZW1rcCj4ZSsWQJOeXerMwmKCF7fw 21EYdnPyuypf67V3YBnVu3oFHQCDxObhdwivK5hd1Olk/1oGlCpz+UYJs4AWDC0lxmB5 X14S2ztFBHxHORCsUc9ZiLJ7IMjkddsiJ6RLW7u2AabgZTdpHJ4y4Ouvg/t4t04z6wkb ZqpOWunC16MKCs8XR5NfJEppLuYne5pLxjvNpcqRjcA8p/VZ1QzjpL22by2f2uCRXp6s YFtWzJAVXGWCaA9/gFYA9q+9SJqsB7OiSUFhcr0jqV0or5vBHNAvVXphFq344LDLzNKP efcA== X-Forwarded-Encrypted: i=1; AHgh+RrgVZDaH/x7a6XxJkjHt4iTnCcC38+c16HH+UJvalYjr3hzx5yv1IWqQfJwGagNRUivtZCWdnsTby57a6c=@vger.kernel.org X-Gm-Message-State: AOJu0YzwHQkLEjpVrAWT5HLl/CQHk/bdErL20349EhDbSpb394JCWJPT hYiz6g5KVlXsZTP76rC/LQpp7xDEx0YDJHFfzFZx0tF/IqV+yeb+DIZk X-Gm-Gg: AR+sD119MX2XMXvxvMfOq2xAahRqvzvKRlZ9UIegRvUzn5dpDvVIjICOkKfxgRtNuO4 Jiac+ZdbBFpPx8A4IY1Hi2QM3aJ+iBu2wbB4RlZulwQzMUQDzbLmbW1NUnO2CuQiLaKXMn2h8DH 4yotyRuFdsSKWUOGU4wSE34iBXL9pol1RV/+3EPn4dJl0/30sYqCVRKiqNvdWt5lS8ra4ecnc1q m1dINepWZRzKEKWktxHf+KqdcHoYg9yUeBUHUZaGJLm+vE7nAayHEVRy3uqz3TDovhL0c744OzS cdX8n8P6M08+XHov5xpi0lQXf+dUfyn4inKKUY57w821kmgUH8W1KAz6KhoO9/SOV7gduQDZ45E Lk1gIJnh9YkV2mNw14y4xN+WJMYvouH5ks+QSoinx1pxxSVXLBEC/Vj25QRsw9j8iueqvKq98Je ZSe113Gs9JLBmqW3k3juPbeBLe8vqtykHgtZT5tzSBVIcCZV95RZEMJqDmBQx/5YTB0FZwsn8yl kk= X-Received: by 2002:a05:6a00:2406:b0:845:a435:a2eb with SMTP id d2e1a72fcca58-84f2e094eacmr22879939b3a.31.1786097533847; Fri, 07 Aug 2026 03:12:13 -0700 (PDT) Received: from baineng-pc.. ([117.133.183.252]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-84f5a5528adsm797510b3a.45.2026.08.07.03.12.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Aug 2026 03:12: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 v6 2/4] misc: fastrpc: don't publish fd before copy_to_user() succeeds Date: Fri, 7 Aug 2026 18:11:38 +0800 Message-Id: <20260807101140.1357218-3-shoubaineng@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260807101140.1357218-1-shoubaineng@gmail.com> References: <20260807101140.1357218-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 Signed-off-by: Baineng Shou Acked-by: Sumit Semwal --- 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 Wed Sep 30 18:00:38 2026 Received: from mail-pf1-f180.google.com (mail-pf1-f180.google.com [209.85.210.180]) (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 3135C41DDFD for ; Fri, 7 Aug 2026 10:12:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.180 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786097542; cv=none; b=jSB1vsvenDSDvkFBBZGReeAbYpM45X/JfcyyM1Dwq7fPUcKsl6as9TtN9aT4FNBamx7ku5Ld2NGG1S+98NHxJTCeuQO3L6K6Iu7E52rRqmnErkaYWrpkgTLFXiVORxhmsj9lW1DkCMRvLBSf625JKUZ2DSdbHdeq3N4S7YGyhPY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786097542; c=relaxed/simple; bh=kYA5RbCeLTsX+J20uD1xRq8xVWSem8VdkEpw2oXKluk=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=Yb/5vyef+UNwWPzgxXipcDwBdrzz601GCBiBLXP+9xFcc3qYL4Ym0iogVR2Dfl+qn7Lh+jLG/hShZOiprdr1TGyqXd6En3Zojo4EYL0dljeEDBjJtpMgJkfNc/jHAyW7EsUqHGwQDcuuKX1JOIQ4otiqZCBJXI/pM6K51gQI99w= 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=ACjJUCsp; arc=none smtp.client-ip=209.85.210.180 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="ACjJUCsp" Received: by mail-pf1-f180.google.com with SMTP id d2e1a72fcca58-84a4d8fd6ecso3870491b3a.1 for ; Fri, 07 Aug 2026 03:12:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1786097540; x=1786702340; 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=8LdAoJKwXyAPy2Oxe1p5of7f27uz/x1w5QiaYqvn624=; b=ACjJUCspvxE7E8qbuN+1UtHZd5TKL6YYgv6D24XFFGVgccuLdhI4L7gZLUxM9BkCE6 v/OFRzQNOiAzPoiUxsQbRRFo5UB9NwO9dnH6lCJ9MuAHSqkzm+Mf+7LO/gWzUUGgfTj1 Khr33k1t2K+f0TbSOiQWogejw7i1BtjQNHL4gyXicVS1SlFybBjnc+24PzRv4O5rjXwp ZfKVo+X5FBrGRoHfWi4h0s5cfNl/Y6cGslXlziz7tYGIG8YDakWxbue7jockZdavI7a2 6aW2zOI9AS2P407h948QKrhXFHHQ0b1wU+/CFQEwM9e69wM06HM450Bex5utIptt/BXX F3lg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786097540; x=1786702340; 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=8LdAoJKwXyAPy2Oxe1p5of7f27uz/x1w5QiaYqvn624=; b=aeiskdSRvYBzszYvUU/b6pRtAWylNHh908vF/sNQs5eJE5379hCsHARMrG28dRCAux Si/VcyAqil5Uh/0kYu2IRllznQxeiTq6o423pBdP4EcPc0rxnhgdc0uNRSWmP4JIwmGG 2qj6SflHAzwLJKwmaKLpI9FJF/fdnf2wGUd7xv3z5mffnEPQxNhg+whXWaoYp24tzQMb 9bFKpUMJNEuRHS4Ss2dVIT6dY7pakOM3dkpewBGUNV/YnUD73bsHYmrlRwog2Sa2fBt3 QZH7hnLcRCGdtujtg5cA4T0wsjJ5MzKnuM4EaQwIvqlu4XM5bxZYDlWyeUklpLDh5wic d9fQ== X-Forwarded-Encrypted: i=1; AHgh+RoQqzfyc99vylMJejuF16T+FYbSSnzobmnk4oKfeht7QR0GOcdy3fBoOIkxZBY8uA3kkUuzucy2c7tzY1c=@vger.kernel.org X-Gm-Message-State: AOJu0Yz70sTSRmqy59k4rUselQezeDLHH9c/nutcBrwkdXeZAFCBDuo4 P54VX+2Vtu+cToibm/L/CSz0+VJBIj8GGxovDcsCr/HD1zguR+1Ejl39 X-Gm-Gg: AR+sD13D96IP5UPrW3klDxf/bK+28Xsy5vAykJ75952mD9b/cMe4EtGwYqPovaRvYyc GNA00xcAv5qZki2rJE6d+0Vndp43O3F6qv+1JSD/60AM37KxbYq6ZOFwPXIlEv4kTdMhQ5mV/qI +srBaaqAgQhHOwpMsozPLvgC3vb4dxmI95cn+JnWTMpj/uh1P5d2nvSYApoh7QKq7cYRO+f88sx JfJf2qD/lAbHiI0Yo++w3rF6VEZYYvipAVEexAVL8riA1jz7XUc++0wLLCcI7xoJQ3WDB9GnrAP ZnXtT7rUudLsKc4s95KAHvCCxqkPJNVSvblpveDdPZUyfkY9zrRBG3l95s5OZ89r6odGisFYCUv a3JuNr0Z7rdZWZw+PKgZVqwD3gJkhDlnIVLreDYHoiOZ5+56Xt7hleeClYAu/6P4J19DetvF6Hm D1V0J15NKCFgbp8PedEXw/WFVZY0b6QJ7hfCdWmD/QbElwdjy0UO1WvXa81d5mjHpe X-Received: by 2002:a05:6a00:32c3:b0:848:47d3:47ec with SMTP id d2e1a72fcca58-84f2e0826afmr26947369b3a.31.1786097540308; Fri, 07 Aug 2026 03:12:20 -0700 (PDT) Received: from baineng-pc.. ([117.133.183.252]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-84f5a5528adsm797510b3a.45.2026.08.07.03.12.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Aug 2026 03:12:19 -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 v6 3/4] drm/prime: use dma_buf_fd_install() to preserve export tracing Date: Fri, 7 Aug 2026 18:11:39 +0800 Message-Id: <20260807101140.1357218-4-shoubaineng@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260807101140.1357218-1-shoubaineng@gmail.com> References: <20260807101140.1357218-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 Signed-off-by: Baineng Shou Acked-by: Sumit Semwal --- 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 Wed Sep 30 18:00:38 2026 Received: from mail-pf1-f177.google.com (mail-pf1-f177.google.com [209.85.210.177]) (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 637FB41DDFD for ; Fri, 7 Aug 2026 10:12:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.177 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786097548; cv=none; b=BzlLFP7KKr9dYQ7Vuc8mEI95sNTumdFqH9MLzd7RIbS2L6kqk2Yt+wTduMdmGJmSrYUtNEVzVtrQQfzaIF4/YA7UAJ0iAekH4vDfBgY0OO5UQjv9C38X8IxgE3jTu5ZgWYeXP5FxJmvNSZ15ZpauYk/3D+D/EtKA0qqfDfpC8g8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786097548; c=relaxed/simple; bh=F1UzQeZHsiabgRSoKYgZ6x2SoQv1aOF17+66tpxhGm8=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=Avk3R+OImv84DiEJXBJ4ySABdPE2f9n2Dl/SXduGooIVgHVVt5tHpjqTDKLfAl/9Jop1/EmFUaJMT6N1iGLuvy6hNE52JhuHi/LUUlWatkudy8NDhZF31vhTRjv5GGcGwLRo+vieUZ8Nh7ZgyifjkYnOk0FVJa0FUUKivPACh54= 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=R+UAkjmY; arc=none smtp.client-ip=209.85.210.177 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="R+UAkjmY" Received: by mail-pf1-f177.google.com with SMTP id d2e1a72fcca58-84862b0d5f8so2973845b3a.3 for ; Fri, 07 Aug 2026 03:12:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1786097547; x=1786702347; 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=b1QPAle4B6UVEoKy/UvltvjtFmYUt6krDcEVyTwixgM=; b=R+UAkjmYQVwAFPG/XsDDKTicbg2ber+BJXst4QUEEcglLGxzmaLZ2eh70Ke6b39D8n gNTdaRXw0hOTbc227iBaKwE0rt3YGJPj2pMchuFwTJyXiBooqyBuCiSAaSIxokSu7g3D ND9NDcZsi2087K4qhwpt4iOa83ns5uvjgIspETrhX/hUrsjSqx0KmTgFSWrWYmf6jwNF c4xQQsarmmL2nBp/0G+ALhmfUEhTLKeb5YixerbyXVC93ge0iIiQbyBOgD9/0zhTQcT8 cFQ5tTqb2Rug+fb2JNyaQueDucVoveEQs+UmBupD2qshTb065ALYnOin/Uo30LUu1s00 LvTw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786097547; x=1786702347; 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=b1QPAle4B6UVEoKy/UvltvjtFmYUt6krDcEVyTwixgM=; b=ngZ6q/ZOWO5+7e3L+U82+hAKAElz3s/GNwXPYlrwNIiis/1vfn+yqbZ/X2pR5CMpi1 icYRLGSngmcrqzCeYMGKTAlFfModsO1+iNOqLRbZyyCFqRSMv6hsEzsTxYKJ/qMMPGri O0lGRq6qctCvtKMWR3VNgEbIIrvLpSmz68kLfLoBez4bi2OOC+2X7yNhBoCz6jhaB9iD qF87fUuKCPxaqem387TGzqsOxCfuaJpdU34AE+lo6SAC0VSMzQBkrptJiPeGW6cerea4 EifFcoLAheqSGsxom8gcOF5azkMaYGQ8UoD97kskHoo8A/hqFYpLLDnfoAqcpG3qSp91 zSZw== X-Forwarded-Encrypted: i=1; AHgh+Ro+O0wpq8lqasEbPjB5ZS9jxuN0XrMp9GVyeSTzzHJkQ07zmtRH4jE6B5TCtAN22ElDN5rr9yYhwnmhtJc=@vger.kernel.org X-Gm-Message-State: AOJu0Yy+y9Sm/OiiC3dsshv3nH810HWcnalYS9BZqvifaxr367JOpKsR kpzQVSswZ+ZGK2ESIXcrP36bIMaWQvxDle3WZzkWz6wIyc7ORdcfYXJt X-Gm-Gg: AR+sD10u8eWV1Mvo9afrSWAGWvM3wVfseSz1hS6c0KuAGVrNhuhWDBBK7D5CWZTWozC fzOmTmD8sSAgCFEy5dwskaBvRX9b78l1NPuaJy3t0Dm83wnkqJXataonSZSD2CLs5NipmgQBDJ9 JueYjGaIPVvxgNlFb2QkOY3kl8yQbC1eOWDu0Y5ul8ZHeC76lNDTtNgm8W255UIY3qOLNv9byaB s1MKgpahkkcogBtfQcSiI4Q2usRM0TiiIduyKAD27sk0Z6k8wOWmPRbNpfI80kzWEgf98rQJsVt 54DAQgozLbzdAxXY5Lk5mpHGhAiisDWR4Up1D+dKLdQeuUFbPJzcUptGQj2Y2HSq9WHL7F5nCBp V2T5lJOoB9arfqnZWtI5dK6RTGBt2PhHo0Xu4zbR+V/p44hSvGr+a0pzM3Qimpxdhs2mfN4pBAl raDMhfTedxZ5mtzcRtGL2vtZq+xdJdnoL/zFmPoLLyz/NbgKMgnJ2zG69MBZCbf5Nt X-Received: by 2002:a05:6a00:ba06:b0:84d:ff47:fa53 with SMTP id d2e1a72fcca58-84f4fd9f842mr10114159b3a.2.1786097546501; Fri, 07 Aug 2026 03:12:26 -0700 (PDT) Received: from baineng-pc.. ([117.133.183.252]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-84f5a5528adsm797510b3a.45.2026.08.07.03.12.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Aug 2026 03:12:26 -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 v6 4/4] selftests: dmabuf-heaps: add fd-leak-on-EFAULT regression test Date: Fri, 7 Aug 2026 18:11:40 +0800 Message-Id: <20260807101140.1357218-5-shoubaineng@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260807101140.1357218-1-shoubaineng@gmail.com> References: <20260807101140.1357218-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 Signed-off-by: Baineng Shou Acked-by: Sumit Semwal --- .../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