[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250916090109.91132-2-ethan.w.s.graham@gmail.com>
Date: Tue, 16 Sep 2025 09:01:00 +0000
From: Ethan Graham <ethan.w.s.graham@...il.com>
To: ethangraham@...gle.com,
glider@...gle.com
Cc: andreyknvl@...il.com,
andy@...nel.org,
brauner@...nel.org,
brendan.higgins@...ux.dev,
davem@...emloft.net,
davidgow@...gle.com,
dhowells@...hat.com,
dvyukov@...gle.com,
elver@...gle.com,
herbert@...dor.apana.org.au,
ignat@...udflare.com,
jack@...e.cz,
jannh@...gle.com,
johannes@...solutions.net,
kasan-dev@...glegroups.com,
kees@...nel.org,
kunit-dev@...glegroups.com,
linux-crypto@...r.kernel.org,
linux-kernel@...r.kernel.org,
linux-mm@...ck.org,
lukas@...ner.de,
rmoar@...gle.com,
shuah@...nel.org,
tarasmadan@...gle.com
Subject: [PATCH v1 01/10] mm/kasan: implement kasan_poison_range
From: Ethan Graham <ethangraham@...gle.com>
Introduce a new helper function, kasan_poison_range(), to encapsulate
the logic for poisoning an arbitrary memory range of a given size, and
expose it publically in <include/linux/kasan.h>.
This is a preparatory change for the upcoming KFuzzTest patches, which
requires the ability to poison the inter-region padding in its input
buffers.
No functional change to any other subsystem is intended by this commit.
---
v3:
- Enforce KASAN_GRANULE_SIZE alignment for the end of the range in
kasan_poison_range(), and return -EINVAL when this isn't respected.
---
Signed-off-by: Ethan Graham <ethangraham@...gle.com>
---
include/linux/kasan.h | 11 +++++++++++
mm/kasan/shadow.c | 34 ++++++++++++++++++++++++++++++++++
2 files changed, 45 insertions(+)
diff --git a/include/linux/kasan.h b/include/linux/kasan.h
index 890011071f2b..cd6cdf732378 100644
--- a/include/linux/kasan.h
+++ b/include/linux/kasan.h
@@ -102,6 +102,16 @@ static inline bool kasan_has_integrated_init(void)
}
#ifdef CONFIG_KASAN
+
+/**
+ * kasan_poison_range - poison the memory range [@addr, @addr + @size)
+ *
+ * The exact behavior is subject to alignment with KASAN_GRANULE_SIZE, defined
+ * in <mm/kasan/kasan.h>: if @start is unaligned, the initial partial granule
+ * at the beginning of the range is only poisoned if CONFIG_KASAN_GENERIC=y.
+ */
+int kasan_poison_range(const void *addr, size_t size);
+
void __kasan_unpoison_range(const void *addr, size_t size);
static __always_inline void kasan_unpoison_range(const void *addr, size_t size)
{
@@ -402,6 +412,7 @@ static __always_inline bool kasan_check_byte(const void *addr)
#else /* CONFIG_KASAN */
+static inline int kasan_poison_range(const void *start, size_t size) { return 0; }
static inline void kasan_unpoison_range(const void *address, size_t size) {}
static inline void kasan_poison_pages(struct page *page, unsigned int order,
bool init) {}
diff --git a/mm/kasan/shadow.c b/mm/kasan/shadow.c
index d2c70cd2afb1..7faed02264f2 100644
--- a/mm/kasan/shadow.c
+++ b/mm/kasan/shadow.c
@@ -147,6 +147,40 @@ void kasan_poison(const void *addr, size_t size, u8 value, bool init)
}
EXPORT_SYMBOL_GPL(kasan_poison);
+int kasan_poison_range(const void *addr, size_t size)
+{
+ uintptr_t start_addr = (uintptr_t)addr;
+ uintptr_t head_granule_start;
+ uintptr_t poison_body_start;
+ uintptr_t poison_body_end;
+ size_t head_prefix_size;
+ uintptr_t end_addr;
+
+ if ((start_addr + size) % KASAN_GRANULE_SIZE)
+ return -EINVAL;
+
+ end_addr = ALIGN_DOWN(start_addr + size, KASAN_GRANULE_SIZE);
+ if (start_addr >= end_addr)
+ return -EINVAL;
+
+ head_granule_start = ALIGN_DOWN(start_addr, KASAN_GRANULE_SIZE);
+ head_prefix_size = start_addr - head_granule_start;
+
+ if (IS_ENABLED(CONFIG_KASAN_GENERIC) && head_prefix_size > 0)
+ kasan_poison_last_granule((void *)head_granule_start,
+ head_prefix_size);
+
+ poison_body_start = ALIGN(start_addr, KASAN_GRANULE_SIZE);
+ poison_body_end = ALIGN_DOWN(end_addr, KASAN_GRANULE_SIZE);
+
+ if (poison_body_start < poison_body_end)
+ kasan_poison((void *)poison_body_start,
+ poison_body_end - poison_body_start,
+ KASAN_SLAB_REDZONE, false);
+ return 0;
+}
+EXPORT_SYMBOL(kasan_poison_range);
+
#ifdef CONFIG_KASAN_GENERIC
void kasan_poison_last_granule(const void *addr, size_t size)
{
--
2.51.0.384.g4c02a37b29-goog
Powered by blists - more mailing lists