Skip to content

Commit 466ae69

Browse files
misalehjoergroedel
authored andcommitted
iommu: Add page_ext for IOMMU_DEBUG_PAGEALLOC
Add a new config IOMMU_DEBUG_PAGEALLOC, which registers new data to page_ext. This config will be used by the IOMMU API to track pages mapped in the IOMMU to catch drivers trying to free kernel memory that they still map in their domains, causing all types of memory corruption. This behaviour is disabled by default and can be enabled using kernel cmdline iommu.debug_pagealloc. Acked-by: David Hildenbrand (Red Hat) <david@kernel.org> Reviewed-by: Pranjal Shrivastava <praan@google.com> Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com> Signed-off-by: Mostafa Saleh <smostafa@google.com> Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
1 parent f5b16b8 commit 466ae69

6 files changed

Lines changed: 82 additions & 0 deletions

File tree

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2675,6 +2675,15 @@ Kernel parameters
26752675
1 - Bypass the IOMMU for DMA.
26762676
unset - Use value of CONFIG_IOMMU_DEFAULT_PASSTHROUGH.
26772677

2678+
iommu.debug_pagealloc=
2679+
[KNL,EARLY] When CONFIG_IOMMU_DEBUG_PAGEALLOC is set, this
2680+
parameter enables the feature at boot time. By default, it
2681+
is disabled and the system behaves the same way as a kernel
2682+
built without CONFIG_IOMMU_DEBUG_PAGEALLOC.
2683+
Format: { "0" | "1" }
2684+
0 - Sanitizer disabled.
2685+
1 - Sanitizer enabled, expect runtime overhead.
2686+
26782687
io7= [HW] IO7 for Marvel-based Alpha systems
26792688
See comment before marvel_specify_io7 in
26802689
arch/alpha/kernel/core_marvel.c.

drivers/iommu/Kconfig

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,25 @@ config SPRD_IOMMU
384384

385385
Say Y here if you want to use the multimedia devices listed above.
386386

387+
config IOMMU_DEBUG_PAGEALLOC
388+
bool "Debug IOMMU mappings against page allocations"
389+
depends on DEBUG_PAGEALLOC && IOMMU_API && PAGE_EXTENSION
390+
help
391+
This enables a consistency check between the kernel page allocator and
392+
the IOMMU subsystem. It verifies that pages being allocated or freed
393+
are not currently mapped in any IOMMU domain.
394+
395+
This helps detect DMA use-after-free bugs where a driver frees a page
396+
but forgets to unmap it from the IOMMU, potentially allowing a device
397+
to overwrite memory that the kernel has repurposed.
398+
399+
These checks are best-effort and may not detect all problems.
400+
401+
Due to performance overhead, this feature is disabled by default.
402+
You must enable "iommu.debug_pagealloc" from the kernel command
403+
line to activate the runtime checks.
404+
405+
If unsure, say N.
387406
endif # IOMMU_SUPPORT
388407

389408
source "drivers/iommu/generic_pt/Kconfig"

drivers/iommu/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,4 @@ obj-$(CONFIG_IOMMU_SVA) += iommu-sva.o
3636
obj-$(CONFIG_IOMMU_IOPF) += io-pgfault.o
3737
obj-$(CONFIG_SPRD_IOMMU) += sprd-iommu.o
3838
obj-$(CONFIG_APPLE_DART) += apple-dart.o
39+
obj-$(CONFIG_IOMMU_DEBUG_PAGEALLOC) += iommu-debug-pagealloc.o
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
/*
3+
* Copyright (C) 2025 - Google Inc
4+
* Author: Mostafa Saleh <smostafa@google.com>
5+
* IOMMU API debug page alloc sanitizer
6+
*/
7+
#include <linux/atomic.h>
8+
#include <linux/iommu-debug-pagealloc.h>
9+
#include <linux/kernel.h>
10+
#include <linux/page_ext.h>
11+
12+
static bool needed;
13+
14+
struct iommu_debug_metadata {
15+
atomic_t ref;
16+
};
17+
18+
static __init bool need_iommu_debug(void)
19+
{
20+
return needed;
21+
}
22+
23+
struct page_ext_operations page_iommu_debug_ops = {
24+
.size = sizeof(struct iommu_debug_metadata),
25+
.need = need_iommu_debug,
26+
};
27+
28+
static int __init iommu_debug_pagealloc(char *str)
29+
{
30+
return kstrtobool(str, &needed);
31+
}
32+
early_param("iommu.debug_pagealloc", iommu_debug_pagealloc);
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
/*
3+
* Copyright (C) 2025 - Google Inc
4+
* Author: Mostafa Saleh <smostafa@google.com>
5+
* IOMMU API debug page alloc sanitizer
6+
*/
7+
8+
#ifndef __LINUX_IOMMU_DEBUG_PAGEALLOC_H
9+
#define __LINUX_IOMMU_DEBUG_PAGEALLOC_H
10+
11+
#ifdef CONFIG_IOMMU_DEBUG_PAGEALLOC
12+
13+
extern struct page_ext_operations page_iommu_debug_ops;
14+
15+
#endif /* CONFIG_IOMMU_DEBUG_PAGEALLOC */
16+
17+
#endif /* __LINUX_IOMMU_DEBUG_PAGEALLOC_H */

mm/page_ext.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <linux/page_table_check.h>
1212
#include <linux/rcupdate.h>
1313
#include <linux/pgalloc_tag.h>
14+
#include <linux/iommu-debug-pagealloc.h>
1415

1516
/*
1617
* struct page extension
@@ -89,6 +90,9 @@ static struct page_ext_operations *page_ext_ops[] __initdata = {
8990
#ifdef CONFIG_PAGE_TABLE_CHECK
9091
&page_table_check_ops,
9192
#endif
93+
#ifdef CONFIG_IOMMU_DEBUG_PAGEALLOC
94+
&page_iommu_debug_ops,
95+
#endif
9296
};
9397

9498
unsigned long page_ext_size;

0 commit comments

Comments
 (0)