Commit b081ee5d authored by Andrey Konovalov's avatar Andrey Konovalov Committed by Vincenzo Frascino
Browse files

kasan: hide invalid free check implementation

This is a preparatory commit for the upcoming addition of a new hardware
tag-based (MTE-based) KASAN mode.

For software KASAN modes the check is based on the value in the shadow
memory. Hardware tag-based KASAN won't be using shadow, so hide the
implementation of the check in check_invalid_free().

Also simplify the code for software tag-based mode.

No functional changes for software modes.

Signed-off-by: default avatarAndrey Konovalov <>
Signed-off-by: Vincenzo Frascino's avatarVincenzo Frascino <>
Reviewed-by: default avatarMarco Elver <>
Reviewed-by: default avatarAlexander Potapenko <>
Change-Id: I5fae9531c9fc948eb4d4e0c589744032fc5a0789
parent 26d1b031
......@@ -278,25 +278,9 @@ void * __must_check kasan_init_slab_obj(struct kmem_cache *cache,
return (void *)object;
static inline bool shadow_invalid(u8 tag, s8 shadow_byte)
return shadow_byte < 0 ||
shadow_byte >= KASAN_GRANULE_SIZE;
if ((u8)shadow_byte == KASAN_TAG_INVALID)
return true;
if ((tag != KASAN_TAG_KERNEL) && (tag != (u8)shadow_byte))
return true;
return false;
static bool __kasan_slab_free(struct kmem_cache *cache, void *object,
unsigned long ip, bool quarantine)
s8 shadow_byte;
u8 tag;
void *tagged_object;
unsigned long rounded_up_size;
......@@ -318,8 +302,7 @@ static bool __kasan_slab_free(struct kmem_cache *cache, void *object,
if (unlikely(cache->flags & SLAB_TYPESAFE_BY_RCU))
return false;
shadow_byte = READ_ONCE(*(s8 *)kasan_mem_to_shadow(object));
if (shadow_invalid(tag, shadow_byte)) {
if (check_invalid_free(tagged_object)) {
kasan_report_invalid_free(tagged_object, ip);
return true;
......@@ -188,6 +188,13 @@ bool check_memory_region(unsigned long addr, size_t size, bool write,
return check_memory_region_inline(addr, size, write, ret_ip);
bool check_invalid_free(void *addr)
s8 shadow_byte = READ_ONCE(*(s8 *)kasan_mem_to_shadow(addr));
return shadow_byte < 0 || shadow_byte >= KASAN_GRANULE_SIZE;
void kasan_cache_shrink(struct kmem_cache *cache)
......@@ -166,6 +166,8 @@ void unpoison_range(const void *address, size_t size);
bool check_memory_region(unsigned long addr, size_t size, bool write,
unsigned long ret_ip);
bool check_invalid_free(void *addr);
void *find_first_bad_addr(void *addr, size_t size);
const char *get_bug_type(struct kasan_access_info *info);
......@@ -121,6 +121,15 @@ bool check_memory_region(unsigned long addr, size_t size, bool write,
return true;
bool check_invalid_free(void *addr)
u8 tag = get_tag(addr);
u8 shadow_byte = READ_ONCE(*(u8 *)kasan_mem_to_shadow(reset_tag(addr)));
return (shadow_byte == KASAN_TAG_INVALID) ||
(tag != KASAN_TAG_KERNEL && tag != shadow_byte);
void __hwasan_load##size##_noabort(unsigned long addr) \
{ \
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment