Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/sys Add DMA instrumentation in KASAN. We note the origin...
details: https://anonhg.NetBSD.org/src/rev/ad5e32b8b27f
branches: trunk
changeset: 1003891:ad5e32b8b27f
user: maxv <maxv%NetBSD.org@localhost>
date: Fri Oct 04 06:27:42 2019 +0000
description:
Add DMA instrumentation in KASAN. We note the original buffer and length in
the map, and check the buffer on each bus_dmamap_sync. This allows us to
find DMA buffer overflows and UAFs, which couldn't be found before because
the device accesses to memory are outside of KASAN's control.
diffstat:
sys/arch/amd64/include/types.h | 3 +-
sys/arch/x86/include/bus_defs.h | 11 +++-
sys/arch/x86/x86/bus_dma.c | 15 +++++-
sys/kern/subr_asan.c | 103 ++++++++++++++++++++++++++++++++++++++-
sys/sys/asan.h | 22 ++++++-
5 files changed, 142 insertions(+), 12 deletions(-)
diffs (300 lines):
diff -r 4752e4616621 -r ad5e32b8b27f sys/arch/amd64/include/types.h
--- a/sys/arch/amd64/include/types.h Fri Oct 04 05:48:11 2019 +0000
+++ b/sys/arch/amd64/include/types.h Fri Oct 04 06:27:42 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: types.h,v 1.62 2019/09/23 23:06:26 kamil Exp $ */
+/* $NetBSD: types.h,v 1.63 2019/10/04 06:27:42 maxv Exp $ */
/*-
* Copyright (c) 1990 The Regents of the University of California.
@@ -108,6 +108,7 @@
#include "opt_kasan.h"
#ifdef KASAN
#define __HAVE_KASAN_INSTR_BUS
+#define __HAVE_KASAN_INSTR_DMA
#endif
#if defined(__x86_64__) && !defined(XENPV)
#if !defined(KASAN)
diff -r 4752e4616621 -r ad5e32b8b27f sys/arch/x86/include/bus_defs.h
--- a/sys/arch/x86/include/bus_defs.h Fri Oct 04 05:48:11 2019 +0000
+++ b/sys/arch/x86/include/bus_defs.h Fri Oct 04 06:27:42 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: bus_defs.h,v 1.3 2019/09/23 16:17:58 skrll Exp $ */
+/* $NetBSD: bus_defs.h,v 1.4 2019/10/04 06:27:42 maxv Exp $ */
/*-
* Copyright (c) 1996, 1997, 1998, 2001 The NetBSD Foundation, Inc.
@@ -64,6 +64,10 @@
#ifndef _X86_BUS_H_
#define _X86_BUS_H_
+#ifdef _KERNEL_OPT
+#include "opt_kasan.h"
+#endif
+
#include <x86/busdefs.h>
#ifdef BUS_SPACE_DEBUG
@@ -141,6 +145,11 @@
/*
* PUBLIC MEMBERS: these are used by machine-independent code.
*/
+#if defined(KASAN)
+ void *dm_buf;
+ bus_size_t dm_buflen;
+ int dm_buftype;
+#endif
bus_size_t dm_maxsegsz; /* largest possible segment */
bus_size_t dm_mapsize; /* size of the mapping */
int dm_nsegs; /* # valid segments in mapping */
diff -r 4752e4616621 -r ad5e32b8b27f sys/arch/x86/x86/bus_dma.c
--- a/sys/arch/x86/x86/bus_dma.c Fri Oct 04 05:48:11 2019 +0000
+++ b/sys/arch/x86/x86/bus_dma.c Fri Oct 04 06:27:42 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: bus_dma.c,v 1.79 2019/06/14 03:35:31 mrg Exp $ */
+/* $NetBSD: bus_dma.c,v 1.80 2019/10/04 06:27:42 maxv Exp $ */
/*-
* Copyright (c) 1996, 1997, 1998, 2007 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: bus_dma.c,v 1.79 2019/06/14 03:35:31 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: bus_dma.c,v 1.80 2019/10/04 06:27:42 maxv Exp $");
/*
* The following is included because _bus_dma_uiomove is derived from
@@ -95,6 +95,7 @@
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/proc.h>
+#include <sys/asan.h>
#include <sys/bus.h>
#include <machine/bus_private.h>
@@ -1327,6 +1328,8 @@
{
bus_dma_tag_t it;
+ kasan_dma_sync(p, o, l, ops);
+
if ((t->bdt_exists & BUS_DMAMAP_OVERRIDE_SYNC) == 0)
; /* skip override */
else for (it = t; it != NULL; it = it->bdt_super) {
@@ -1386,6 +1389,8 @@
{
bus_dma_tag_t it;
+ kasan_dma_load(dmam, buf, buflen, KASAN_DMA_LINEAR);
+
if ((t->bdt_exists & BUS_DMAMAP_OVERRIDE_LOAD) == 0)
; /* skip override */
else for (it = t; it != NULL; it = it->bdt_super) {
@@ -1404,6 +1409,8 @@
{
bus_dma_tag_t it;
+ kasan_dma_load(dmam, chain, 0, KASAN_DMA_MBUF);
+
if ((t->bdt_exists & BUS_DMAMAP_OVERRIDE_LOAD_MBUF) == 0)
; /* skip override */
else for (it = t; it != NULL; it = it->bdt_super) {
@@ -1422,6 +1429,8 @@
{
bus_dma_tag_t it;
+ kasan_dma_load(dmam, uio, 0, KASAN_DMA_UIO);
+
if ((t->bdt_exists & BUS_DMAMAP_OVERRIDE_LOAD_UIO) == 0)
; /* skip override */
else for (it = t; it != NULL; it = it->bdt_super) {
@@ -1441,6 +1450,8 @@
{
bus_dma_tag_t it;
+ kasan_dma_load(dmam, NULL, 0, KASAN_DMA_RAW);
+
if ((t->bdt_exists & BUS_DMAMAP_OVERRIDE_LOAD_RAW) == 0)
; /* skip override */
else for (it = t; it != NULL; it = it->bdt_super) {
diff -r 4752e4616621 -r ad5e32b8b27f sys/kern/subr_asan.c
--- a/sys/kern/subr_asan.c Fri Oct 04 05:48:11 2019 +0000
+++ b/sys/kern/subr_asan.c Fri Oct 04 06:27:42 2019 +0000
@@ -1,7 +1,7 @@
-/* $NetBSD: subr_asan.c,v 1.14 2019/09/22 10:35:12 maxv Exp $ */
+/* $NetBSD: subr_asan.c,v 1.15 2019/10/04 06:27:42 maxv Exp $ */
/*
- * Copyright (c) 2018 The NetBSD Foundation, Inc.
+ * Copyright (c) 2018-2019 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_asan.c,v 1.14 2019/09/22 10:35:12 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_asan.c,v 1.15 2019/10/04 06:27:42 maxv Exp $");
#include <sys/param.h>
#include <sys/device.h>
@@ -932,6 +932,103 @@
/* -------------------------------------------------------------------------- */
+#ifdef __HAVE_KASAN_INSTR_DMA
+
+#include <sys/mbuf.h>
+
+static void
+kasan_dma_sync_linear(uint8_t *buf, bus_addr_t offset, bus_size_t len,
+ bool write, uintptr_t pc)
+{
+ kasan_shadow_check((uintptr_t)(buf + offset), len, write, pc);
+}
+
+static void
+kasan_dma_sync_mbuf(struct mbuf *m, bus_addr_t offset, bus_size_t len,
+ bool write, uintptr_t pc)
+{
+ bus_addr_t minlen;
+
+ for (; m != NULL && len != 0; m = m->m_next) {
+ kasan_shadow_check((uintptr_t)m, sizeof(*m), false, pc);
+
+ if (offset >= m->m_len) {
+ offset -= m->m_len;
+ continue;
+ }
+
+ minlen = MIN(len, m->m_len - offset);
+ kasan_shadow_check((uintptr_t)(mtod(m, char *) + offset),
+ minlen, write, pc);
+
+ offset = 0;
+ len -= minlen;
+ }
+}
+
+static void
+kasan_dma_sync_uio(struct uio *uio, bus_addr_t offset, bus_size_t len,
+ bool write, uintptr_t pc)
+{
+ bus_size_t minlen, resid;
+ struct iovec *iov;
+ int i;
+
+ if (uio->uio_vmspace != NULL)
+ return;
+
+ kasan_shadow_check((uintptr_t)uio, sizeof(struct uio), false, pc);
+
+ resid = uio->uio_resid;
+ iov = uio->uio_iov;
+
+ for (i = 0; i < uio->uio_iovcnt && resid != 0; i++) {
+ kasan_shadow_check((uintptr_t)&iov[i], sizeof(iov[i]),
+ false, pc);
+ minlen = MIN(resid, iov[i].iov_len);
+ kasan_shadow_check((uintptr_t)iov[i].iov_base, minlen,
+ write, pc);
+ resid -= minlen;
+ }
+}
+
+void
+kasan_dma_sync(bus_dmamap_t map, bus_addr_t offset, bus_size_t len, int ops)
+{
+ bool write = (ops & (BUS_DMASYNC_PREWRITE|BUS_DMASYNC_POSTWRITE)) != 0;
+
+ switch (map->dm_buftype) {
+ case KASAN_DMA_LINEAR:
+ kasan_dma_sync_linear(map->dm_buf, offset, len, write,
+ __RET_ADDR);
+ break;
+ case KASAN_DMA_MBUF:
+ kasan_dma_sync_mbuf(map->dm_buf, offset, len, write,
+ __RET_ADDR);
+ break;
+ case KASAN_DMA_UIO:
+ kasan_dma_sync_uio(map->dm_buf, offset, len, write,
+ __RET_ADDR);
+ break;
+ case KASAN_DMA_RAW:
+ break;
+ default:
+ panic("%s: impossible", __func__);
+ }
+}
+
+void
+kasan_dma_load(bus_dmamap_t map, void *buf, bus_size_t buflen, int type)
+{
+ map->dm_buf = buf;
+ map->dm_buflen = buflen;
+ map->dm_buftype = type;
+}
+
+#endif /* __HAVE_KASAN_INSTR_DMA */
+
+/* -------------------------------------------------------------------------- */
+
void __asan_register_globals(struct __asan_global *, size_t);
void __asan_unregister_globals(struct __asan_global *, size_t);
diff -r 4752e4616621 -r ad5e32b8b27f sys/sys/asan.h
--- a/sys/sys/asan.h Fri Oct 04 05:48:11 2019 +0000
+++ b/sys/sys/asan.h Fri Oct 04 06:27:42 2019 +0000
@@ -1,7 +1,7 @@
-/* $NetBSD: asan.h,v 1.10 2019/04/07 09:20:04 maxv Exp $ */
+/* $NetBSD: asan.h,v 1.11 2019/10/04 06:27:42 maxv Exp $ */
/*
- * Copyright (c) 2018 The NetBSD Foundation, Inc.
+ * Copyright (c) 2018-2019 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@@ -36,7 +36,9 @@
#include "opt_kasan.h"
#endif
+#ifdef KASAN
#include <sys/types.h>
+#include <sys/bus.h>
/* Stack redzone values. Part of the compiler ABI. */
#define KASAN_STACK_LEFT 0xF1
@@ -52,17 +54,27 @@
#define KASAN_POOL_REDZONE 0xFD
#define KASAN_POOL_FREED 0xFE
-#ifdef KASAN
+/* DMA types. */
+#define KASAN_DMA_LINEAR 1
+#define KASAN_DMA_MBUF 2
+#define KASAN_DMA_UIO 3
+#define KASAN_DMA_RAW 4
+
void kasan_shadow_map(void *, size_t);
void kasan_early_init(void *);
void kasan_init(void);
void kasan_softint(struct lwp *);
+void kasan_dma_sync(bus_dmamap_t, bus_addr_t, bus_size_t, int);
+void kasan_dma_load(bus_dmamap_t, void *, bus_size_t, int);
+
void kasan_add_redzone(size_t *);
void kasan_mark(const void *, size_t, size_t, uint8_t);
#else
-#define kasan_add_redzone(s) __nothing
-#define kasan_mark(p, s, l, c) __nothing
+#define kasan_dma_sync(m, a, s, o) __nothing
+#define kasan_dma_load(m, b, s, o) __nothing
+#define kasan_add_redzone(s) __nothing
+#define kasan_mark(p, s, l, c) __nothing
#endif
#endif /* !_SYS_ASAN_H_ */
Home |
Main Index |
Thread Index |
Old Index