From: sashiko-bot@kernel.org
To: "Pavel Begunkov" <asml.silence@gmail.com>
Cc: media-ci@linuxtv.org, dri-devel@lists.freedesktop.org
Subject: Re: [PATCH v6 01/13] dma-buf: introduce initial file I/O infrastructure
Date: Mon, 21 Sep 2026 13:53:43 +0000 [thread overview]
Message-ID: <20260921135344.035B81F000FF@smtp.kernel.org> (raw)
In-Reply-To: <5490ee42c4452fd4198b245ead20fcf7438c066e.1789997898.git.asml.silence@gmail.com>
Thank you for your contribution! Sashiko AI review found 6 potential issue(s) to consider:
- [Critical] dma-buf: TOCTOU race allows a stale map to escape concurrent invalidation
- [High] dma-buf: Use-After-Free of ctx in waitqueue due to race condition
- [High] dma-buf: GFP_KERNEL allocation performed while holding dmabuf->resv ww_mutex
- [Medium] dma-buf: Hardcoded kfree(map) restricts driver structure embedding
- [Medium] dma-buf: Memory leak of ctx and dmabuf reference on incomplete dev_ops error path
- [Medium] dma-buf: Memory leak of map structure and DMA mappings on min_seg_shift validation error
--
commit b9251fd88ee105b166b558434c10ce6e3b106691
Author: Pavel Begunkov <asml.silence@gmail.com>
Subject: dma-buf: introduce initial file I/O infrastructure
This commit adds basic building blocks serving as a glue and API between
drivers and upper layer subsystems providing the uAPI. It introduces
struct dma_buf_io_ctx and struct dma_buf_io_map, allowing dma-buf to be
natively used in the read-write / IO path.
> diff --git a/drivers/dma-buf/dma-buf-io.c b/drivers/dma-buf/dma-buf-io.c
> new file mode 100644
> index 0000000000000..8312637a299f6
> --- /dev/null
> +++ b/drivers/dma-buf/dma-buf-io.c
[ ... ]
> @@ -22,17 +22,17 @@ static void dma_buf_io_map_release_work(struct work_struct *work)
> {
> struct dma_buf_io_map *map = container_of(work, struct dma_buf_io_map,
> release_work);
> struct dma_buf_io_ctx *ctx = map->ctx;
> struct dma_buf *dmabuf = ctx->dmabuf;
>
> dma_resv_lock(dmabuf->resv, NULL);
> ctx->dev_ops->unmap(ctx, map);
> dma_resv_unlock(dmabuf->resv);
>
> percpu_ref_exit(&map->refs);
> kfree(map);
[Severity: Medium]
Since drivers allocate this map object (often embedding it in a larger
structure), does this unconditional kfree(map) restrict where drivers can
embed the structure?
If a driver needs to use vmalloc or embed the map at a non-zero offset,
this will cause a panic. Could a .free callback be provided for safe
lifecycle management?
>
> atomic_dec(&ctx->all_maps);
> wake_up(&ctx->maps_wq);
[Severity: High]
Can this sequence lead to a use-after-free on ctx?
If atomic_dec(&ctx->all_maps) drops the count to 0, a concurrent thread
blocked in dma_buf_io_wait_maps() can wake up, return, and free the ctx via
dma_buf_io_ctx_release():
Thread 1 (waiter):
dma_buf_io_ctx_release()
dma_buf_io_wait_maps()
wait_event() unblocks since atomic_read(&ctx->all_maps) == 0.
dma_buf_io_put_ctx() is called and frees ctx.
Thread 2 (worker here):
Proceeds to call wake_up(&ctx->maps_wq) on the now-freed ctx memory.
> }
[ ... ]
> +int dma_buf_io_init_map(struct dma_buf_io_ctx *ctx, struct dma_buf_io_map *map,
> + struct sg_table *sgt)
> +{
> + unsigned seg_shift = ~0U;
> + struct scatterlist *sg;
> + unsigned long tmp;
> + int ret;
> +
> + for_each_sgtable_dma_sg(sgt, sg, tmp)
> + seg_shift = min(seg_shift, __ffs(sg_dma_len(sg)));
> +
> + ret = percpu_ref_init(&map->refs, dma_buf_io_map_refs_release, 0,
> + GFP_KERNEL);
[Severity: High]
Does this GFP_KERNEL allocation violate DMA-buf locking rules?
dma_buf_io_create_map() calls ctx->dev_ops->map(ctx) while holding the
dmabuf->resv ww_mutex. If the driver then calls dma_buf_io_init_map() under
this lock, the GFP_KERNEL allocation could deadlock if memory reclaim
attempts to acquire dma_resv locks.
> + if (ret)
> + return ret;
> + map->min_seg_shift = seg_shift;
> + map->ctx = ctx;
> + return 0;
> +}
> +EXPORT_SYMBOL_NS_GPL(dma_buf_io_init_map, "DMA_BUF");
> +
> +struct dma_buf_io_map *dma_buf_io_create_map(struct dma_buf_io_ctx *ctx)
> +{
> + struct dma_buf *dmabuf = ctx->dmabuf;
> + struct dma_buf_io_map *map;
> + long ret;
> +
> + guard(mutex)(&ctx->map_create_mutex);
> +
> + scoped_guard(mutex, &ctx->map_mutex) {
> + if (ctx->maps_killed)
> + return ERR_PTR(-ENOENT);
> + /* recheck under the lock in case it has already been re-created */
> + map = __dma_buf_io_get_map(ctx);
> + if (map)
> + return map;
> + }
> +
> + dma_buf_io_wait_active_maps(ctx);
> +
> + ret = dma_resv_lock_interruptible(dmabuf->resv, NULL);
> + if (ret)
> + return ERR_PTR(ret);
> +
> + ret = dma_resv_wait_timeout(dmabuf->resv, DMA_RESV_USAGE_KERNEL,
> + true, MAX_SCHEDULE_TIMEOUT);
> + if (ret <= 0) {
> + if (!ret)
> + ret = -EAGAIN;
> + dma_resv_unlock(dmabuf->resv);
> + return ERR_PTR(ret);
> + }
> +
> + map = ctx->dev_ops->map(ctx);
> + dma_resv_unlock(dmabuf->resv);
> +
> + if (IS_ERR(map))
> + return map;
> + if (WARN_ON_ONCE(!map->min_seg_shift))
> + return ERR_PTR(-EFAULT);
[Severity: Medium]
If this validation fails and we return -EFAULT, do we leak the map structure
and the underlying device DMA mappings?
It looks like we are bypassing ctx->dev_ops->unmap() and the corresponding
map structure freeing here.
[Severity: Critical]
Does this sequence create a TOCTOU race with dma_buf_io_invalidate_mappings()?
The map is created under dmabuf->resv lock, but we unlock it before updating
ctx->map and ctx->active_maps.
If an exporter triggers an invalidation:
1. dma_buf_io_create_map() calls ctx->dev_ops->map(ctx).
2. It then calls dma_resv_unlock(dmabuf->resv).
3. The exporter acquires the dmabuf->resv lock and calls
dma_buf_io_invalidate_mappings().
4. dma_buf_io_kill_maps() and dma_buf_io_wait_active_maps() observe
no active maps and finish the invalidation.
5. dma_buf_io_create_map() resumes, increments active_maps, and publishes
the now-stale map to ctx->map.
This allows the stale physical memory mapping to escape to the caller.
> +
> + atomic_inc(&ctx->active_maps);
> + atomic_inc(&ctx->all_maps);
> + /* get a reference for the caller */
> + percpu_ref_get(&map->refs);
> +
> + scoped_guard(mutex, &ctx->map_mutex)
> + rcu_assign_pointer(ctx->map, map);
> + return map;
> +}
[ ... ]
> +int dma_buf_io_ctx_create(struct file *file,
> + struct dma_buf *dmabuf,
> + enum dma_data_direction dir,
> + struct dma_buf_io_ctx **out_ctx)
> +{
> + struct dma_buf_io_ctx *ctx;
> + int ret;
> +
> + if (!file->f_op->init_dma_buf_io_ctx)
> + return -EOPNOTSUPP;
> +
> + ctx = kmalloc_obj(*ctx);
> + if (!ctx)
> + return -ENOMEM;
> +
> + memset(ctx, 0, sizeof(*ctx));
> + ctx->dir = dir;
> + ctx->dmabuf = dmabuf;
> + get_dma_buf(dmabuf);
> + mutex_init(&ctx->map_mutex);
> + mutex_init(&ctx->map_create_mutex);
> + atomic_set(&ctx->active_maps, 0);
> + atomic_set(&ctx->all_maps, 0);
> + init_waitqueue_head(&ctx->maps_wq);
> +
> + ret = file->f_op->init_dma_buf_io_ctx(file, ctx);
> + if (ret) {
> + kfree(ctx);
> + dma_buf_put(dmabuf);
> + return ret;
> + }
> +
> + if (WARN_ON_ONCE(!ctx->dev_ops ||
> + !ctx->dev_ops->map ||
> + !ctx->dev_ops->unmap ||
> + !ctx->dev_ops->release))
> + return -EINVAL;
[Severity: Medium]
If this check fails, does it leak the allocated ctx and the dmabuf reference?
The previous error path handles cleanup via kfree(ctx) and dma_buf_put(dmabuf),
but this one bails out without cleaning up.
> +
> + *out_ctx = ctx;
> + return 0;
> +}
--
Sashiko AI review · https://sashiko.dev/#/patchset/cover.1789997898.git.asml.silence@gmail.com?part=1
next prev parent reply other threads:[~2026-09-21 13:53 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-21 13:38 [PATCH v6 00/13] Add dmabuf read/write via io_uring Pavel Begunkov
2026-09-21 13:38 ` [PATCH v6 01/13] dma-buf: introduce initial file I/O infrastructure Pavel Begunkov
2026-09-21 13:53 ` sashiko-bot [this message]
2026-09-22 9:08 ` Pavel Begunkov
2026-09-30 6:54 ` Matthew Brost
2026-09-30 10:03 ` Pavel Begunkov
2026-09-30 3:00 ` Matthew Brost
2026-09-30 10:08 ` Pavel Begunkov
2026-09-30 12:48 ` Pavel Begunkov
2026-09-30 19:43 ` Matthew Brost
2026-10-05 11:49 ` Pavel Begunkov
2026-09-21 13:38 ` [PATCH v6 02/13] iov_iter: add iterator type for dmabuf maps Pavel Begunkov
2026-09-21 13:53 ` sashiko-bot
2026-09-22 9:15 ` Pavel Begunkov
2026-09-21 13:38 ` [PATCH v6 03/13] block: always adjust bi_offset on bio_advance_iter Pavel Begunkov
2026-09-21 13:38 ` [PATCH v6 04/13] block: introduce dma map backed bio type Pavel Begunkov
[not found] ` <20260922131610.GA30468@lst.de>
2026-09-22 13:54 ` Pavel Begunkov
2026-09-21 13:38 ` [PATCH v6 05/13] block: add dma-buf support for raw bdev Pavel Begunkov
2026-09-21 13:50 ` sashiko-bot
2026-09-21 13:38 ` [PATCH v6 06/13] nvme-pci: implement dma-buf backed requests Pavel Begunkov
2026-09-21 13:58 ` sashiko-bot
[not found] ` <20260922132016.GA30684@lst.de>
2026-09-22 13:37 ` Pavel Begunkov
[not found] ` <20260923045505.GB26231@lst.de>
2026-09-24 15:53 ` Pavel Begunkov
2026-09-21 13:38 ` [PATCH v6 07/13] nvme-pci: rename nvme_pci_sgl_set_data to nvme_pci_dma_iter_set_sgl Pavel Begunkov
2026-09-21 13:38 ` [PATCH v6 08/13] nvme-pci: add SGL support for the dmabuf path Pavel Begunkov
2026-09-21 13:38 ` [PATCH v6 09/13] io_uring/rsrc: introduce buf registration structure Pavel Begunkov
2026-09-21 13:38 ` [PATCH v6 10/13] io_uring/rsrc: extend buffer update Pavel Begunkov
2026-09-21 13:38 ` [PATCH v6 11/13] io_uring/rsrc: add uncloneable regbuf flag Pavel Begunkov
2026-09-21 13:53 ` sashiko-bot
2026-09-21 13:38 ` [PATCH v6 12/13] io_uring/rsrc: add regbuf import flags Pavel Begunkov
2026-09-21 13:38 ` [PATCH v6 13/13] io_uring/rsrc: add dmabuf backed registered buffers Pavel Begunkov
2026-09-21 13:54 ` sashiko-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=20260921135344.035B81F000FF@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=asml.silence@gmail.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=media-ci@linuxtv.org \
--cc=sashiko-reviews@lists.linux.dev \
/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