FROMGIT: kasan: untag addresses for KFENCE

[ This change combines two fixes for "kfence, kasan: make KFENCE
  compatible with KASAN" cherry-picked from the mm tree. ]

KFENCE annotations operate on untagged addresses.

Untag addresses in KASAN runtime where they might be tagged.

Signed-off-by: Marco Elver <elver@google.com>
Co-developed-by: Andrey Konovalov <andreyknvl@google.com>
Signed-off-by: Andrey Konovalov <andreyknvl@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
(cherry picked from commit 9c9dcae3169799a0882da9318ea8c335c3fe09da
 https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git akpm)
(cherry picked from commit dec4728fab910da0c86cf9a97e980f4244ebae9f
 https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git akpm)
Bug: 172318110
Signed-off-by: Andrey Konovalov <andreyknvl@google.com>
Change-Id: I5c57ebfce7f8a3754efe7b1215e4eac364fb922a
This commit is contained in:
Andrew Morton 2021-02-03 15:36:58 +11:00 committed by Alistair Delva
parent 13aefe4bf8
commit f03825db4d
3 changed files with 32 additions and 4 deletions

View File

@ -416,7 +416,7 @@ static void *____kasan_kmalloc(struct kmem_cache *cache, const void *object,
if (unlikely(object == NULL))
return NULL;
if (is_kfence_address(object))
if (is_kfence_address(kasan_reset_tag(object)))
return (void *)object;
redzone_start = round_up((unsigned long)(object + size),

View File

@ -3,6 +3,7 @@
#define __MM_KASAN_KASAN_H
#include <linux/kasan.h>
#include <linux/kfence.h>
#include <linux/stackdepot.h>
#ifdef CONFIG_KASAN_HW_TAGS
@ -319,14 +320,28 @@ static inline u8 kasan_random_tag(void) { return 0; }
static inline void kasan_poison(const void *address, size_t size, u8 value)
{
hw_set_mem_tag_range(kasan_reset_tag(address),
address = kasan_reset_tag(address);
/* Skip KFENCE memory if called explicitly outside of sl*b. */
if (is_kfence_address(address))
return;
hw_set_mem_tag_range((void *)address,
round_up(size, KASAN_GRANULE_SIZE), value);
}
static inline void kasan_unpoison(const void *address, size_t size)
{
hw_set_mem_tag_range(kasan_reset_tag(address),
round_up(size, KASAN_GRANULE_SIZE), get_tag(address));
u8 tag = get_tag(address);
address = kasan_reset_tag(address);
/* Skip KFENCE memory if called explicitly outside of sl*b. */
if (is_kfence_address(address))
return;
hw_set_mem_tag_range((void *)address,
round_up(size, KASAN_GRANULE_SIZE), tag);
}
static inline bool kasan_byte_accessible(const void *addr)

View File

@ -13,6 +13,7 @@
#include <linux/init.h>
#include <linux/kasan.h>
#include <linux/kernel.h>
#include <linux/kfence.h>
#include <linux/kmemleak.h>
#include <linux/memory.h>
#include <linux/mm.h>
@ -84,6 +85,10 @@ void kasan_poison(const void *address, size_t size, u8 value)
address = kasan_reset_tag(address);
size = round_up(size, KASAN_GRANULE_SIZE);
/* Skip KFENCE memory if called explicitly outside of sl*b. */
if (is_kfence_address(address))
return;
shadow_start = kasan_mem_to_shadow(address);
shadow_end = kasan_mem_to_shadow(address + size);
@ -102,6 +107,14 @@ void kasan_unpoison(const void *address, size_t size)
*/
address = kasan_reset_tag(address);
/*
* Skip KFENCE memory if called explicitly outside of sl*b. Also note
* that calls to ksize(), where size is not a multiple of machine-word
* size, would otherwise poison the invalid portion of the word.
*/
if (is_kfence_address(address))
return;
kasan_poison(address, size, tag);
if (size & KASAN_GRANULE_MASK) {