[PATCH RFC v3 16/18] kasan: allow architectures to manage the memory-to-shadow mapping
Christophe Leroy
christophe.leroy at c-s.fr
Wed Mar 13 09:16:22 AEDT 2019
From: Daniel Axtens <dja at axtens.net>
Currently, shadow addresses are always addr >> shift + offset.
However, for powerpc, the virtual address space is fragmented in
ways that make this simple scheme impractical.
Allow architectures to override:
- kasan_shadow_to_mem
- kasan_mem_to_shadow
- addr_has_shadow
Rename addr_has_shadow to kasan_addr_has_shadow as if it is
overridden it will be available in more places, increasing the
risk of collisions.
If architectures do not #define their own versions, the generic
code will continue to run as usual.
Reviewed-by: Dmitry Vyukov <dvyukov at google.com>
Signed-off-by: Daniel Axtens <dja at axtens.net>
Signed-off-by: Christophe Leroy <christophe.leroy at c-s.fr>
---
include/linux/kasan.h | 2 ++
mm/kasan/generic.c | 2 +-
mm/kasan/generic_report.c | 2 +-
mm/kasan/kasan.h | 6 +++++-
mm/kasan/report.c | 6 +++---
mm/kasan/tags.c | 2 +-
6 files changed, 13 insertions(+), 7 deletions(-)
diff --git a/include/linux/kasan.h b/include/linux/kasan.h
index b40ea104dd36..f6261840f94c 100644
--- a/include/linux/kasan.h
+++ b/include/linux/kasan.h
@@ -23,11 +23,13 @@ extern p4d_t kasan_early_shadow_p4d[MAX_PTRS_PER_P4D];
int kasan_populate_early_shadow(const void *shadow_start,
const void *shadow_end);
+#ifndef kasan_mem_to_shadow
static inline void *kasan_mem_to_shadow(const void *addr)
{
return (void *)((unsigned long)addr >> KASAN_SHADOW_SCALE_SHIFT)
+ KASAN_SHADOW_OFFSET;
}
+#endif
/* Enable reporting bugs after kasan_disable_current() */
extern void kasan_enable_current(void);
diff --git a/mm/kasan/generic.c b/mm/kasan/generic.c
index 9e5c989dab8c..a5b28e3ceacb 100644
--- a/mm/kasan/generic.c
+++ b/mm/kasan/generic.c
@@ -173,7 +173,7 @@ static __always_inline void check_memory_region_inline(unsigned long addr,
if (unlikely(size == 0))
return;
- if (unlikely(!addr_has_shadow((void *)addr))) {
+ if (unlikely(!kasan_addr_has_shadow((void *)addr))) {
kasan_report(addr, size, write, ret_ip);
return;
}
diff --git a/mm/kasan/generic_report.c b/mm/kasan/generic_report.c
index 36c645939bc9..6caafd61fc3a 100644
--- a/mm/kasan/generic_report.c
+++ b/mm/kasan/generic_report.c
@@ -107,7 +107,7 @@ static const char *get_wild_bug_type(struct kasan_access_info *info)
const char *get_bug_type(struct kasan_access_info *info)
{
- if (addr_has_shadow(info->access_addr))
+ if (kasan_addr_has_shadow(info->access_addr))
return get_shadow_bug_type(info);
return get_wild_bug_type(info);
}
diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h
index 3e0c11f7d7a1..958e984d4544 100644
--- a/mm/kasan/kasan.h
+++ b/mm/kasan/kasan.h
@@ -110,16 +110,20 @@ struct kasan_alloc_meta *get_alloc_info(struct kmem_cache *cache,
struct kasan_free_meta *get_free_info(struct kmem_cache *cache,
const void *object);
+#ifndef kasan_shadow_to_mem
static inline const void *kasan_shadow_to_mem(const void *shadow_addr)
{
return (void *)(((unsigned long)shadow_addr - KASAN_SHADOW_OFFSET)
<< KASAN_SHADOW_SCALE_SHIFT);
}
+#endif
-static inline bool addr_has_shadow(const void *addr)
+#ifndef kasan_addr_has_shadow
+static inline bool kasan_addr_has_shadow(const void *addr)
{
return (addr >= kasan_shadow_to_mem((void *)KASAN_SHADOW_START));
}
+#endif
void kasan_poison_shadow(const void *address, size_t size, u8 value);
diff --git a/mm/kasan/report.c b/mm/kasan/report.c
index ca9418fe9232..bc3355ee2dd0 100644
--- a/mm/kasan/report.c
+++ b/mm/kasan/report.c
@@ -298,7 +298,7 @@ void kasan_report(unsigned long addr, size_t size,
untagged_addr = reset_tag(tagged_addr);
info.access_addr = tagged_addr;
- if (addr_has_shadow(untagged_addr))
+ if (kasan_addr_has_shadow(untagged_addr))
info.first_bad_addr = find_first_bad_addr(tagged_addr, size);
else
info.first_bad_addr = untagged_addr;
@@ -309,11 +309,11 @@ void kasan_report(unsigned long addr, size_t size,
start_report(&flags);
print_error_description(&info);
- if (addr_has_shadow(untagged_addr))
+ if (kasan_addr_has_shadow(untagged_addr))
print_tags(get_tag(tagged_addr), info.first_bad_addr);
pr_err("\n");
- if (addr_has_shadow(untagged_addr)) {
+ if (kasan_addr_has_shadow(untagged_addr)) {
print_address_description(untagged_addr);
pr_err("\n");
print_shadow_for_address(info.first_bad_addr);
diff --git a/mm/kasan/tags.c b/mm/kasan/tags.c
index 87ebee0a6aea..661c23dd5340 100644
--- a/mm/kasan/tags.c
+++ b/mm/kasan/tags.c
@@ -109,7 +109,7 @@ void check_memory_region(unsigned long addr, size_t size, bool write,
return;
untagged_addr = reset_tag((const void *)addr);
- if (unlikely(!addr_has_shadow(untagged_addr))) {
+ if (unlikely(!kasan_addr_has_shadow(untagged_addr))) {
kasan_report(addr, size, write, ret_ip);
return;
}
--
2.13.3
More information about the Linuxppc-dev
mailing list