diff options
author | Catalin Marinas <catalin.marinas@arm.com> | 2016-10-11 16:55:11 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-11 18:06:33 -0400 |
commit | 9099daed9c6991a512c1f74b92ec49daf9408cda (patch) | |
tree | 9ebac94f168a0d5d843b715c1d19708d12a1c8c0 /mm/kmemleak.c | |
parent | 0549a3c02efb350776bc869685a361045efd3a29 (diff) |
mm: kmemleak: avoid using __va() on addresses that don't have a lowmem mapping
Some of the kmemleak_*() callbacks in memblock, bootmem, CMA convert a
physical address to a virtual one using __va(). However, such physical
addresses may sometimes be located in highmem and using __va() is
incorrect, leading to inconsistent object tracking in kmemleak.
The following functions have been added to the kmemleak API and they take
a physical address as the object pointer. They only perform the
corresponding action if the address has a lowmem mapping:
kmemleak_alloc_phys
kmemleak_free_part_phys
kmemleak_not_leak_phys
kmemleak_ignore_phys
The affected calling places have been updated to use the new kmemleak
API.
Link: http://lkml.kernel.org/r/1471531432-16503-1-git-send-email-catalin.marinas@arm.com
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Reported-by: Vignesh R <vigneshr@ti.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/kmemleak.c')
-rw-r--r-- | mm/kmemleak.c | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/mm/kmemleak.c b/mm/kmemleak.c index 086292f7c59d..a5e453cf05c4 100644 --- a/mm/kmemleak.c +++ b/mm/kmemleak.c | |||
@@ -90,6 +90,8 @@ | |||
90 | #include <linux/cache.h> | 90 | #include <linux/cache.h> |
91 | #include <linux/percpu.h> | 91 | #include <linux/percpu.h> |
92 | #include <linux/hardirq.h> | 92 | #include <linux/hardirq.h> |
93 | #include <linux/bootmem.h> | ||
94 | #include <linux/pfn.h> | ||
93 | #include <linux/mmzone.h> | 95 | #include <linux/mmzone.h> |
94 | #include <linux/slab.h> | 96 | #include <linux/slab.h> |
95 | #include <linux/thread_info.h> | 97 | #include <linux/thread_info.h> |
@@ -1121,6 +1123,51 @@ void __ref kmemleak_no_scan(const void *ptr) | |||
1121 | } | 1123 | } |
1122 | EXPORT_SYMBOL(kmemleak_no_scan); | 1124 | EXPORT_SYMBOL(kmemleak_no_scan); |
1123 | 1125 | ||
1126 | /** | ||
1127 | * kmemleak_alloc_phys - similar to kmemleak_alloc but taking a physical | ||
1128 | * address argument | ||
1129 | */ | ||
1130 | void __ref kmemleak_alloc_phys(phys_addr_t phys, size_t size, int min_count, | ||
1131 | gfp_t gfp) | ||
1132 | { | ||
1133 | if (!IS_ENABLED(CONFIG_HIGHMEM) || PHYS_PFN(phys) < max_low_pfn) | ||
1134 | kmemleak_alloc(__va(phys), size, min_count, gfp); | ||
1135 | } | ||
1136 | EXPORT_SYMBOL(kmemleak_alloc_phys); | ||
1137 | |||
1138 | /** | ||
1139 | * kmemleak_free_part_phys - similar to kmemleak_free_part but taking a | ||
1140 | * physical address argument | ||
1141 | */ | ||
1142 | void __ref kmemleak_free_part_phys(phys_addr_t phys, size_t size) | ||
1143 | { | ||
1144 | if (!IS_ENABLED(CONFIG_HIGHMEM) || PHYS_PFN(phys) < max_low_pfn) | ||
1145 | kmemleak_free_part(__va(phys), size); | ||
1146 | } | ||
1147 | EXPORT_SYMBOL(kmemleak_free_part_phys); | ||
1148 | |||
1149 | /** | ||
1150 | * kmemleak_not_leak_phys - similar to kmemleak_not_leak but taking a physical | ||
1151 | * address argument | ||
1152 | */ | ||
1153 | void __ref kmemleak_not_leak_phys(phys_addr_t phys) | ||
1154 | { | ||
1155 | if (!IS_ENABLED(CONFIG_HIGHMEM) || PHYS_PFN(phys) < max_low_pfn) | ||
1156 | kmemleak_not_leak(__va(phys)); | ||
1157 | } | ||
1158 | EXPORT_SYMBOL(kmemleak_not_leak_phys); | ||
1159 | |||
1160 | /** | ||
1161 | * kmemleak_ignore_phys - similar to kmemleak_ignore but taking a physical | ||
1162 | * address argument | ||
1163 | */ | ||
1164 | void __ref kmemleak_ignore_phys(phys_addr_t phys) | ||
1165 | { | ||
1166 | if (!IS_ENABLED(CONFIG_HIGHMEM) || PHYS_PFN(phys) < max_low_pfn) | ||
1167 | kmemleak_ignore(__va(phys)); | ||
1168 | } | ||
1169 | EXPORT_SYMBOL(kmemleak_ignore_phys); | ||
1170 | |||
1124 | /* | 1171 | /* |
1125 | * Update an object's checksum and return true if it was modified. | 1172 | * Update an object's checksum and return true if it was modified. |
1126 | */ | 1173 | */ |