diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/rnd.c | 37 | ||||
-rw-r--r-- | sys/kern/exec_subr.c | 51 | ||||
-rw-r--r-- | sys/sys/systm.h | 6 |
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); |