Provide helpers that allow architectures implement illegitimate PTE direct accesses while the lazy MMU mode is enabled, such as: pte_t pte = *ptep; *ptep = pte; By contrast, these would have to be: pte_t pte = ptep_get(ptep); set_pte(ptep, pte); The direct PTE accesses pose a real issue on s390. Suggested-by: Ilya Leoshkevich Signed-off-by: Alexander Gordeev --- include/linux/kasan.h | 19 +++++++++++++++++-- mm/kasan/common.c | 14 ++++++++++++++ mm/kasan/kasan.h | 2 ++ mm/kasan/report_generic.c | 3 +++ 4 files changed, 36 insertions(+), 2 deletions(-) diff --git a/include/linux/kasan.h b/include/linux/kasan.h index bf233bde68c7..1aa4d9dd2485 100644 --- a/include/linux/kasan.h +++ b/include/linux/kasan.h @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -35,8 +36,6 @@ typedef unsigned int __bitwise kasan_vmalloc_flags_t; #if defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KASAN_SW_TAGS) -#include - /* Software KASAN implementations use shadow memory. */ #ifdef CONFIG_KASAN_SW_TAGS @@ -134,6 +133,20 @@ static __always_inline void kasan_poison_slab(struct slab *slab) __kasan_poison_slab(slab); } +void __kasan_poison_pte(pte_t *pte, int nr); +static __always_inline void kasan_poison_pte(pte_t *pte, int nr) +{ + if (kasan_enabled()) + __kasan_poison_pte(pte, nr); +} + +void __kasan_unpoison_pte(pte_t *pte, int nr); +static __always_inline void kasan_unpoison_pte(pte_t *pte, int nr) +{ + if (kasan_enabled()) + __kasan_unpoison_pte(pte, nr); +} + void __kasan_unpoison_new_object(struct kmem_cache *cache, void *object); /** * kasan_unpoison_new_object - Temporarily unpoison a new slab object. @@ -414,6 +427,8 @@ static inline bool kasan_unpoison_pages(struct page *page, unsigned int order, return false; } static inline void kasan_poison_slab(struct slab *slab) {} +static inline void kasan_poison_pte(pte_t *pte, int nr) {} +static inline void kasan_unpoison_pte(pte_t *pte, int nr) {} static inline void kasan_unpoison_new_object(struct kmem_cache *cache, void *object) {} static inline void kasan_poison_new_object(struct kmem_cache *cache, diff --git a/mm/kasan/common.c b/mm/kasan/common.c index b7d05c2a6d93..94d106094989 100644 --- a/mm/kasan/common.c +++ b/mm/kasan/common.c @@ -163,6 +163,20 @@ void __kasan_poison_slab(struct slab *slab) KASAN_SLAB_REDZONE, false); } +void __kasan_poison_pte(pte_t *pte, int nr) +{ + if (IS_ALIGNED(sizeof(*pte), KASAN_GRANULE_SIZE)) + kasan_poison(pte, sizeof(*pte) * nr, KASAN_LAZY_MMU_PTE, false); +} +EXPORT_SYMBOL_GPL(__kasan_poison_pte); + +void __kasan_unpoison_pte(pte_t *pte, int nr) +{ + if (IS_ALIGNED(sizeof(*pte), KASAN_GRANULE_SIZE)) + kasan_unpoison(pte, sizeof(*pte) * nr, false); +} +EXPORT_SYMBOL_GPL(__kasan_unpoison_pte); + void __kasan_unpoison_new_object(struct kmem_cache *cache, void *object) { kasan_unpoison(object, cache->object_size, false); diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h index fc9169a54766..1a2d18cdb21d 100644 --- a/mm/kasan/kasan.h +++ b/mm/kasan/kasan.h @@ -144,12 +144,14 @@ static inline bool kasan_requires_meta(void) #define KASAN_PAGE_REDZONE 0xFE /* redzone for kmalloc_large allocation */ #define KASAN_SLAB_REDZONE 0xFC /* redzone for slab object */ #define KASAN_SLAB_FREE 0xFB /* freed slab object */ +#define KASAN_LAZY_MMU_PTE 0xFD /* direct pte access in lazy mmu mode */ #define KASAN_VMALLOC_INVALID 0xF8 /* inaccessible space in vmap area */ #else #define KASAN_PAGE_FREE KASAN_TAG_INVALID #define KASAN_PAGE_REDZONE KASAN_TAG_INVALID #define KASAN_SLAB_REDZONE KASAN_TAG_INVALID #define KASAN_SLAB_FREE KASAN_TAG_INVALID +#define KASAN_LAZY_MMU_PTE KASAN_TAG_INVALID #define KASAN_VMALLOC_INVALID KASAN_TAG_INVALID /* only used for SW_TAGS */ #endif diff --git a/mm/kasan/report_generic.c b/mm/kasan/report_generic.c index f5b8e37b3805..489d4a8d6902 100644 --- a/mm/kasan/report_generic.c +++ b/mm/kasan/report_generic.c @@ -113,6 +113,9 @@ static const char *get_shadow_bug_type(struct kasan_report_info *info) case KASAN_SLAB_FREE_META: bug_type = "slab-use-after-free"; break; + case KASAN_LAZY_MMU_PTE: + bug_type = "lazy-mmu-pte-access"; + break; case KASAN_ALLOCA_LEFT: case KASAN_ALLOCA_RIGHT: bug_type = "alloca-out-of-bounds"; -- 2.53.0