Allocate all arc4random data on the same page.
Saves one dirty page per process.
Test: bionic unit tests, reboot, manual check of /proc/*/maps
Change-Id: Ibbcafa955d60e43f4cb735fa484c6868aa357cd5
diff --git a/libc/upstream-openbsd/android/include/arc4random.h b/libc/upstream-openbsd/android/include/arc4random.h
index 8d965e0..0d70c81 100644
--- a/libc/upstream-openbsd/android/include/arc4random.h
+++ b/libc/upstream-openbsd/android/include/arc4random.h
@@ -28,6 +28,7 @@
#include <signal.h>
#include "private/bionic_prctl.h"
+#include "private/libc_logging.h"
// Android gets these from "thread_private.h".
#include "thread_private.h"
@@ -46,7 +47,7 @@
static inline void
_getentropy_fail(void)
{
- raise(SIGKILL);
+ __libc_fatal("getentropy failed");
}
volatile sig_atomic_t _rs_forked;
@@ -68,21 +69,21 @@
static inline int
_rs_allocate(struct _rs **rsp, struct _rsx **rsxp)
{
- if ((*rsp = mmap(NULL, sizeof(**rsp), PROT_READ|PROT_WRITE,
+ // OpenBSD's arc4random_linux.h allocates two separate mappings, but for
+ // themselves they just allocate both structs into one mapping like this.
+ struct {
+ struct _rs rs;
+ struct _rsx rsx;
+ } *p;
+
+ if ((p = mmap(NULL, sizeof(*p), PROT_READ|PROT_WRITE,
MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
return (-1);
- prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, *rsp, sizeof(**rsp),
- "arc4random _rs structure");
+ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, p, sizeof(*p), "arc4random data");
- if ((*rsxp = mmap(NULL, sizeof(**rsxp), PROT_READ|PROT_WRITE,
- MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) {
- munmap(*rsxp, sizeof(**rsxp));
- return (-1);
- }
-
- prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, *rsxp, sizeof(**rsxp),
- "arc4random _rsx structure");
+ *rsp = &p->rs;
+ *rsxp = &p->rsx;
return (0);
}