summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormortimer <mortimer@cvs.openbsd.org>2018-02-08 09:27:45 +0000
committermortimer <mortimer@cvs.openbsd.org>2018-02-08 09:27:45 +0000
commit8bb6cc188ce3a378bddf100774f013c26a29bb16 (patch)
tree81d966d9e482d27ca0b4a1ee21d7cda4bf11ba55
parent7b376b4859578f9a85ceb479b00d2d131f62b9c4 (diff)
Use a temporary chacha instance to fill large randomdata sections. Avoids
grabbing the rnglock repeatedly. ok deraadt@ djm@
-rw-r--r--sys/dev/rnd.c37
-rw-r--r--sys/kern/exec_subr.c51
-rw-r--r--sys/sys/systm.h6
3 files changed, 72 insertions, 22 deletions
diff --git a/sys/dev/rnd.c b/sys/dev/rnd.c
index 5e44048aa1b..945d947943a 100644
--- a/sys/dev/rnd.c
+++ b/sys/dev/rnd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rnd.c,v 1.195 2017/11/26 17:06:46 mikeb Exp $ */
+/* $OpenBSD: rnd.c,v 1.196 2018/02/08 09:27:44 mortimer Exp $ */
/*
* Copyright (c) 2011 Theo de Raadt.
@@ -652,6 +652,41 @@ arc4random_buf(void *buf, size_t n)
}
/*
+ * Allocate a new ChaCha20 context for the caller to use.
+ */
+struct arc4random_ctx *
+arc4random_ctx_new()
+{
+ char keybuf[KEYSZ + IVSZ];
+
+ chacha_ctx *ctx = malloc(sizeof(chacha_ctx), M_TEMP, M_WAITOK);
+ arc4random_buf(keybuf, KEYSZ + IVSZ);
+ chacha_keysetup(ctx, keybuf, 256);
+ chacha_ivsetup(ctx, keybuf + KEYSZ, NULL);
+ explicit_bzero(keybuf, sizeof(keybuf));
+ return (struct arc4random_ctx *)ctx;
+}
+
+/*
+ * Free a ChaCha20 context created by arc4random_ctx_new()
+ */
+void
+arc4random_ctx_free(struct arc4random_ctx *ctx)
+{
+ explicit_bzero(ctx, sizeof(chacha_ctx));
+ free(ctx, M_TEMP, sizeof(chacha_ctx));
+}
+
+/*
+ * Use a given ChaCha20 context to fill a buffer
+ */
+void
+arc4random_ctx_buf(struct arc4random_ctx *ctx, void *buf, size_t n)
+{
+ chacha_encrypt_bytes((chacha_ctx *)ctx, buf, buf, n);
+}
+
+/*
* Calculate a uniformly distributed random number less than upper_bound
* avoiding "modulo bias".
*
diff --git a/sys/kern/exec_subr.c b/sys/kern/exec_subr.c
index c3784909c23..a502b4b773c 100644
--- a/sys/kern/exec_subr.c
+++ b/sys/kern/exec_subr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: exec_subr.c,v 1.52 2017/05/18 18:50:32 kettenis Exp $ */
+/* $OpenBSD: exec_subr.c,v 1.53 2018/02/08 09:27:44 mortimer Exp $ */
/* $NetBSD: exec_subr.c,v 1.9 1994/12/04 03:10:42 mycroft Exp $ */
/*
@@ -283,35 +283,46 @@ vmcmd_map_zero(struct proc *p, struct exec_vmcmd *cmd)
* vmcmd_randomize():
* handle vmcmd which specifies a randomized address space region.
*/
-
+#define RANDOMIZE_CTX_THRESHOLD 512
int
vmcmd_randomize(struct proc *p, struct exec_vmcmd *cmd)
{
- char *buf;
int error;
- size_t off = 0, len;
+ struct arc4random_ctx *ctx;
+ char *buf;
+ size_t count, sublen, off = 0;
+ size_t len = cmd->ev_len;
- if (cmd->ev_len == 0)
+ if (len == 0)
return (0);
- if (cmd->ev_len > ELF_RANDOMIZE_LIMIT)
+ if (len > ELF_RANDOMIZE_LIMIT)
return (EINVAL);
buf = malloc(PAGE_SIZE, M_TEMP, M_WAITOK);
- len = cmd->ev_len;
- do {
- size_t sublen = MIN(len, PAGE_SIZE);
-
- arc4random_buf(buf, sublen);
- error = copyout(buf, (void *)cmd->ev_addr + off, sublen);
- if (error)
- break;
- off += sublen;
- len -= sublen;
- if (len)
- yield();
- } while (len);
+ if (len < RANDOMIZE_CTX_THRESHOLD) {
+ arc4random_buf(buf, len);
+ error = copyout(buf, (void *)cmd->ev_addr, len);
+ explicit_bzero(buf, len);
+ } else {
+ ctx = arc4random_ctx_new();
+ count = 0;
+ do {
+ sublen = MIN(len, PAGE_SIZE);
+ arc4random_ctx_buf(ctx, buf, sublen);
+ error = copyout(buf, (void *)cmd->ev_addr + off, sublen);
+ if (error)
+ break;
+ off += sublen;
+ len -= sublen;
+ if (++count == 32) {
+ count = 0;
+ yield();
+ }
+ } while (len);
+ arc4random_ctx_free(ctx);
+ explicit_bzero(buf, PAGE_SIZE);
+ }
free(buf, M_TEMP, PAGE_SIZE);
-
return (error);
}
diff --git a/sys/sys/systm.h b/sys/sys/systm.h
index 5fa3b80b177..93ddae25307 100644
--- a/sys/sys/systm.h
+++ b/sys/sys/systm.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: systm.h,v 1.137 2018/01/05 11:10:25 pirofti Exp $ */
+/* $OpenBSD: systm.h,v 1.138 2018/02/08 09:27:44 mortimer Exp $ */
/* $NetBSD: systm.h,v 1.50 1996/06/09 04:55:09 briggs Exp $ */
/*-
@@ -210,8 +210,12 @@ int copyin(const void *, void *, size_t)
int copyout(const void *, void *, size_t);
int copyin32(const uint32_t *, uint32_t *);
+struct arc4random_ctx;
void arc4random_buf(void *, size_t)
__attribute__ ((__bounded__(__buffer__,1,2)));
+struct arc4random_ctx *arc4random_ctx_new(void);
+void arc4random_ctx_free(struct arc4random_ctx *);
+void arc4random_ctx_buf(struct arc4random_ctx *, void *, size_t);
u_int32_t arc4random(void);
u_int32_t arc4random_uniform(u_int32_t);