Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mte/kasan: Implementing KASAN memory protection for ARM64 hardware MTE #15461

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions arch/arm64/include/memtag.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/****************************************************************************
* arch/arm64/include/memtag.h
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/

#ifndef ___ARCH_ARM64_INCLUDE_MEMTAG_H
#define ___ARCH_ARM64_INCLUDE_MEMTAG_H

/****************************************************************************
* Public Function Prototypes
****************************************************************************/

/* Initialize MTE settings and enable memory tagging */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need move to arch.h


void up_memtag_init(void);

/* Check if MTE is enabled */

bool up_memtag_is_enable(void);

/* Set MTE state */

void up_memtag_bypass(bool bypass);

/* Set memory tags for a given memory range */

void up_memtag_set_tag(const void *addr, size_t size);

/* Get a random label based on the address through the mte register */

uint8_t up_memtag_get_random_tag(const void *addr);

/* Get the address without label */

void *up_memtag_get_untagged_addr(const void *addr);

/* Get the address with label */

void *up_memtag_get_tagged_addr(const void *addr, uint8_t tag);

#endif /* ___ARCH_ARM64_INCLUDE_MEMTAG_H */
6 changes: 0 additions & 6 deletions arch/arm64/src/common/arm64_arch.h
Original file line number Diff line number Diff line change
Expand Up @@ -506,12 +506,6 @@ uint64_t arm64_get_mpid(int cpu);
int arm64_get_cpuid(uint64_t mpid);
#endif

#ifdef CONFIG_ARM64_MTE
void arm64_enable_mte(void);
#else
#define arm64_enable_mte()
#endif

#endif /* __ASSEMBLY__ */

#endif /* ___ARCH_ARM64_SRC_COMMON_ARM64_ARCH_H */
6 changes: 4 additions & 2 deletions arch/arm64/src/common/arm64_mmu.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,10 @@
* in the address range [59:55] = 0b00000 are unchecked accesses.
*/

#define TCR_TCMA0 (1ULL << 57)
#define TCR_TCMA1 (1ULL << 58)
#define TCR_TCMA0 BIT(57)
#define TCR_TCMA1 BIT(58)
#define TCR_MTX0_SHIFT BIT(60)
#define TCR_MTX1_SHIFT BIT(61)

#define TCR_PS_BITS_4GB 0x0ULL
#define TCR_PS_BITS_64GB 0x1ULL
Expand Down
88 changes: 85 additions & 3 deletions arch/arm64/src/common/arm64_mte.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,24 @@
#include <stdio.h>

#include "arm64_arch.h"
#include "arm64_mmu.h"

/****************************************************************************
* Pre-processor Definitions
****************************************************************************/

#define GCR_EL1_VAL 0x10001
#define MTE_TAG_SHIFT 56

/* The alignment length of the MTE must be a multiple of sixteen */

#define MTE_MM_AILGN 16

/****************************************************************************
* Private Functions
****************************************************************************/

static int arm64_mte_is_support(void)
static int mte_is_support(void)
{
int supported;
__asm__ volatile (
Expand All @@ -53,15 +59,83 @@ static int arm64_mte_is_support(void)
return supported != 0;
}

static inline uint8_t mte_get_ptr_tag(const void *ptr)
{
return 0xf0 | (uint8_t)(((uint64_t)(ptr)) >> MTE_TAG_SHIFT);
}

/****************************************************************************
* Public Functions
****************************************************************************/

void arm64_enable_mte(void)
uint8_t up_memtag_get_random_tag(const void *addr)
{
asm("irg %0, %0" : "=r" (addr));

return mte_get_ptr_tag(addr);
}

void *up_memtag_get_untagged_addr(const void *addr)
{
return (FAR void *)
(((uint64_t)(addr)) & ~((uint64_t)0xff << MTE_TAG_SHIFT));
}

void *up_memtag_get_tagged_addr(const void *addr, uint8_t tag)
{
return (FAR void *)
(((uint64_t)(addr)) | ((uint64_t)tag << MTE_TAG_SHIFT));
}

/* Read MTE TCF1 */

bool up_memtag_is_enable(void)
{
uint64_t val = read_sysreg(sctlr_el1);

return (val & SCTLR_TCF1_BIT);
}

/* Set MTE state */

void up_memtag_bypass(bool bypass)
{
uint64_t val = read_sysreg(sctlr_el1);

if (bypass)
{
val |= SCTLR_TCF1_BIT;
}
else
{
val &= ~SCTLR_TCF1_BIT;
}

write_sysreg(val, sctlr_el1);
}

/* Set memory tags for a given memory range */

void up_memtag_set_tag(const void *addr, size_t size)
{
size_t i;

DEBUGASSERT((uintptr_t)addr % MTE_MM_AILGN == 0);
DEBUGASSERT(size % MTE_MM_AILGN == 0);

for (i = 0; i < size; i += MTE_MM_AILGN)
{
asm("stg %0, [%0]" : : "r"(addr + i));
}
}

/* Initialize MTE settings and enable memory tagging */

void up_memtag_init(void)
{
uint64_t val;

if (!arm64_mte_is_support())
if (!mte_is_support())
{
return;
}
Expand All @@ -78,6 +152,14 @@ void arm64_enable_mte(void)
assert(!(read_sysreg(ttbr0_el1) & TTBR_CNP_BIT));
assert(!(read_sysreg(ttbr1_el1) & TTBR_CNP_BIT));

/* Controls the default value for skipping high bytes */

val = read_sysreg(tcr_el1);
val |= TCR_TCMA1;
write_sysreg(val, tcr_el1);

/* Enable the MTE function */

val = read_sysreg(sctlr_el1);
val |= SCTLR_ATA_BIT | SCTLR_TCF1_BIT;
write_sysreg(val, sctlr_el1);
Expand Down
5 changes: 4 additions & 1 deletion arch/arm64/src/qemu/qemu_boot.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
# include <nuttx/page.h>
#endif

#include <arch/memtag.h>
#include <arch/chip/chip.h>

#ifdef CONFIG_SMP
Expand Down Expand Up @@ -161,7 +162,9 @@ void arm64_chip_boot(void)

arm64_mmu_init(true);

arm64_enable_mte();
#ifdef CONFIG_ARM64_MTE
up_memtag_init();
#endif

#ifdef CONFIG_DEVICE_TREE
fdt_register((const char *)0x40000000);
Expand Down
37 changes: 37 additions & 0 deletions include/nuttx/mm/kasan.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@
# define kasan_stop()
# define kasan_debugpoint(t,a,s) 0
# define kasan_init_early()
# define kasan_bypass(bypass)
# define kasan_bypass_save() 0
# define kasan_bypass_restore(state) UNUSED(state)
#else

# define kasan_init_early() kasan_stop()
Expand Down Expand Up @@ -159,7 +162,11 @@ FAR void *kasan_reset_tag(FAR const void *addr);
*
****************************************************************************/

#ifdef CONFIG_MM_KASAN_INSTRUMENT
void kasan_start(void);
#else
# define kasan_start()
#endif

/****************************************************************************
* Name: kasan_stop
Expand All @@ -177,7 +184,11 @@ void kasan_start(void);
*
****************************************************************************/

#ifdef CONFIG_MM_KASAN_INSTRUMENT
void kasan_stop(void);
#else
# define kasan_stop()
#endif

/****************************************************************************
* Name: kasan_debugpoint
Expand All @@ -201,6 +212,32 @@ void kasan_stop(void);

int kasan_debugpoint(int type, FAR void *addr, size_t size);

#ifndef CONFIG_MM_KASAN_HW_TAGS
# define kasan_bypass(bypass)
# define kasan_bypass_save() 0
# define kasan_bypass_restore(state) UNUSED(state)
#else

/****************************************************************************
* Name: kasan_bypass
****************************************************************************/

void kasan_bypass(bool bypass);

/****************************************************************************
* Name: kasan_bypass_save
****************************************************************************/

bool kasan_bypass_save(void);

/****************************************************************************
* Name: kasan_bypass_restore
****************************************************************************/

void kasan_bypass_restore(bool state);

#endif

#undef EXTERN
#ifdef __cplusplus
}
Expand Down
14 changes: 11 additions & 3 deletions mm/kasan/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,18 @@ config MM_KASAN_GENERIC
KASan generic mode that does not require hardware support at all

config MM_KASAN_SW_TAGS
bool "KAsan SW tags"
select ARM64_TBI
bool "KAsan softtags tags"
select ARM64_TBI if ARCH_ARM64
select MM_KASAN_INSTRUMENT
depends on ARCH_ARM64
---help---
KAsan based on software tags

config MM_KASAN_HW_TAGS
bool "KAsan hardware tags"
select ARM64_MTE if ARCH_ARM64
---help---
KAsan based on hardware tags

endchoice

config MM_KASAN_INSTRUMENT_ALL
Expand All @@ -52,6 +57,8 @@ config MM_KASAN_INSTRUMENT_ALL
to check. Enabling this option will get image size increased
and performance decreased significantly.

if MM_KASAN_INSTRUMENT

config MM_KASAN_REGIONS
int "Kasan region count"
default 8
Expand Down Expand Up @@ -126,4 +133,5 @@ config MM_KASAN_GLOBAL_ALIGN
It is recommended to use 1, 2, 4, 8, 16, 32.
The maximum value is 32.

endif # MM_KASAN_INSTRUMENT
endif # MM_KASAN
7 changes: 7 additions & 0 deletions mm/kasan/hook.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@
# include "generic.c"
#elif defined(CONFIG_MM_KASAN_SW_TAGS)
# include "sw_tags.c"
#elif defined(CONFIG_MM_KASAN_HW_TAGS)
# include "hw_tags.c"
#else
# define kasan_is_poisoned(addr, size) false
#endif
Expand Down Expand Up @@ -96,6 +98,8 @@

#define KASAN_INIT_VALUE 0xcafe

#ifdef CONFIG_MM_KASAN_INSTRUMENT

/****************************************************************************
* Private Types
****************************************************************************/
Expand Down Expand Up @@ -405,3 +409,6 @@ DEFINE_ASAN_LOAD_STORE(2)
DEFINE_ASAN_LOAD_STORE(4)
DEFINE_ASAN_LOAD_STORE(8)
DEFINE_ASAN_LOAD_STORE(16)

#endif /* CONFIG_MM_KASAN_INSTRUMENT */

Loading
Loading