Skip to content
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
4 changes: 4 additions & 0 deletions Documentation/admin-guide/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2899,6 +2899,10 @@ Kernel parameters
js= [HW,JOY] Analog joystick
See Documentation/input/joydev/joystick.rst.

kasan= [KNL] controls whether KASAN is enabled.
Format: off | on
default: on

kasan_multi_shot
[KNL] Enforce KASAN (Kernel Address Sanitizer) to print
report on every invalid memory access. Without this
Expand Down
2 changes: 0 additions & 2 deletions Documentation/dev-tools/kasan.rst
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,6 @@ Hardware Tag-Based KASAN mode is intended for use in production as a security
mitigation. Therefore, it supports additional boot parameters that allow
disabling KASAN altogether or controlling its features:

- ``kasan=off`` or ``=on`` controls whether KASAN is enabled (default: ``on``).

- ``kasan.mode=sync``, ``=async`` or ``=asymm`` controls whether KASAN
is configured in synchronous, asynchronous or asymmetric mode of
execution (default: ``sync``).
Expand Down
6 changes: 6 additions & 0 deletions arch/arm/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -1135,6 +1135,12 @@ void __init setup_arch(char **cmdline_p)
early_fixmap_init();
early_ioremap_init();

/*
* Initialise the static keys early as they may be enabled by the
* kasan_init() or early parameters.
*/
jump_label_init();

parse_early_param();

#ifdef CONFIG_MMU
Expand Down
3 changes: 3 additions & 0 deletions arch/arm/mm/kasan_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,9 @@ void __init kasan_init(void)
phys_addr_t pa_start, pa_end;
u64 i;

/* If KASAN is disabled via command line, don't initialize it. */
if (kasan_arg_disabled)
return;
/*
* We are going to perform proper setup of shadow memory.
*
Expand Down
7 changes: 7 additions & 0 deletions arch/arm64/mm/kasan_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,9 @@ void __init kasan_populate_early_vm_area_shadow(void *start, unsigned long size)
{
unsigned long shadow_start, shadow_end;

if (!kasan_enabled())
return;

if (!is_vmalloc_or_module_addr(start))
return;

Expand All @@ -397,6 +400,10 @@ void __init kasan_populate_early_vm_area_shadow(void *start, unsigned long size)

void __init kasan_init(void)
{
/* If KASAN is disabled via command line, don't initialize it. */
if (kasan_arg_disabled)
return;

kasan_init_shadow();
kasan_init_depth();
kasan_init_generic();
Expand Down
1 change: 0 additions & 1 deletion arch/loongarch/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ config LOONGARCH
select ACPI_PPTT if ACPI
select ACPI_SYSTEM_POWER_STATES_SUPPORT if ACPI
select ARCH_BINFMT_ELF_STATE
select ARCH_NEEDS_DEFER_KASAN
select ARCH_DISABLE_KASAN_INLINE
select ARCH_ENABLE_MEMORY_HOTPLUG
select ARCH_ENABLE_MEMORY_HOTREMOVE
Expand Down
3 changes: 3 additions & 0 deletions arch/loongarch/mm/kasan_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,9 @@ void __init kasan_init(void)
u64 i;
phys_addr_t pa_start, pa_end;

/* If KASAN is disabled via command line, don't initialize it. */
if (kasan_arg_disabled)
return;
/*
* If PGDIR_SIZE is too large for cpu_vabits, KASAN_SHADOW_END will
* overflow UINTPTR_MAX and then looks like a user space address.
Expand Down
1 change: 0 additions & 1 deletion arch/powerpc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,6 @@ config PPC
# Please keep this list sorted alphabetically.
#
select ARCH_32BIT_OFF_T if PPC32
select ARCH_NEEDS_DEFER_KASAN if PPC_RADIX_MMU
select ARCH_DISABLE_KASAN_INLINE if PPC_RADIX_MMU
select ARCH_DMA_DEFAULT_COHERENT if !NOT_COHERENT_CACHE
select ARCH_ENABLE_MEMORY_HOTPLUG
Expand Down
6 changes: 5 additions & 1 deletion arch/powerpc/mm/kasan/init_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,10 @@ void __init kasan_init(void)
u64 i;
int ret;

/* If KASAN is disabled via command line, don't initialize it. */
if (kasan_arg_disabled)
return;

for_each_mem_range(i, &base, &end) {
phys_addr_t top = min(end, total_lowmem);

Expand Down Expand Up @@ -170,7 +174,7 @@ void __init kasan_init(void)

void __init kasan_late_init(void)
{
if (IS_ENABLED(CONFIG_KASAN_VMALLOC))
if (IS_ENABLED(CONFIG_KASAN_VMALLOC) && kasan_enabled())
kasan_unmap_early_shadow_vmalloc();
}

Expand Down
4 changes: 4 additions & 0 deletions arch/powerpc/mm/kasan/init_book3e_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ void __init kasan_init(void)
u64 i;
pte_t zero_pte = pfn_pte(virt_to_pfn(kasan_early_shadow_page), PAGE_KERNEL_RO);

/* If KASAN is disabled via command line, don't initialize it. */
if (kasan_arg_disabled)
return;

for_each_mem_range(i, &start, &end)
kasan_init_phys_region(phys_to_virt(start), phys_to_virt(end));

Expand Down
4 changes: 4 additions & 0 deletions arch/powerpc/mm/kasan/init_book3s_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ void __init kasan_init(void)
u64 i;
pte_t zero_pte = pfn_pte(virt_to_pfn(kasan_early_shadow_page), PAGE_KERNEL);

/* If KASAN is disabled via command line, don't initialize it. */
if (kasan_arg_disabled)
return;

if (!early_radix_enabled()) {
pr_warn("KASAN not enabled as it requires radix!");
return;
Expand Down
4 changes: 4 additions & 0 deletions arch/riscv/mm/kasan_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,10 @@ void __init kasan_init(void)
phys_addr_t p_start, p_end;
u64 i;

/* If KASAN is disabled via command line, don't initialize it. */
if (kasan_arg_disabled)
return;

create_tmp_mapping();
csr_write(CSR_SATP, PFN_DOWN(__pa(tmp_pg_dir)) | satp_mode);

Expand Down
1 change: 0 additions & 1 deletion arch/um/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ config UML
bool
default y
select ARCH_DISABLE_KASAN_INLINE if STATIC_LINK
select ARCH_NEEDS_DEFER_KASAN if STATIC_LINK
select ARCH_WANTS_DYNAMIC_TASK_STRUCT
select ARCH_HAS_CACHE_LINE_SIZE
select ARCH_HAS_CPU_FINALIZE_INIT
Expand Down
5 changes: 4 additions & 1 deletion arch/um/kernel/mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,11 @@ static unsigned long brk_end;

void __init arch_mm_preinit(void)
{
#ifdef CONFIG_KASAN
/* Safe to call after jump_label_init(). Enables KASAN. */
kasan_init_generic();
if (!kasan_arg_disabled)
kasan_init_generic();
#endif

/* clear the zero-page */
memset(empty_zero_page, 0, PAGE_SIZE);
Expand Down
4 changes: 4 additions & 0 deletions arch/x86/mm/kasan_init_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,10 @@ void __init kasan_init(void)
unsigned long shadow_cea_begin, shadow_cea_per_cpu_begin, shadow_cea_end;
int i;

/* If KASAN is disabled via command line, don't initialize it. */
if (kasan_arg_disabled)
return;

memcpy(early_top_pgt, init_top_pgt, sizeof(early_top_pgt));

/*
Expand Down
1 change: 1 addition & 0 deletions arch/xtensa/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@ void __init setup_arch(char **cmdline_p)
mem_reserve(__pa(_SecondaryResetVector_text_start),
__pa(_SecondaryResetVector_text_end));
#endif
jump_label_init();
parse_early_param();
bootmem_init();
kasan_init();
Expand Down
4 changes: 4 additions & 0 deletions arch/xtensa/mm/kasan_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ void __init kasan_init(void)
{
int i;

/* If KASAN is disabled via command line, don't initialize it. */
if (kasan_arg_disabled)
return;

BUILD_BUG_ON(KASAN_SHADOW_OFFSET != KASAN_SHADOW_START -
(KASAN_START_VADDR >> KASAN_SHADOW_SCALE_SHIFT));
BUILD_BUG_ON(VMALLOC_START < KASAN_START_VADDR);
Expand Down
10 changes: 5 additions & 5 deletions include/linux/kasan-enabled.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@

#include <linux/static_key.h>

#if defined(CONFIG_ARCH_DEFER_KASAN) || defined(CONFIG_KASAN_HW_TAGS)
#ifdef CONFIG_KASAN
extern bool kasan_arg_disabled;

/*
* Global runtime flag for KASAN modes that need runtime control.
* Used by ARCH_DEFER_KASAN architectures and HW_TAGS mode.
*/
DECLARE_STATIC_KEY_FALSE(kasan_flag_enabled);

Expand All @@ -25,14 +26,13 @@ static inline void kasan_enable(void)
static_branch_enable(&kasan_flag_enabled);
}
#else
/* For architectures that can enable KASAN early, use compile-time check. */
static __always_inline bool kasan_enabled(void)
{
return IS_ENABLED(CONFIG_KASAN);
return false;
}

static inline void kasan_enable(void) {}
#endif /* CONFIG_ARCH_DEFER_KASAN || CONFIG_KASAN_HW_TAGS */
#endif

#ifdef CONFIG_KASAN_HW_TAGS
static inline bool kasan_hw_tags_enabled(void)
Expand Down
7 changes: 6 additions & 1 deletion include/linux/kasan.h
Original file line number Diff line number Diff line change
Expand Up @@ -492,7 +492,12 @@ size_t kasan_metadata_size(struct kmem_cache *cache, bool in_object);
void kasan_cache_create(struct kmem_cache *cache, unsigned int *size,
slab_flags_t *flags);

void kasan_cache_shrink(struct kmem_cache *cache);
void __kasan_cache_shrink(struct kmem_cache *cache);
static inline void kasan_cache_shrink(struct kmem_cache *cache)
{
if (kasan_enabled())
__kasan_cache_shrink(cache);
}
void kasan_cache_shutdown(struct kmem_cache *cache);
void kasan_record_aux_stack(void *ptr);

Expand Down
12 changes: 0 additions & 12 deletions lib/Kconfig.kasan
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,6 @@ config ARCH_DISABLE_KASAN_INLINE
Disables both inline and stack instrumentation. Selected by
architectures that do not support these instrumentation types.

config ARCH_NEEDS_DEFER_KASAN
bool

config ARCH_DEFER_KASAN
def_bool y
depends on KASAN && ARCH_NEEDS_DEFER_KASAN
help
Architectures should select this if they need to defer KASAN
initialization until shadow memory is properly set up. This
enables runtime control via static keys. Otherwise, KASAN uses
compile-time constants for better performance.

config CC_HAS_KASAN_GENERIC
def_bool $(cc-option, -fsanitize=kernel-address)

Expand Down
21 changes: 19 additions & 2 deletions mm/kasan/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,31 @@
#include "kasan.h"
#include "../slab.h"

#if defined(CONFIG_ARCH_DEFER_KASAN) || defined(CONFIG_KASAN_HW_TAGS)
/*
* Definition of the unified static key declared in kasan-enabled.h.
* This provides consistent runtime enable/disable across KASAN modes.
*/
DEFINE_STATIC_KEY_FALSE(kasan_flag_enabled);
EXPORT_SYMBOL_GPL(kasan_flag_enabled);
#endif

bool kasan_arg_disabled __ro_after_init;

/* kasan=off/on */
static int __init early_kasan_flag(char *arg)
{
if (!arg)
return -EINVAL;

if (!strcmp(arg, "off"))
kasan_arg_disabled = true;
else if (!strcmp(arg, "on"))
kasan_arg_disabled = false;
else
return -EINVAL;

return 0;
}
early_param("kasan", early_kasan_flag);

struct slab *kasan_addr_to_slab(const void *addr)
{
Expand Down
16 changes: 14 additions & 2 deletions mm/kasan/generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -212,14 +212,14 @@ bool kasan_byte_accessible(const void *addr)
return shadow_byte >= 0 && shadow_byte < KASAN_GRANULE_SIZE;
}

void kasan_cache_shrink(struct kmem_cache *cache)
void __kasan_cache_shrink(struct kmem_cache *cache)
{
kasan_quarantine_remove_cache(cache);
}

void kasan_cache_shutdown(struct kmem_cache *cache)
{
if (!__kmem_cache_empty(cache))
if (kasan_enabled() && !__kmem_cache_empty(cache))
kasan_quarantine_remove_cache(cache);
}

Expand All @@ -239,6 +239,9 @@ void __asan_register_globals(void *ptr, ssize_t size)
int i;
struct kasan_global *globals = ptr;

if (!kasan_enabled())
return;

for (i = 0; i < size; i++)
register_global(&globals[i]);
}
Expand Down Expand Up @@ -369,6 +372,9 @@ void kasan_cache_create(struct kmem_cache *cache, unsigned int *size,
unsigned int rem_free_meta_size;
unsigned int orig_alloc_meta_offset;

if (!kasan_enabled())
return;

if (!kasan_requires_meta())
return;

Expand Down Expand Up @@ -518,6 +524,9 @@ size_t kasan_metadata_size(struct kmem_cache *cache, bool in_object)
{
struct kasan_cache *info = &cache->kasan_info;

if (!kasan_enabled())
return 0;

if (!kasan_requires_meta())
return 0;

Expand All @@ -543,6 +552,9 @@ void kasan_record_aux_stack(void *addr)
struct kasan_alloc_meta *alloc_meta;
void *object;

if (!kasan_enabled())
return;

if (is_kfence_address(addr) || !slab)
return;

Expand Down
Loading
Loading