Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

dma: swiotlb: add KMSAN annotations to swiotlb_bounce()

When a device performs DMA to a bounce buffer, KMSAN is unaware of
the write and does not mark the data as initialized. When
swiotlb_bounce() later copies the bounce buffer back to the original
buffer, memcpy propagates the uninitialized shadow to the original
buffer, causing false positive uninit-value reports.

Fix this by calling kmsan_unpoison_memory() on the bounce buffer
before copying it back in the DMA_FROM_DEVICE path, so that memcpy
naturally propagates initialized shadow to the destination.

Suggested-by: Alexander Potapenko <glider@google.com>
Link: https://lore.kernel.org/CAG_fn=WUGta-paG1BgsGRoAR+fmuCgh3xo=R3XdzOt_-DqSdHw@mail.gmail.com/
Fixes: 7ade4f10779c ("dma: kmsan: unpoison DMA mappings")
Signed-off-by: Shigeru Yoshida <syoshida@redhat.com>
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Link: https://lore.kernel.org/r/20260315082750.2375581-1-syoshida@redhat.com

authored by

Shigeru Yoshida and committed by
Marek Szyprowski
6f770b73 d5b5e814

+19 -2
+19 -2
kernel/dma/swiotlb.c
··· 30 30 #include <linux/gfp.h> 31 31 #include <linux/highmem.h> 32 32 #include <linux/io.h> 33 + #include <linux/kmsan-checks.h> 33 34 #include <linux/iommu-helper.h> 34 35 #include <linux/init.h> 35 36 #include <linux/memblock.h> ··· 902 901 903 902 local_irq_save(flags); 904 903 page = pfn_to_page(pfn); 905 - if (dir == DMA_TO_DEVICE) 904 + if (dir == DMA_TO_DEVICE) { 905 + /* 906 + * Ideally, kmsan_check_highmem_page() 907 + * could be used here to detect infoleaks, 908 + * but callers may map uninitialized buffers 909 + * that will be written by the device, 910 + * causing false positives. 911 + */ 906 912 memcpy_from_page(vaddr, page, offset, sz); 907 - else 913 + } else { 914 + kmsan_unpoison_memory(vaddr, sz); 908 915 memcpy_to_page(page, offset, vaddr, sz); 916 + } 909 917 local_irq_restore(flags); 910 918 911 919 size -= sz; ··· 923 913 offset = 0; 924 914 } 925 915 } else if (dir == DMA_TO_DEVICE) { 916 + /* 917 + * Ideally, kmsan_check_memory() could be used here to detect 918 + * infoleaks (uninitialized data being sent to device), but 919 + * callers may map uninitialized buffers that will be written 920 + * by the device, causing false positives. 921 + */ 926 922 memcpy(vaddr, phys_to_virt(orig_addr), size); 927 923 } else { 924 + kmsan_unpoison_memory(vaddr, size); 928 925 memcpy(phys_to_virt(orig_addr), vaddr, size); 929 926 } 930 927 }