summaryrefslogtreecommitdiff
path: root/sys/dev/kcov.c
diff options
context:
space:
mode:
authoranton <anton@cvs.openbsd.org>2019-05-19 08:55:28 +0000
committeranton <anton@cvs.openbsd.org>2019-05-19 08:55:28 +0000
commit2d2c77aab4bf0aa09f42fe92df9bce4fd42aee8e (patch)
tree6eef03805646b13eefbc2bc0e372402b3d84a31f /sys/dev/kcov.c
parent8d31f90aa1eb93b5a4d6ecf4fbbf9a97aa8a156a (diff)
During fuzzing, one or many fuzzing processes are often stuck waiting on
memory from the subproc malloc subsystem which is exhausted. Attempt to circumvent such scenarios by allocation the kcov coverage buffer using km_alloc() instead. With help from kettenis@ and ok visa@
Diffstat (limited to 'sys/dev/kcov.c')
-rw-r--r--sys/dev/kcov.c19
1 files changed, 12 insertions, 7 deletions
diff --git a/sys/dev/kcov.c b/sys/dev/kcov.c
index bdf727747e5..384951aebdc 100644
--- a/sys/dev/kcov.c
+++ b/sys/dev/kcov.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kcov.c,v 1.14 2019/05/14 13:44:45 jsg Exp $ */
+/* $OpenBSD: kcov.c,v 1.15 2019/05/19 08:55:27 anton Exp $ */
/*
* Copyright (c) 2018 Anton Lindqvist <anton@openbsd.org>
@@ -26,6 +26,8 @@
#include <uvm/uvm_extern.h>
+#define KCOV_BUF_MEMB_SIZE sizeof(uintptr_t)
+
#define KCOV_CMP_CONST 0x1
#define KCOV_CMP_SIZE(x) ((x) << 1)
@@ -343,7 +345,7 @@ kcovmmap(dev_t dev, off_t offset, int prot)
if (kd == NULL)
return (paddr_t)(-1);
- if (offset < 0 || offset >= kd->kd_nmemb * sizeof(uintptr_t))
+ if (offset < 0 || offset >= kd->kd_nmemb * KCOV_BUF_MEMB_SIZE)
return (paddr_t)(-1);
va = (vaddr_t)kd->kd_buf + offset;
@@ -399,11 +401,13 @@ kd_init(struct kcov_dev *kd, unsigned long nmemb)
if (nmemb == 0 || nmemb > KCOV_BUF_MAX_NMEMB)
return (EINVAL);
- size = roundup(nmemb * sizeof(uintptr_t), PAGE_SIZE);
- buf = malloc(size, M_SUBPROC, M_WAITOK | M_ZERO);
- /* malloc() can sleep, ensure the race was won. */
+ size = roundup(nmemb * KCOV_BUF_MEMB_SIZE, PAGE_SIZE);
+ buf = km_alloc(size, &kv_any, &kp_zero, &kd_waitok);
+ if (buf == NULL)
+ return (ENOMEM);
+ /* km_malloc() can sleep, ensure the race was won. */
if (kd->kd_state != KCOV_STATE_NONE) {
- free(buf, M_SUBPROC, size);
+ km_free(buf, size, &kv_any, &kp_zero);
return (EBUSY);
}
kd->kd_buf = buf;
@@ -421,7 +425,8 @@ kd_free(struct kcov_dev *kd)
__func__, kd->kd_unit, kd->kd_state, kd->kd_mode);
TAILQ_REMOVE(&kd_list, kd, kd_entry);
- free(kd->kd_buf, M_SUBPROC, kd->kd_size);
+ if (kd->kd_buf != NULL)
+ km_free(kd->kd_buf, kd->kd_size, &kv_any, &kp_zero);
free(kd, M_SUBPROC, sizeof(*kd));
}