Skip to content

Commit 452c03f

Browse files
melverakpm00
authored andcommitted
kasan: add support for kasan.fault=panic_on_write
KASAN's boot time kernel parameter 'kasan.fault=' currently supports 'report' and 'panic', which results in either only reporting bugs or also panicking on reports. However, some users may wish to have more control over when KASAN reports result in a kernel panic: in particular, KASAN reported invalid _writes_ are of special interest, because they have greater potential to corrupt random kernel memory or be more easily exploited. To panic on invalid writes only, introduce 'kasan.fault=panic_on_write', which allows users to choose to continue running on invalid reads, but panic only on invalid writes. Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Marco Elver <[email protected]> Reviewed-by: Alexander Potapenko <[email protected]> Cc: Aleksandr Nogikh <[email protected]> Cc: Andrey Konovalov <[email protected]> Cc: Andrey Ryabinin <[email protected]> Cc: Dmitry Vyukov <[email protected]> Cc: Jonathan Corbet <[email protected]> Cc: Taras Madan <[email protected]> Cc: Vincenzo Frascino <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent cb0551a commit 452c03f

File tree

2 files changed

+30
-8
lines changed

2 files changed

+30
-8
lines changed

Documentation/dev-tools/kasan.rst

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,10 @@ effectively disables ``panic_on_warn`` for KASAN reports.
107107
Alternatively, independent of ``panic_on_warn``, the ``kasan.fault=`` boot
108108
parameter can be used to control panic and reporting behaviour:
109109

110-
- ``kasan.fault=report`` or ``=panic`` controls whether to only print a KASAN
111-
report or also panic the kernel (default: ``report``). The panic happens even
112-
if ``kasan_multi_shot`` is enabled.
110+
- ``kasan.fault=report``, ``=panic``, or ``=panic_on_write`` controls whether
111+
to only print a KASAN report, panic the kernel, or panic the kernel on
112+
invalid writes only (default: ``report``). The panic happens even if
113+
``kasan_multi_shot`` is enabled.
113114

114115
Software and Hardware Tag-Based KASAN modes (see the section about various
115116
modes below) support altering stack trace collection behavior:

mm/kasan/report.c

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ enum kasan_arg_fault {
4343
KASAN_ARG_FAULT_DEFAULT,
4444
KASAN_ARG_FAULT_REPORT,
4545
KASAN_ARG_FAULT_PANIC,
46+
KASAN_ARG_FAULT_PANIC_ON_WRITE,
4647
};
4748

4849
static enum kasan_arg_fault kasan_arg_fault __ro_after_init = KASAN_ARG_FAULT_DEFAULT;
@@ -57,6 +58,8 @@ static int __init early_kasan_fault(char *arg)
5758
kasan_arg_fault = KASAN_ARG_FAULT_REPORT;
5859
else if (!strcmp(arg, "panic"))
5960
kasan_arg_fault = KASAN_ARG_FAULT_PANIC;
61+
else if (!strcmp(arg, "panic_on_write"))
62+
kasan_arg_fault = KASAN_ARG_FAULT_PANIC_ON_WRITE;
6063
else
6164
return -EINVAL;
6265

@@ -211,7 +214,7 @@ static void start_report(unsigned long *flags, bool sync)
211214
pr_err("==================================================================\n");
212215
}
213216

214-
static void end_report(unsigned long *flags, const void *addr)
217+
static void end_report(unsigned long *flags, const void *addr, bool is_write)
215218
{
216219
if (addr)
217220
trace_error_report_end(ERROR_DETECTOR_KASAN,
@@ -220,8 +223,18 @@ static void end_report(unsigned long *flags, const void *addr)
220223
spin_unlock_irqrestore(&report_lock, *flags);
221224
if (!test_bit(KASAN_BIT_MULTI_SHOT, &kasan_flags))
222225
check_panic_on_warn("KASAN");
223-
if (kasan_arg_fault == KASAN_ARG_FAULT_PANIC)
226+
switch (kasan_arg_fault) {
227+
case KASAN_ARG_FAULT_DEFAULT:
228+
case KASAN_ARG_FAULT_REPORT:
229+
break;
230+
case KASAN_ARG_FAULT_PANIC:
224231
panic("kasan.fault=panic set ...\n");
232+
break;
233+
case KASAN_ARG_FAULT_PANIC_ON_WRITE:
234+
if (is_write)
235+
panic("kasan.fault=panic_on_write set ...\n");
236+
break;
237+
}
225238
add_taint(TAINT_BAD_PAGE, LOCKDEP_NOW_UNRELIABLE);
226239
lockdep_on();
227240
report_suppress_stop();
@@ -536,7 +549,11 @@ void kasan_report_invalid_free(void *ptr, unsigned long ip, enum kasan_report_ty
536549

537550
print_report(&info);
538551

539-
end_report(&flags, ptr);
552+
/*
553+
* Invalid free is considered a "write" since the allocator's metadata
554+
* updates involves writes.
555+
*/
556+
end_report(&flags, ptr, true);
540557
}
541558

542559
/*
@@ -570,7 +587,7 @@ bool kasan_report(const void *addr, size_t size, bool is_write,
570587

571588
print_report(&info);
572589

573-
end_report(&irq_flags, (void *)addr);
590+
end_report(&irq_flags, (void *)addr, is_write);
574591

575592
out:
576593
user_access_restore(ua_flags);
@@ -596,7 +613,11 @@ void kasan_report_async(void)
596613
pr_err("Asynchronous fault: no details available\n");
597614
pr_err("\n");
598615
dump_stack_lvl(KERN_ERR);
599-
end_report(&flags, NULL);
616+
/*
617+
* Conservatively set is_write=true, because no details are available.
618+
* In this mode, kasan.fault=panic_on_write is like kasan.fault=panic.
619+
*/
620+
end_report(&flags, NULL, true);
600621
}
601622
#endif /* CONFIG_KASAN_HW_TAGS */
602623

0 commit comments

Comments
 (0)