| From: Ilya Leoshkevich <iii@linux.ibm.com> |
| Subject: mm: kfence: disable KMSAN when checking the canary |
| Date: Fri, 21 Jun 2024 13:35:03 +0200 |
| |
| KMSAN warns about check_canary() accessing the canary. |
| |
| The reason is that, even though set_canary() is properly instrumented and |
| sets shadow, slub explicitly poisons the canary's address range |
| afterwards. |
| |
| Unpoisoning the canary is not the right thing to do: only check_canary() |
| is supposed to ever touch it. Instead, disable KMSAN checks around canary |
| read accesses. |
| |
| Link: https://lkml.kernel.org/r/20240621113706.315500-20-iii@linux.ibm.com |
| Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com> |
| Reviewed-by: Alexander Potapenko <glider@google.com> |
| Tested-by: Alexander Potapenko <glider@google.com> |
| Cc: Alexander Gordeev <agordeev@linux.ibm.com> |
| Cc: Christian Borntraeger <borntraeger@linux.ibm.com> |
| Cc: Christoph Lameter <cl@linux.com> |
| Cc: David Rientjes <rientjes@google.com> |
| Cc: Dmitry Vyukov <dvyukov@google.com> |
| Cc: Heiko Carstens <hca@linux.ibm.com> |
| Cc: Hyeonggon Yoo <42.hyeyoo@gmail.com> |
| Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com> |
| Cc: <kasan-dev@googlegroups.com> |
| Cc: Marco Elver <elver@google.com> |
| Cc: Mark Rutland <mark.rutland@arm.com> |
| Cc: Masami Hiramatsu (Google) <mhiramat@kernel.org> |
| Cc: Pekka Enberg <penberg@kernel.org> |
| Cc: Roman Gushchin <roman.gushchin@linux.dev> |
| Cc: Steven Rostedt (Google) <rostedt@goodmis.org> |
| Cc: Sven Schnelle <svens@linux.ibm.com> |
| Cc: Vasily Gorbik <gor@linux.ibm.com> |
| Cc: Vlastimil Babka <vbabka@suse.cz> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| --- |
| |
| mm/kfence/core.c | 11 +++++++++-- |
| 1 file changed, 9 insertions(+), 2 deletions(-) |
| |
| --- a/mm/kfence/core.c~mm-kfence-disable-kmsan-when-checking-the-canary |
| +++ a/mm/kfence/core.c |
| @@ -305,8 +305,14 @@ metadata_update_state(struct kfence_meta |
| WRITE_ONCE(meta->state, next); |
| } |
| |
| +#ifdef CONFIG_KMSAN |
| +#define check_canary_attributes noinline __no_kmsan_checks |
| +#else |
| +#define check_canary_attributes inline |
| +#endif |
| + |
| /* Check canary byte at @addr. */ |
| -static inline bool check_canary_byte(u8 *addr) |
| +static check_canary_attributes bool check_canary_byte(u8 *addr) |
| { |
| struct kfence_metadata *meta; |
| unsigned long flags; |
| @@ -341,7 +347,8 @@ static inline void set_canary(const stru |
| *((u64 *)addr) = KFENCE_CANARY_PATTERN_U64; |
| } |
| |
| -static inline void check_canary(const struct kfence_metadata *meta) |
| +static check_canary_attributes void |
| +check_canary(const struct kfence_metadata *meta) |
| { |
| const unsigned long pageaddr = ALIGN_DOWN(meta->addr, PAGE_SIZE); |
| unsigned long addr = pageaddr; |
| _ |