[PATCH] kasan: arm64: support specialized outlined tag mismatch checks

Mark Rutland mark.rutland at arm.com
Tue Nov 3 10:28:22 EST 2020


Hi Peter,

On Thu, Oct 29, 2020 at 01:59:44PM -0700, Peter Collingbourne wrote:
> Outlined checks require a new runtime function with a custom calling
> convention. Add this function to arch/arm64/lib.

[...]

> +/*
> + * Report a tag mismatch detected by tag-based KASAN.
> + *
> + * This function has a custom calling convention in order to minimize the sizes
> + * of the compiler-generated thunks that call it. All registers except for x16
> + * and x17 must be preserved. This includes x0 and x1 which are used by the
> + * caller to pass arguments, and x29 (the frame pointer register). In order to
> + * allow these registers to be restored the caller spills them to stack. The 256
> + * bytes of stack space allocated by the caller must be deallocated on return.

This is a bit difficult to follow.

Am I right in understanding that the caller has pre-allocated 256 bytes
on the stack by decrementing the SP, yet it's up to the callee to undo
that? That seems bizarre to me, and it would be much easier (and more
generally useful) for the caller to leave it to the trampoline to
allocate/free its own space.

> + *
> + * This function takes care of transitioning to the standard AAPCS calling
> + * convention and calls the C function kasan_tag_mismatch to report the error.
> + *
> + * Parameters:
> + *	x0 - the fault address
> + *	x1 - an encoded description of the faulting access
> + */
> +SYM_FUNC_START(__hwasan_tag_mismatch)

For non-AAPCS code you should use SYM_CODE_*() rather than SYM_FUNC_*(),
and place any BTI instructions necessary manually.

We should probably add SYM_NONSTD_FUNC_*() helpers for trampolines, as
it looks like we didn't add BTIs into the ftrace trampolines (and module
PLTs can get there via indirect branches). I'll put together a
point-fix for ftrace.

> +	add	x29, sp, #232

Where has this offset come from? Is there already a frame record created
by the caller? If so, that should be mentioned in the description of the
calling convention. If not, I don't think this code works.

> +	stp	x2, x3, [sp, #16]
> +	stp	x4, x5, [sp, #32]
> +	stp	x6, x7, [sp, #48]
> +	stp	x8, x9, [sp, #64]
> +	stp	x10, x11, [sp, #80]
> +	stp	x12, x13, [sp, #96]
> +	stp	x14, x15, [sp, #112]

Is there a reason this starts at an offset of 16?

For offsets please use (16 * n) like we do in entry.S, e.g.

|	stp	x2, x3, [sp,  #16 * 0]
|	stp	x4, x5, [sp,  #16 * 1]
|	stp	x4, x5, [sp,  #16 * 2]

... as it makes the relationship clearer.

> +#ifndef CONFIG_SHADOW_CALL_STACK
> +	str	x18, [sp, #128]
> +#endif

This doesn't look right to me. The shadow call stack should remain
balanced across a call, so why do you need to save x18? any manipulation
within kasan_tag_mismatch should be balanced.

Did you mean to save the return address to the shadow stack, rather
than saving the shadow stack pointer?

> +	mov	x2, x30
> +	bl	kasan_tag_mismatch

We didn't preserve x0 and x1 above, so they can be clobbered here, but
the comment said we needed to preserve them.

> +	ldp	x29, x30, [sp, #232]

This doesn't look right. This function didn't save x29/x30 to the stack,
so the only way this could work is if the caller had a redundant frame
record pointing to itself.

> +#ifndef CONFIG_SHADOW_CALL_STACK
> +	ldr	x18, [sp, #128]
> +#endif

As above, this doesn't look right.

> +	ldp	x14, x15, [sp, #112]
> +	ldp	x12, x13, [sp, #96]
> +	ldp	x10, x11, [sp, #80]
> +	ldp	x8, x9, [sp, #64]
> +	ldp	x6, x7, [sp, #48]
> +	ldp	x4, x5, [sp, #32]
> +	ldp	x2, x3, [sp, #16]
> +	ldp	x0, x1, [sp], #256

As above, we didn't save x0 and x1 -- did the caller do that?

Likewise, did the caller allocate 256 bytes that we have to deallocate?
That's *really* confusing.

Thanks,
Mark.



More information about the linux-arm-kernel mailing list