Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/kern Improve the KASAN output, provide an error code, to...
details: https://anonhg.NetBSD.org/src/rev/da7f773439a9
branches: trunk
changeset: 997142:da7f773439a9
user: maxv <maxv%NetBSD.org@localhost>
date: Sun Feb 24 10:44:41 2019 +0000
description:
Improve the KASAN output, provide an error code, to help distinguish
classes of bugs.
diffstat:
sys/kern/subr_asan.c | 102 ++++++++++++++++++++++++++++++++++++---------------
1 files changed, 72 insertions(+), 30 deletions(-)
diffs (214 lines):
diff -r f854d60c0500 -r da7f773439a9 sys/kern/subr_asan.c
--- a/sys/kern/subr_asan.c Sun Feb 24 08:02:45 2019 +0000
+++ b/sys/kern/subr_asan.c Sun Feb 24 10:44:41 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: subr_asan.c,v 1.4 2019/02/24 08:02:45 maxv Exp $ */
+/* $NetBSD: subr_asan.c,v 1.5 2019/02/24 10:44:41 maxv Exp $ */
/*
* Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_asan.c,v 1.4 2019/02/24 08:02:45 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_asan.c,v 1.5 2019/02/24 10:44:41 maxv Exp $");
#include <sys/param.h>
#include <sys/device.h>
@@ -52,7 +52,7 @@
#include <machine/asan.h>
/* Our redzone values. */
-#define KASAN_GLOBAL_REDZONE 0xFA
+#define KASAN_MEMORY_FREED 0xFA
#define KASAN_MEMORY_REDZONE 0xFB
/* Stack redzone values. Part of the compiler ABI. */
@@ -163,12 +163,37 @@
kasan_ctors();
}
-static void
-kasan_report(unsigned long addr, size_t size, bool write, unsigned long pc)
+static inline const char *
+kasan_code_name(uint8_t code)
{
- printf("ASan: Unauthorized Access In %p: Addr %p [%zu byte%s, %s]\n",
+ switch (code) {
+ case KASAN_MEMORY_FREED:
+ return "UseAfterFree";
+ case KASAN_MEMORY_REDZONE:
+ return "RedZone";
+ case 1 ... 7:
+ return "RedZonePartial";
+ case KASAN_STACK_LEFT:
+ return "StackLeft";
+ case KASAN_STACK_RIGHT:
+ return "StackRight";
+ case KASAN_STACK_PARTIAL:
+ return "StackPartial";
+ case KASAN_USE_AFTER_SCOPE:
+ return "UseAfterScope";
+ default:
+ return "Unknown";
+ }
+}
+
+static void
+kasan_report(unsigned long addr, size_t size, bool write, unsigned long pc,
+ uint8_t code)
+{
+ printf("ASan: Unauthorized Access In %p: Addr %p [%zu byte%s, %s,"
+ " %s]\n",
(void *)pc, (void *)addr, size, (size > 1 ? "s" : ""),
- (write ? "write" : "read"));
+ (write ? "write" : "read"), kasan_code_name(code));
kasan_md_unwind();
}
@@ -259,69 +284,85 @@
((addr + size - 1) >> KASAN_SHADOW_SCALE_SHIFT)
static __always_inline bool
-kasan_shadow_1byte_isvalid(unsigned long addr)
+kasan_shadow_1byte_isvalid(unsigned long addr, uint8_t *code)
{
int8_t *byte = kasan_md_addr_to_shad((void *)addr);
int8_t last = (addr & KASAN_SHADOW_MASK) + 1;
- return __predict_true(*byte == 0 || last <= *byte);
+ if (__predict_true(*byte == 0 || last <= *byte)) {
+ return true;
+ }
+ *code = *byte;
+ return false;
}
static __always_inline bool
-kasan_shadow_2byte_isvalid(unsigned long addr)
+kasan_shadow_2byte_isvalid(unsigned long addr, uint8_t *code)
{
int8_t *byte, last;
if (ADDR_CROSSES_SCALE_BOUNDARY(addr, 2)) {
- return (kasan_shadow_1byte_isvalid(addr) &&
- kasan_shadow_1byte_isvalid(addr+1));
+ return (kasan_shadow_1byte_isvalid(addr, code) &&
+ kasan_shadow_1byte_isvalid(addr+1, code));
}
byte = kasan_md_addr_to_shad((void *)addr);
last = ((addr + 1) & KASAN_SHADOW_MASK) + 1;
- return __predict_true(*byte == 0 || last <= *byte);
+ if (__predict_true(*byte == 0 || last <= *byte)) {
+ return true;
+ }
+ *code = *byte;
+ return false;
}
static __always_inline bool
-kasan_shadow_4byte_isvalid(unsigned long addr)
+kasan_shadow_4byte_isvalid(unsigned long addr, uint8_t *code)
{
int8_t *byte, last;
if (ADDR_CROSSES_SCALE_BOUNDARY(addr, 4)) {
- return (kasan_shadow_2byte_isvalid(addr) &&
- kasan_shadow_2byte_isvalid(addr+2));
+ return (kasan_shadow_2byte_isvalid(addr, code) &&
+ kasan_shadow_2byte_isvalid(addr+2, code));
}
byte = kasan_md_addr_to_shad((void *)addr);
last = ((addr + 3) & KASAN_SHADOW_MASK) + 1;
- return __predict_true(*byte == 0 || last <= *byte);
+ if (__predict_true(*byte == 0 || last <= *byte)) {
+ return true;
+ }
+ *code = *byte;
+ return false;
}
static __always_inline bool
-kasan_shadow_8byte_isvalid(unsigned long addr)
+kasan_shadow_8byte_isvalid(unsigned long addr, uint8_t *code)
{
int8_t *byte, last;
if (ADDR_CROSSES_SCALE_BOUNDARY(addr, 8)) {
- return (kasan_shadow_4byte_isvalid(addr) &&
- kasan_shadow_4byte_isvalid(addr+4));
+ return (kasan_shadow_4byte_isvalid(addr, code) &&
+ kasan_shadow_4byte_isvalid(addr+4, code));
}
byte = kasan_md_addr_to_shad((void *)addr);
last = ((addr + 7) & KASAN_SHADOW_MASK) + 1;
- return __predict_true(*byte == 0 || last <= *byte);
+ if (__predict_true(*byte == 0 || last <= *byte)) {
+ return true;
+ }
+ *code = *byte;
+ return false;
}
static __always_inline bool
-kasan_shadow_Nbyte_isvalid(unsigned long addr, size_t size)
+kasan_shadow_Nbyte_isvalid(unsigned long addr, size_t size, uint8_t *code)
{
size_t i;
for (i = 0; i < size; i++) {
- if (!kasan_shadow_1byte_isvalid(addr+i))
+ if (!kasan_shadow_1byte_isvalid(addr+i, code))
return false;
}
@@ -332,6 +373,7 @@
kasan_shadow_check(unsigned long addr, size_t size, bool write,
unsigned long retaddr)
{
+ uint8_t code;
bool valid;
if (__predict_false(!kasan_enabled))
@@ -344,27 +386,27 @@
if (__builtin_constant_p(size)) {
switch (size) {
case 1:
- valid = kasan_shadow_1byte_isvalid(addr);
+ valid = kasan_shadow_1byte_isvalid(addr, &code);
break;
case 2:
- valid = kasan_shadow_2byte_isvalid(addr);
+ valid = kasan_shadow_2byte_isvalid(addr, &code);
break;
case 4:
- valid = kasan_shadow_4byte_isvalid(addr);
+ valid = kasan_shadow_4byte_isvalid(addr, &code);
break;
case 8:
- valid = kasan_shadow_8byte_isvalid(addr);
+ valid = kasan_shadow_8byte_isvalid(addr, &code);
break;
default:
- valid = kasan_shadow_Nbyte_isvalid(addr, size);
+ valid = kasan_shadow_Nbyte_isvalid(addr, size, &code);
break;
}
} else {
- valid = kasan_shadow_Nbyte_isvalid(addr, size);
+ valid = kasan_shadow_Nbyte_isvalid(addr, size, &code);
}
if (__predict_false(!valid)) {
- kasan_report(addr, size, write, retaddr);
+ kasan_report(addr, size, write, retaddr, code);
}
}
Home |
Main Index |
Thread Index |
Old Index