From: "Christian König" <ckoenig.leichtzumerken@gmail.com>
To: Matthew Auld <matthew.auld@intel.com>,
sumit.semwal@linaro.org, linux-media@vger.kernel.org,
dri-devel@lists.freedesktop.org, linaro-mm-sig@lists.linaro.org,
simona.vetter@ffwll.ch
Subject: Re: [PATCH 1/2] dma-buf: improve sg_table debugging hack v2
Date: Fri, 5 Dec 2025 11:41:23 +0100 [thread overview]
Message-ID: <e21cc071-0133-4b07-a52f-67ed4d80cbcd@gmail.com> (raw)
In-Reply-To: <3e09719d-af1b-4c5d-83fb-6ef5f41739b5@intel.com>
On 12/4/25 16:51, Matthew Auld wrote:
> On 04/12/2025 14:59, Christian König wrote:
>> This debugging hack is important to enforce the rule that importers
>> should *never* touch the underlying struct page of the exporter.
>>
>> Instead of just mangling the page link create a copy of the sg_table
>> but only copy over the DMA addresses and not the pages.
>>
>> This will cause a NULL pointer de-reference if the importer tries to
>> touch the struct page. Still quite a hack but this at least allows the
>> exporter to properly keeps it's sg_table intact while allowing the
>> DMA-buf maintainer to find and fix misbehaving importers and finally
>> switch over to using a different data structure in the future.
>>
>> v2: improve the hack further by using a wrapper structure and explaining
>> the background a bit more in the commit message.
>>
>> Signed-off-by: Christian König <christian.koenig@amd.com>
>> Reviewed-by: Michael J. Ruhl <michael.j.ruhl@intel.com> (v1)
>> ---
>> drivers/dma-buf/dma-buf.c | 72 +++++++++++++++++++++++++++++++--------
>> 1 file changed, 58 insertions(+), 14 deletions(-)
>>
>> diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
>> index 2305bb2cc1f1..8c4afd360b72 100644
>> --- a/drivers/dma-buf/dma-buf.c
>> +++ b/drivers/dma-buf/dma-buf.c
>> @@ -35,6 +35,12 @@
>> #include "dma-buf-sysfs-stats.h"
>> +/* Wrapper to hide the sg_table page link from the importer */
>> +struct dma_buf_sg_table_wrapper {
>> + struct sg_table *original;
>> + struct sg_table wrapper;
>> +};
>> +
>> static inline int is_dma_buf_file(struct file *);
>> static DEFINE_MUTEX(dmabuf_list_mutex);
>> @@ -828,21 +834,57 @@ void dma_buf_put(struct dma_buf *dmabuf)
>> }
>> EXPORT_SYMBOL_NS_GPL(dma_buf_put, "DMA_BUF");
>> -static void mangle_sg_table(struct sg_table *sg_table)
>> +static int dma_buf_mangle_sg_table(struct sg_table **sg_table)
>> {
>> -#ifdef CONFIG_DMABUF_DEBUG
>> - int i;
>> - struct scatterlist *sg;
>> -
>> - /* To catch abuse of the underlying struct page by importers mix
>> - * up the bits, but take care to preserve the low SG_ bits to
>> - * not corrupt the sgt. The mixing is undone on unmap
>> - * before passing the sgt back to the exporter.
>> + struct scatterlist *to_sg, *from_sg;
>> + struct sg_table *from = *sg_table;
>> + struct dma_buf_sg_table_wrapper *to;
>> + int i, ret;
>> +
>> + if (!IS_ENABLED(CONFIG_DMABUF_DEBUG))
>> + return 0;
>> +
>> + /*
>> + * To catch abuse of the underlying struct page by importers copy the
>> + * sg_table without copying the page_link and give only the copy back to
>> + * the importer.
>> */
>> - for_each_sgtable_sg(sg_table, sg, i)
>> - sg->page_link ^= ~0xffUL;
>> -#endif
>> + to = kzalloc(sizeof(*to), GFP_KERNEL);
>> + if (!to)
>> + return -ENOMEM;
>> +
>> + ret = sg_alloc_table(&to->wrapper, from->nents, GFP_KERNEL);
>> + if (ret)
>> + goto free_to;
>> +
>> + to_sg = to->wrapper.sgl;
>> + for_each_sgtable_dma_sg(from, from_sg, i) {
>> + sg_set_page(to_sg, NULL, 0, 0);
>
> Are we still allowed to pass NULL page here? There looks to be the recently added:
>
> VM_WARN_ON_ONCE(!page_range_contiguous(page, ALIGN(len + offset, PAGE_SIZE) / PAGE_SIZE));
>
> And if page_range_contiguous() does not just return true, it potentially wants to dereference the page, like with page_to_pfn()?
Good point.
It doesn't crash at the moment because page_to_pfn() also works with NULL as page, but it is clearly not the nicest thing to do.
I will switch over to using sg_assign_page() instead.
>
>
>> + sg_dma_address(to_sg) = sg_dma_address(from_sg);
>> + sg_dma_len(to_sg) = sg_dma_len(from_sg);
>
> Nit: formatting looks off here.
Oh, indeed.
Thanks,
Christian.
>
>> + to_sg = sg_next(to_sg);
>> + }
>> + to->original = from;
>> + *sg_table = &to->wrapper;
>> + return 0;
>> +
>> +free_to:
>> + kfree(to);
>> + return ret;
>> +}
>> +
>> +static void dma_buf_demangle_sg_table(struct sg_table **sg_table)
>> +{
>> + struct dma_buf_sg_table_wrapper *copy;
>> +
>> + if (!IS_ENABLED(CONFIG_DMABUF_DEBUG))
>> + return;
>> +
>> + copy = container_of(*sg_table, typeof(*copy), wrapper);
>> + *sg_table = copy->original;
>> + sg_free_table(©->wrapper);
>> + kfree(copy);
>> }
>> static inline bool
>> @@ -1139,7 +1181,9 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
>> if (ret < 0)
>> goto error_unmap;
>> }
>> - mangle_sg_table(sg_table);
>> + ret = dma_buf_mangle_sg_table(&sg_table);
>> + if (ret)
>> + goto error_unmap;
>> if (IS_ENABLED(CONFIG_DMA_API_DEBUG)) {
>> struct scatterlist *sg;
>> @@ -1220,7 +1264,7 @@ void dma_buf_unmap_attachment(struct dma_buf_attachment *attach,
>> dma_resv_assert_held(attach->dmabuf->resv);
>> - mangle_sg_table(sg_table);
>> + dma_buf_demangle_sg_table(&sg_table);
>> attach->dmabuf->ops->unmap_dma_buf(attach, sg_table, direction);
>> if (dma_buf_pin_on_map(attach))
>
next prev parent reply other threads:[~2025-12-05 10:41 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-12-04 14:59 [PATCH 1/2] dma-buf: improve sg_table debugging hack v2 Christian König
2025-12-04 14:59 ` [PATCH 2/2] dma-buf: enable DMABUF_DEBUG by default on DEBUG kernels Christian König
2025-12-04 15:51 ` [PATCH 1/2] dma-buf: improve sg_table debugging hack v2 Matthew Auld
2025-12-05 10:41 ` Christian König [this message]
2025-12-05 11:10 ` Matthew Auld
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=e21cc071-0133-4b07-a52f-67ed4d80cbcd@gmail.com \
--to=ckoenig.leichtzumerken@gmail.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=linaro-mm-sig@lists.linaro.org \
--cc=linux-media@vger.kernel.org \
--cc=matthew.auld@intel.com \
--cc=simona.vetter@ffwll.ch \
--cc=sumit.semwal@linaro.org \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.