linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
From: Catalin Marinas <catalin.marinas@arm.com>
To: Petr Tesarik <ptesarik@suse.com>
Cc: Vlastimil Babka <vbabka@suse.cz>,
	Feng Tang <feng.tang@linux.alibaba.com>,
	Harry Yoo <harry.yoo@oracle.com>, Peng Fan <peng.fan@nxp.com>,
	Hyeonggon Yoo <42.hyeyoo@gmail.com>,
	David Rientjes <rientjes@google.com>,
	Christoph Lameter <cl@linux.com>,
	"linux-mm@kvack.org" <linux-mm@kvack.org>,
	Robin Murphy <robin.murphy@arm.com>,
	Sean Christopherson <seanjc@google.com>,
	Halil Pasic <pasic@linux.ibm.com>
Subject: Re: slub - extended kmalloc redzone and dma alignment
Date: Wed, 9 Apr 2025 13:49:48 +0100	[thread overview]
Message-ID: <Z_Zs7L1e9pMm5TR8@arm.com> (raw)
In-Reply-To: <20250409141816.1046889f@mordecai>

On Wed, Apr 09, 2025 at 02:18:16PM +0200, Petr Tesarik wrote:
> On Wed, 9 Apr 2025 10:47:36 +0100
> Catalin Marinas <catalin.marinas@arm.com> wrote:
> > On Wed, Apr 09, 2025 at 11:05:29AM +0200, Petr Tesarik wrote:
> > > On Wed, 9 Apr 2025 10:39:04 +0200
> > > Petr Tesarik <ptesarik@suse.com> wrote:  
> > > > I believe there is potential for a nasty race condition, and maybe even
> > > > info leak. Consider this:
> > > > 
> > > > 1. DMA buffer is allocated by kmalloc(). The memory area previously
> > > >    contained sensitive information, which had been written to main
> > > >    memory.
> > > > 2. The DMA buffer is initialized with zeroes, but this new content
> > > >    stays in a CPU cache (because this is kernel memory with a write
> > > >    behind cache policy).
> > > > 3. DMA is set up, but nothing is written to main memory by the
> > > >    bus-mastering device.
> > > > 4. The CPU cache line is now discarded in arch_sync_dma_for_cpu().
> > > > 
> > > > IIUC the zeroes were never written to main memory, and previous content
> > > > can now be read by the CPU through the DMA buffer.
> > > > 
> > > > I haven't checked if any architecture is affected, but I strongly
> > > > believe that the CPU cache MUST be flushed both before and after the
> > > > DMA transfer. Any architecture which does not do it that way should be
> > > > fixed.
> > > > 
> > > > Or did I miss a crucial detail (again)?  
> > > 
> > > Just after sending this, I realized I did. :(
> > > 
> > > There is a step between 2 and 3:
> > > 
> > > 2a. arch_sync_dma_for_device() invalidates the CPU cache line.
> > >     Architectures which do not write previous content to main memory
> > >     effectively undo the zeroing here.  
> > 
> > Good point, that's a problem on those architectures that invalidate the
> > caches in arch_sync_dma_for_device(). We fixed it for arm64 in 5.19 -
> > c50f11c6196f ("arm64: mm: Don't invalidate FROM_DEVICE buffers at start
> > of DMA transfer") - for the same reasons, information leak.
> > 
> > So we could ignore all those architectures. If they people complain
> > about redzone failures, we can ask them to fix. Well, crude attempt
> > below at fixing those. I skipped powerpc and for arch/arm I only
> > addressed cache-v7. Completely untested.
> > 
> > But I wonder whether it's easier to fix the callers of
> > arch_sync_dma_for_device and always pass DMA_BIDIRECTIONAL for security
> > reasons:
> 
> Then we could remove this parameter as useless. ;-)

Yes, I just took the lazy approach of not changing the arch code.

> Now, arch_sync_for_device() must always do the same thing, regardless
> of the transfer direction: Write back any cached DMA buffer data to
> main memory. Except, if an architectures can do this with or without
> invalidating the cache line _and_ it never loads cache content
> speculatively (does not even have a prefetch instruction), it might
> optimize like this:
> 
> - DMA_FROM_DEVICE:
>   - arch_sync_for_device(): writeback and invalidate
>   - arch_sync_for_cpu(): nothing
> 
> - anythig else:
>   - arch_sync_for_device(): writeback only
>   - arch_sync_for_cpu(): invalidate unless DMA_TO_DEVICE
> 
> I don't know if there's any such non-prefetching architecture, much
> less if this optimization would make sense there. It's just the only
> scenario I can imagine where the direction parameter makes any
> difference for arch_sync_for_device().

We have at least some old arm cores (pre ARMv6) that have a no-op for
the arch_sync_dma_for_cpu() case. They rely on the for_device code to
invalidate the caches. That's why I suggested DMA_BIDIRECTIONAL as a
cover-all option. However, such default may affect the performance of
CPUs that would benefit from a writeback without invalidate.

Basically what we need is something like:

	if (dir == DMA_TO_DEVICE)
		dir = DMA_BIDIRECTIONAL;

We could hide this in the core DMA code (behind some macro/function) or
update the arch code to do this. I don't have the setup to test all of
them (I can test arm64, maybe modern arm32 but that's about it).

Or we ignore the problem and tell people to fix their DMA ops if they
see complains about slab redzones. We also ignore the potential
information leak we've had for decades.

-- 
Catalin


  reply	other threads:[~2025-04-09 12:49 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-04-04  9:30 Vlastimil Babka
2025-04-04 10:30 ` Harry Yoo
2025-04-04 11:12   ` Petr Tesarik
2025-04-04 12:45     ` Vlastimil Babka
2025-04-04 13:53       ` Petr Tesarik
2025-04-06 14:02         ` Feng Tang
2025-04-07  7:21           ` Feng Tang
2025-04-07  7:54             ` Vlastimil Babka
2025-04-07  9:50               ` Petr Tesarik
2025-04-07 17:12               ` Catalin Marinas
2025-04-08  5:27                 ` Petr Tesarik
2025-04-08 15:07                   ` Catalin Marinas
2025-04-09  8:39                     ` Petr Tesarik
2025-04-09  9:05                       ` Petr Tesarik
2025-04-09  9:47                         ` Catalin Marinas
2025-04-09 12:18                           ` Petr Tesarik
2025-04-09 12:49                             ` Catalin Marinas [this message]
2025-04-09 13:41                               ` Petr Tesarik
2025-04-09  8:51                     ` Vlastimil Babka
2025-04-09 11:11                       ` Catalin Marinas
2025-04-09 12:22                         ` Vlastimil Babka
2025-04-09 14:30                           ` Catalin Marinas
2025-04-10  1:54                             ` Feng Tang
2025-04-07  7:45         ` Vlastimil Babka

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=Z_Zs7L1e9pMm5TR8@arm.com \
    --to=catalin.marinas@arm.com \
    --cc=42.hyeyoo@gmail.com \
    --cc=cl@linux.com \
    --cc=feng.tang@linux.alibaba.com \
    --cc=harry.yoo@oracle.com \
    --cc=linux-mm@kvack.org \
    --cc=pasic@linux.ibm.com \
    --cc=peng.fan@nxp.com \
    --cc=ptesarik@suse.com \
    --cc=rientjes@google.com \
    --cc=robin.murphy@arm.com \
    --cc=seanjc@google.com \
    --cc=vbabka@suse.cz \
    /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