On Thu, Jan 21, 2021 at 5:39 PM Vincenzo Frascino <vincenzo.frasc...@arm.com> wrote: > > Architectures supported by KASAN_HW_TAGS can provide a sync or async mode > of execution. On an MTE enabled arm64 hw for example this can be identified > with the synchronous or asynchronous tagging mode of execution. > In synchronous mode, an exception is triggered if a tag check fault occurs. > In asynchronous mode, if a tag check fault occurs, the TFSR_EL1 register is > updated asynchronously. The kernel checks the corresponding bits > periodically. > > KASAN requires a specific kernel command line parameter to make use of this > hw features. > > Add KASAN HW execution mode kernel command line parameter. > > Note: This patch adds the kasan.mode kernel parameter and the > sync/async kernel command line options to enable the described features. > > Cc: Dmitry Vyukov <dvyu...@google.com> > Cc: Andrey Ryabinin <aryabi...@virtuozzo.com> > Cc: Alexander Potapenko <gli...@google.com> > Cc: Andrey Konovalov <andreyk...@google.com> > Signed-off-by: Vincenzo Frascino <vincenzo.frasc...@arm.com> > --- > Documentation/dev-tools/kasan.rst | 7 +++++++ > lib/test_kasan.c | 2 +- > mm/kasan/hw_tags.c | 27 ++++++++++++++++++++++++++- > mm/kasan/kasan.h | 6 ++++-- > 4 files changed, 38 insertions(+), 4 deletions(-) > > diff --git a/Documentation/dev-tools/kasan.rst > b/Documentation/dev-tools/kasan.rst > index e022b7506e37..7e4a6e0c9f57 100644 > --- a/Documentation/dev-tools/kasan.rst > +++ b/Documentation/dev-tools/kasan.rst > @@ -161,6 +161,13 @@ particular KASAN features. > > - ``kasan=off`` or ``=on`` controls whether KASAN is enabled (default: > ``on``). > > +- ``kasan.mode=sync`` or ``=async`` controls whether KASAN is configured in > + synchronous or asynchronous mode of execution (default: ``sync``). > + ``synchronous mode``: an exception is triggered if a tag check fault > occurs.
Synchronous mode: a bad access is detected immediately when a tag check fault occurs. (No need for `` here, "synchronous mode" is not an inline snippet.) > + ``asynchronous mode``: if a tag check fault occurs, the information is > stored > + asynchronously in hardware (e.g. in the TFSR_EL1 register for arm64). The > kernel > + checks the hardware location and reports an error if the fault is detected. Asynchronous mode: a bad access detection is delayed. When a tag check fault occurs, the information is stored in hardware (in the TFSR_EL1 register for arm64). The kernel periodically checks the hardware and only reports tag faults during these checks. > + > - ``kasan.stacktrace=off`` or ``=on`` disables or enables alloc and free > stack > traces collection (default: ``on`` for ``CONFIG_DEBUG_KERNEL=y``, otherwise > ``off``). > diff --git a/lib/test_kasan.c b/lib/test_kasan.c > index d16ec9e66806..7285dcf9fcc1 100644 > --- a/lib/test_kasan.c > +++ b/lib/test_kasan.c > @@ -97,7 +97,7 @@ static void kasan_test_exit(struct kunit *test) > READ_ONCE(fail_data.report_found)); \ > if (IS_ENABLED(CONFIG_KASAN_HW_TAGS)) { \ > if (READ_ONCE(fail_data.report_found)) \ > - hw_enable_tagging(); \ > + hw_enable_tagging_sync(); \ > migrate_enable(); \ > } \ > } while (0) > diff --git a/mm/kasan/hw_tags.c b/mm/kasan/hw_tags.c > index e529428e7a11..224a2187839c 100644 > --- a/mm/kasan/hw_tags.c > +++ b/mm/kasan/hw_tags.c > @@ -25,6 +25,11 @@ enum kasan_arg { > KASAN_ARG_ON, > }; > > +enum kasan_arg_mode { > + KASAN_ARG_MODE_SYNC, > + KASAN_ARG_MODE_ASYNC, For other modes I explicitly added a _DEFAULT option first. It makes sense to do this here as well for consistency. > +}; > + > enum kasan_arg_stacktrace { > KASAN_ARG_STACKTRACE_DEFAULT, > KASAN_ARG_STACKTRACE_OFF, > @@ -38,6 +43,7 @@ enum kasan_arg_fault { > }; > > static enum kasan_arg kasan_arg __ro_after_init; > +static enum kasan_arg_mode kasan_arg_mode __ro_after_init; > static enum kasan_arg_stacktrace kasan_arg_stacktrace __ro_after_init; > static enum kasan_arg_fault kasan_arg_fault __ro_after_init; > > @@ -68,6 +74,21 @@ static int __init early_kasan_flag(char *arg) > } > early_param("kasan", early_kasan_flag); > > +/* kasan.mode=sync/async */ > +static int __init early_kasan_mode(char *arg) > +{ > + /* If arg is not set the default mode is sync */ > + if ((!arg) || !strcmp(arg, "sync")) > + kasan_arg_mode = KASAN_ARG_MODE_SYNC; > + else if (!strcmp(arg, "async")) > + kasan_arg_mode = KASAN_ARG_MODE_ASYNC; > + else > + return -EINVAL; > + > + return 0; > +} > +early_param("kasan.mode", early_kasan_mode); > + > /* kasan.stacktrace=off/on */ > static int __init early_kasan_flag_stacktrace(char *arg) > { > @@ -115,7 +136,11 @@ void kasan_init_hw_tags_cpu(void) > return; > > hw_init_tags(KASAN_TAG_MAX); > - hw_enable_tagging(); > + Let's add a comment: /* Enable async mode only when explicitly requested through the command line. */ > + if (kasan_arg_mode == KASAN_ARG_MODE_ASYNC) > + hw_enable_tagging_async(); > + else > + hw_enable_tagging_sync(); > } > > /* kasan_init_hw_tags() is called once on boot CPU. */ > diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h > index 07ef7fc742ad..3923d9744105 100644 > --- a/mm/kasan/kasan.h > +++ b/mm/kasan/kasan.h > @@ -294,7 +294,8 @@ static inline const void *arch_kasan_set_tag(const void > *addr, u8 tag) > #define arch_set_mem_tag_range(addr, size, tag) ((void *)(addr)) > #endif > > -#define hw_enable_tagging() arch_enable_tagging() > +#define hw_enable_tagging_sync() arch_enable_tagging_sync() > +#define hw_enable_tagging_async() arch_enable_tagging_async() > #define hw_init_tags(max_tag) arch_init_tags(max_tag) > #define hw_set_tagging_report_once(state) > arch_set_tagging_report_once(state) > #define hw_get_random_tag() arch_get_random_tag() > @@ -303,7 +304,8 @@ static inline const void *arch_kasan_set_tag(const void > *addr, u8 tag) > > #else /* CONFIG_KASAN_HW_TAGS */ > > -#define hw_enable_tagging() > +#define hw_enable_tagging_sync() > +#define hw_enable_tagging_async() > #define hw_set_tagging_report_once(state) > > #endif /* CONFIG_KASAN_HW_TAGS */ > -- > 2.30.0 >