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.

iommu: debug-pagealloc: Check mapped/unmapped kernel memory

Now, as the page_ext holds count of IOMMU mappings, we can use it to
assert that any page allocated/freed is indeed not in the IOMMU.

The sanitizer doesn’t protect against mapping/unmapping during this
period. However, that’s less harmful as the page is not used by the
kernel.

Reviewed-by: Samiullah Khawaja <skhawaja@google.com>
Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
Signed-off-by: Mostafa Saleh <smostafa@google.com>
Reviewed-by: Pranjal Shrivastava <praan@google.com>
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>

authored by

Mostafa Saleh and committed by
Joerg Roedel
a8258ffe 7e845937

+42
+23
drivers/iommu/iommu-debug-pagealloc.c
··· 9 9 #include <linux/iommu-debug-pagealloc.h> 10 10 #include <linux/kernel.h> 11 11 #include <linux/page_ext.h> 12 + #include <linux/page_owner.h> 12 13 13 14 #include "iommu-priv.h" 14 15 ··· 72 71 static size_t iommu_debug_page_size(struct iommu_domain *domain) 73 72 { 74 73 return 1UL << __ffs(domain->pgsize_bitmap); 74 + } 75 + 76 + static bool iommu_debug_page_count(const struct page *page) 77 + { 78 + unsigned int ref; 79 + struct page_ext *page_ext = page_ext_get(page); 80 + struct iommu_debug_metadata *d = get_iommu_data(page_ext); 81 + 82 + ref = atomic_read(&d->ref); 83 + page_ext_put(page_ext); 84 + return ref != 0; 85 + } 86 + 87 + void __iommu_debug_check_unmapped(const struct page *page, int numpages) 88 + { 89 + while (numpages--) { 90 + if (WARN_ON(iommu_debug_page_count(page))) { 91 + pr_warn("iommu: Detected page leak!\n"); 92 + dump_page_owner(page); 93 + } 94 + page++; 95 + } 75 96 } 76 97 77 98 void __iommu_debug_map(struct iommu_domain *domain, phys_addr_t phys, size_t size)
+14
include/linux/iommu-debug-pagealloc.h
··· 13 13 14 14 extern struct page_ext_operations page_iommu_debug_ops; 15 15 16 + void __iommu_debug_check_unmapped(const struct page *page, int numpages); 17 + 18 + static inline void iommu_debug_check_unmapped(const struct page *page, int numpages) 19 + { 20 + if (static_branch_unlikely(&iommu_debug_initialized)) 21 + __iommu_debug_check_unmapped(page, numpages); 22 + } 23 + 24 + #else 25 + static inline void iommu_debug_check_unmapped(const struct page *page, 26 + int numpages) 27 + { 28 + } 29 + 16 30 #endif /* CONFIG_IOMMU_DEBUG_PAGEALLOC */ 17 31 18 32 #endif /* __LINUX_IOMMU_DEBUG_PAGEALLOC_H */
+5
include/linux/mm.h
··· 36 36 #include <linux/rcuwait.h> 37 37 #include <linux/bitmap.h> 38 38 #include <linux/bitops.h> 39 + #include <linux/iommu-debug-pagealloc.h> 39 40 40 41 struct mempolicy; 41 42 struct anon_vma; ··· 4134 4133 #ifdef CONFIG_DEBUG_PAGEALLOC 4135 4134 static inline void debug_pagealloc_map_pages(struct page *page, int numpages) 4136 4135 { 4136 + iommu_debug_check_unmapped(page, numpages); 4137 + 4137 4138 if (debug_pagealloc_enabled_static()) 4138 4139 __kernel_map_pages(page, numpages, 1); 4139 4140 } 4140 4141 4141 4142 static inline void debug_pagealloc_unmap_pages(struct page *page, int numpages) 4142 4143 { 4144 + iommu_debug_check_unmapped(page, numpages); 4145 + 4143 4146 if (debug_pagealloc_enabled_static()) 4144 4147 __kernel_map_pages(page, numpages, 0); 4145 4148 }