summaryrefslogtreecommitdiffstats
path: root/sys/kern/exec_subr.c
diff options
context:
space:
mode:
authorderaadt <deraadt@openbsd.org>2015-02-06 23:58:12 +0000
committerderaadt <deraadt@openbsd.org>2015-02-06 23:58:12 +0000
commit1a0bd10ffe9f658eda7b09dfc58adeac4e2daf87 (patch)
treea812698d9a4f086ed081e6e3011daa8ad2f90051 /sys/kern/exec_subr.c
parentAdd bpf(4) support to iwm(4). Makes tcpdump -i iwm0 work. Based on iwn(4). (diff)
downloadwireguard-openbsd-1a0bd10ffe9f658eda7b09dfc58adeac4e2daf87.tar.xz
wireguard-openbsd-1a0bd10ffe9f658eda7b09dfc58adeac4e2daf87.zip
Raise ELF_RANDOMIZE_LIMIT to 64K, so that programs and libraries can
legitimately use random section variables without execve failures... Because this section is not demand faulted, yield() every page during the fill otherwise the costs are charged poorly. ok tedu matthew
Diffstat (limited to 'sys/kern/exec_subr.c')
-rw-r--r--sys/kern/exec_subr.c24
1 files changed, 18 insertions, 6 deletions
diff --git a/sys/kern/exec_subr.c b/sys/kern/exec_subr.c
index 538e20ecb65..e51b6af910f 100644
--- a/sys/kern/exec_subr.c
+++ b/sys/kern/exec_subr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: exec_subr.c,v 1.46 2014/12/17 06:58:11 guenther Exp $ */
+/* $OpenBSD: exec_subr.c,v 1.47 2015/02/06 23:58:12 deraadt Exp $ */
/* $NetBSD: exec_subr.c,v 1.9 1994/12/04 03:10:42 mycroft Exp $ */
/*
@@ -289,16 +289,28 @@ vmcmd_randomize(struct proc *p, struct exec_vmcmd *cmd)
{
char *buf;
int error;
+ size_t off = 0, len;
if (cmd->ev_len == 0)
return (0);
- if (cmd->ev_len > 1024)
+ if (cmd->ev_len > ELF_RANDOMIZE_LIMIT)
return (EINVAL);
- buf = malloc(cmd->ev_len, M_TEMP, M_WAITOK);
- arc4random_buf(buf, cmd->ev_len);
- error = copyout(buf, (void *)cmd->ev_addr, cmd->ev_len);
- free(buf, M_TEMP, cmd->ev_len);
+ 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);
+ free(buf, M_TEMP, PAGE_SIZE);
return (error);
}