[PATCH v7 3/4] mm/kasan: Introduce helpers for lazy MMU mode sanitizer

9 views
Skip to first unread message

Alexander Gordeev

unread,
Aug 17, 2026, 7:33:09 AMAug 17
to Gerald Schaefer, Heiko Carstens, Christian Borntraeger, Vasily Gorbik, Claudio Imbrenda, Andrey Ryabinin, linux...@vger.kernel.org, linu...@kvack.org, linux-...@vger.kernel.org, kasa...@googlegroups.com
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 <i...@linux.ibm.com>
Signed-off-by: Alexander Gordeev <agor...@linux.ibm.com>
---
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 <linux/kasan-enabled.h>
#include <linux/kasan-tags.h>
#include <linux/kernel.h>
+#include <linux/pgtable.h>
#include <linux/static_key.h>
#include <linux/types.h>

@@ -35,8 +36,6 @@ typedef unsigned int __bitwise kasan_vmalloc_flags_t;

#if defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KASAN_SW_TAGS)

-#include <linux/pgtable.h>
-
/* 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

Andrey Konovalov

unread,
Aug 17, 2026, 6:11:49 PMAug 17
to Alexander Gordeev, Gerald Schaefer, Heiko Carstens, Christian Borntraeger, Vasily Gorbik, Claudio Imbrenda, Andrey Ryabinin, linux...@vger.kernel.org, linu...@kvack.org, linux-...@vger.kernel.org, kasa...@googlegroups.com
> --
> You received this message because you are subscribed to the Google Groups "kasan-dev" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to kasan-dev+...@googlegroups.com.
> To view this discussion visit https://groups.google.com/d/msgid/kasan-dev/52c9be0cf71a8896a5d76c148c38fb24a2005dd9.1786956464.git.agordeev%40linux.ibm.com.

Hi Alexander,

Should all this be limited to only s390?

Thanks!

Alexander Gordeev

unread,
Aug 18, 2026, 8:01:40 AMAug 18
to Andrey Konovalov, Gerald Schaefer, Heiko Carstens, Christian Borntraeger, Vasily Gorbik, Claudio Imbrenda, Andrey Ryabinin, linux...@vger.kernel.org, linu...@kvack.org, linux-...@vger.kernel.org, kasa...@googlegroups.com
On Tue, Aug 18, 2026 at 12:11:34AM +0200, Andrey Konovalov wrote:
...
> Hi Alexander,
>
> Should all this be limited to only s390?

The idea is to allow any architecture to opt-in. Once [1] is accepted
this may look redundant, but I still see the benefit in having it.

I only did not manage to circumvent the ugly __no_sanitize_address
for ptep_get_lockless() to make it avoid "bogus" kasan complains when
gup_fast walks a page table that entered the lazy mmu mode.

1. https://lore.kernel.org/linux-mm/20260806083926.180...@arm.com/

> Thanks!

Heiko Carstens

unread,
Aug 24, 2026, 5:56:45 AMAug 24
to Alexander Gordeev, Andrey Konovalov, Gerald Schaefer, Christian Borntraeger, Vasily Gorbik, Claudio Imbrenda, Andrey Ryabinin, linux...@vger.kernel.org, linu...@kvack.org, linux-...@vger.kernel.org, kasa...@googlegroups.com
On Tue, Aug 18, 2026 at 02:01:30PM +0200, Alexander Gordeev wrote:
> On Tue, Aug 18, 2026 at 12:11:34AM +0200, Andrey Konovalov wrote:
> ...
> > Hi Alexander,
> >
> > Should all this be limited to only s390?
>
> The idea is to allow any architecture to opt-in. Once [1] is accepted
> this may look redundant, but I still see the benefit in having it.

What would be the benefit if [1] is accepted?

Alexander Gordeev

unread,
Aug 25, 2026, 3:50:39 AMAug 25
to Heiko Carstens, Andrey Konovalov, Gerald Schaefer, Christian Borntraeger, Vasily Gorbik, Claudio Imbrenda, Andrey Ryabinin, linux...@vger.kernel.org, linu...@kvack.org, linux-...@vger.kernel.org, kasa...@googlegroups.com
Just another mechanism for verification, and pretty cheap one.
I would dare to say [1] does not rule out an invalid access completely.

Heiko Carstens

unread,
Aug 25, 2026, 6:08:31 AMAug 25
to Alexander Gordeev, Andrey Konovalov, Gerald Schaefer, Christian Borntraeger, Vasily Gorbik, Claudio Imbrenda, Andrey Ryabinin, linux...@vger.kernel.org, linu...@kvack.org, linux-...@vger.kernel.org, kasa...@googlegroups.com
Ok, maybe we should revisit this when we know how the solution for
page table accesses will be. Then hopefully it should be quite obvious
if this additional code is helpful or not.
Reply all
Reply to author
Forward
0 new messages