Commit 2c9bd9d8 authored by Will Deacon's avatar Will Deacon
Browse files

Merge branch 'for-next/kasan' into for-next/core

Optimise out-of-line KASAN checking when using software tagging.

* for-next/kasan:
  kasan: arm64: support specialized outlined tag mismatch checks
parents 181a1269 1cbdf60b
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -23,4 +23,10 @@ long long __ashlti3(long long a, int b);
long long __ashrti3(long long a, int b);
long long __lshrti3(long long a, int b);

/*
 * This function uses a custom calling convention and cannot be called from C so
 * this prototype is not entirely accurate.
 */
void __hwasan_tag_mismatch(unsigned long addr, unsigned long access_info);

#endif /* __ASM_PROTOTYPES_H */
+15 −2
Original line number Diff line number Diff line
#ifdef CONFIG_ARM64_MODULE_PLTS
SECTIONS {
#ifdef CONFIG_ARM64_MODULE_PLTS
	.plt 0 (NOLOAD) : { BYTE(0) }
	.init.plt 0 (NOLOAD) : { BYTE(0) }
	.text.ftrace_trampoline 0 (NOLOAD) : { BYTE(0) }
}
#endif

#ifdef CONFIG_KASAN_SW_TAGS
	/*
	 * Outlined checks go into comdat-deduplicated sections named .text.hot.
	 * Because they are in comdats they are not combined by the linker and
	 * we otherwise end up with multiple sections with the same .text.hot
	 * name in the .ko file. The kernel module loader warns if it sees
	 * multiple sections with the same name so we use this sections
	 * directive to force them into a single section and silence the
	 * warning.
	 */
	.text.hot : { *(.text.hot) }
#endif
}
+2 −0
Original line number Diff line number Diff line
@@ -18,3 +18,5 @@ obj-$(CONFIG_CRC32) += crc32.o
obj-$(CONFIG_FUNCTION_ERROR_INJECTION) += error-inject.o

obj-$(CONFIG_ARM64_MTE) += mte.o

obj-$(CONFIG_KASAN_SW_TAGS) += kasan_sw_tags.o
+76 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (C) 2020 Google LLC
 */

#include <linux/linkage.h>
#include <asm/assembler.h>

/*
 * Report a tag mismatch detected by tag-based KASAN.
 *
 * A compiler-generated thunk calls this with a non-AAPCS calling
 * convention. Upon entry to this function, registers are as follows:
 *
 * x0:         fault address (see below for restore)
 * x1:         fault description (see below for restore)
 * x2 to x15:  callee-saved
 * x16 to x17: safe to clobber
 * x18 to x30: callee-saved
 * sp:         pre-decremented by 256 bytes (see below for restore)
 *
 * The caller has decremented the SP by 256 bytes, and created a
 * structure on the stack as follows:
 *
 * sp + 0..15:    x0 and x1 to be restored
 * sp + 16..231:  free for use
 * sp + 232..247: x29 and x30 (same as in GPRs)
 * sp + 248..255: free for use
 *
 * Note that this is not a struct pt_regs.
 *
 * To call a regular AAPCS function we must save x2 to x15 (which we can
 * store in the gaps), and create a frame record (for which we can use
 * x29 and x30 spilled by the caller as those match the GPRs).
 *
 * The caller expects x0 and x1 to be restored from the structure, and
 * for the structure to be removed from the stack (i.e. the SP must be
 * incremented by 256 prior to return).
 */
SYM_CODE_START(__hwasan_tag_mismatch)
#ifdef BTI_C
	BTI_C
#endif
	add	x29, sp, #232
	stp	x2, x3, [sp, #8 * 2]
	stp	x4, x5, [sp, #8 * 4]
	stp	x6, x7, [sp, #8 * 6]
	stp	x8, x9, [sp, #8 * 8]
	stp	x10, x11, [sp, #8 * 10]
	stp	x12, x13, [sp, #8 * 12]
	stp	x14, x15, [sp, #8 * 14]
#ifndef CONFIG_SHADOW_CALL_STACK
	str	x18, [sp, #8 * 18]
#endif

	mov	x2, x30
	bl	kasan_tag_mismatch

	ldp	x0, x1, [sp]
	ldp	x2, x3, [sp, #8 * 2]
	ldp	x4, x5, [sp, #8 * 4]
	ldp	x6, x7, [sp, #8 * 6]
	ldp	x8, x9, [sp, #8 * 8]
	ldp	x10, x11, [sp, #8 * 10]
	ldp	x12, x13, [sp, #8 * 12]
	ldp	x14, x15, [sp, #8 * 14]
#ifndef CONFIG_SHADOW_CALL_STACK
	ldr	x18, [sp, #8 * 18]
#endif
	ldp	x29, x30, [sp, #8 * 29]

	/* remove the structure from the stack */
	add	sp, sp, #256
	ret
SYM_CODE_END(__hwasan_tag_mismatch)
EXPORT_SYMBOL(__hwasan_tag_mismatch)
+7 −0
Original line number Diff line number Diff line
@@ -207,3 +207,10 @@ struct kasan_track *kasan_get_free_track(struct kmem_cache *cache,

	return &alloc_meta->free_track[i];
}

void kasan_tag_mismatch(unsigned long addr, unsigned long access_info,
			unsigned long ret_ip)
{
	kasan_report(addr, 1 << (access_info & 0xf), access_info & 0x10,
		     ret_ip);
}
Loading