Page MenuHomeFreeBSD

D22839.id65721.diff
No OneTemporary

D22839.id65721.diff

Index: lib/libc/gen/arc4random.h
===================================================================
--- lib/libc/gen/arc4random.h
+++ lib/libc/gen/arc4random.h
@@ -24,10 +24,18 @@
/*
* Stub functions for portability.
*/
+#include <sys/elf.h>
#include <sys/mman.h>
+#include <sys/time.h> /* for sys/vdso.h only. */
+#include <sys/vdso.h>
+#include <machine/atomic.h>
+#include <errno.h>
+#include <stdint.h>
#include <signal.h>
+static uint64_t *fxrng_root_generationp;
+
static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
#define _ARC4_LOCK() \
do { \
@@ -54,6 +62,9 @@
struct _rs rs;
struct _rsx rsx;
} *p;
+#ifndef __ILP32__
+ int error;
+#endif
if ((p = mmap(NULL, sizeof(*p), PROT_READ|PROT_WRITE,
MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
@@ -62,13 +73,44 @@
munmap(p, sizeof(*p));
return (-1);
}
+#ifndef __ILP32__
+ error = _elf_aux_info(AT_FXRNG, &fxrng_root_generationp,
+ sizeof(fxrng_root_generationp));
+ /* XXX: Not rolled out to all arch yet. */
+ if (error == 0) {
+ /*
+ * Need to grab it here on allocation because _rs_init ->
+ * _rs_allocate is invoked *after* getentropy(3) in _rs_stir().
+ */
+ p->rsx.rs_seed_generation =
+ atomic_load_acq_64(fxrng_root_generationp);
+ }
+#endif
*rsp = &p->rs;
*rsxp = &p->rsx;
return (0);
}
+/*
+ * This isn't detecting fork; we're just using the existing callback from
+ * _rs_stir_if_needed() to force arc4random(3) to reseed if the fenestrasX root
+ * seed version has changed. (That is, the root random(4) has reseeded from
+ * pooled entropy.)
+ */
static inline void
_rs_forkdetect(void)
{
+#ifndef __ILP32__
+ if (__predict_false(rs == NULL || rsx == NULL))
+ return;
+ if (fxrng_root_generationp == NULL)
+ return;
+ if (__predict_true(rsx->rs_seed_generation ==
+ atomic_load_acq_64(fxrng_root_generationp)))
+ return;
+
+ /* Invalidate rs_buf to force "stir" (reseed). */
+ memset(rs, 0, sizeof(*rs));
+#endif
}
Index: lib/libc/gen/arc4random.c
===================================================================
--- lib/libc/gen/arc4random.c
+++ lib/libc/gen/arc4random.c
@@ -68,6 +68,9 @@
static struct _rsx {
chacha_ctx rs_chacha; /* chacha context for random keystream */
u_char rs_buf[RSBUFSZ]; /* keystream blocks */
+#ifdef __FreeBSD__
+ uint64_t rs_seed_generation; /* FXRNG seed version */
+#endif
} *rsx;
static inline int _rs_allocate(struct _rs **, struct _rsx **);
@@ -96,6 +99,13 @@
{
u_char rnd[KEYSZ + IVSZ];
+#if defined(__FreeBSD__) && !defined(__ILP32__)
+ if (rsx != NULL && fxrng_root_generationp != NULL) {
+ rsx->rs_seed_generation =
+ atomic_load_acq_64(fxrng_root_generationp);
+ }
+#endif
+
if (getentropy(rnd, sizeof rnd) == -1)
_getentropy_fail();
Index: lib/libc/gen/auxv.c
===================================================================
--- lib/libc/gen/auxv.c
+++ lib/libc/gen/auxv.c
@@ -72,6 +72,7 @@
static char *canary, *pagesizes, *execpath;
static void *timekeep;
static u_long hwcap, hwcap2;
+static void *fxrng_seed_version;
static void
init_aux(void)
@@ -125,6 +126,10 @@
case AT_TIMEKEEP:
timekeep = aux->a_un.a_ptr;
break;
+
+ case AT_FXRNG:
+ fxrng_seed_version = aux->a_un.a_ptr;
+ break;
}
}
}
@@ -224,6 +229,16 @@
} else
res = EINVAL;
break;
+ case AT_FXRNG:
+ if (buflen == sizeof(void *)) {
+ if (fxrng_seed_version != NULL) {
+ *(void **)buf = fxrng_seed_version;
+ res = 0;
+ } else
+ res = ENOENT;
+ } else
+ res = EINVAL;
+ break;
default:
res = ENOENT;
break;
Index: sys/amd64/amd64/elf_machdep.c
===================================================================
--- sys/amd64/amd64/elf_machdep.c
+++ sys/amd64/amd64/elf_machdep.c
@@ -74,7 +74,7 @@
.sv_fixlimit = NULL,
.sv_maxssiz = NULL,
.sv_flags = SV_ABI_FREEBSD | SV_ASLR | SV_LP64 | SV_SHP |
- SV_TIMEKEEP,
+ SV_TIMEKEEP | SV_RNG_SEED_VER,
.sv_set_syscall_retval = cpu_set_syscall_retval,
.sv_fetch_syscall_args = cpu_fetch_syscall_args,
.sv_syscallnames = syscallnames,
Index: sys/dev/random/fenestrasX/fx_brng.c
===================================================================
--- sys/dev/random/fenestrasX/fx_brng.c
+++ sys/dev/random/fenestrasX/fx_brng.c
@@ -39,6 +39,7 @@
#include <sys/sdt.h>
#include <sys/sysctl.h>
#include <sys/systm.h>
+#include <sys/vdso.h>
#include <machine/cpu.h>
@@ -108,6 +109,8 @@
*/
rng->brng_generation++;
atomic_store_rel_64(&fxrng_root_generation, rng->brng_generation);
+ /* Update VDSO version. */
+ fxrng_push_seed_generation(rng->brng_generation);
FXRNG_BRNG_UNLOCK(rng);
}
@@ -129,9 +132,26 @@
rng->brng_generation++;
atomic_store_rel_64(&fxrng_root_generation, rng->brng_generation);
+ /* Update VDSO version. */
+ fxrng_push_seed_generation(rng->brng_generation);
FXRNG_BRNG_UNLOCK(rng);
}
+/*
+ * Sysentvec and VDSO are initialized much later than SI_SUB_RANDOM. When
+ * they're online, go ahead and push an initial root seed version.
+ * INIT_SYSENTVEC runs at SI_SUB_EXEC:SI_ORDER_ANY, and SI_ORDER_ANY is the
+ * maximum value, so we must run at SI_SUB_EXEC+1.
+ */
+static void
+fxrng_vdso_sysinit(void *dummy __unused)
+{
+ FXRNG_BRNG_LOCK(&fxrng_root);
+ fxrng_push_seed_generation(fxrng_root.brng_generation);
+ FXRNG_BRNG_UNLOCK(&fxrng_root);
+}
+SYSINIT(fxrng_vdso, SI_SUB_EXEC + 1, SI_ORDER_ANY, fxrng_vdso_sysinit, NULL);
+
/*
* Grab some bytes off an initialized, current generation RNG.
*
Index: sys/dev/random/fenestrasX/fx_main.c
===================================================================
--- sys/dev/random/fenestrasX/fx_main.c
+++ sys/dev/random/fenestrasX/fx_main.c
@@ -88,7 +88,8 @@
* a while).
*
* Not yet implemented, not in scope, or todo:
- * - Userspace portions -- shared page, like timehands vdso?
+ * - Various initial seeding sources we don't have yet
+ * - In particular, VM migration/copy detection
*/
#include <sys/cdefs.h>
Index: sys/kern/imgact_elf.c
===================================================================
--- sys/kern/imgact_elf.c
+++ sys/kern/imgact_elf.c
@@ -1368,6 +1368,8 @@
AUXARGS_ENTRY(pos, AT_HWCAP, *imgp->sysent->sv_hwcap);
if (imgp->sysent->sv_hwcap2 != NULL)
AUXARGS_ENTRY(pos, AT_HWCAP2, *imgp->sysent->sv_hwcap2);
+ if (imgp->sysent->sv_fxrng_gen_base != 0)
+ AUXARGS_ENTRY(pos, AT_FXRNG, imgp->sysent->sv_fxrng_gen_base);
AUXARGS_ENTRY(pos, AT_NULL, 0);
free(imgp->auxargs, M_TEMP);
Index: sys/kern/kern_sharedpage.c
===================================================================
--- sys/kern/kern_sharedpage.c
+++ sys/kern/kern_sharedpage.c
@@ -60,6 +60,10 @@
static int shared_page_free;
char *shared_page_mapping;
+#ifdef RANDOM_FENESTRASX
+static uint64_t *fxrng_spage_mapping;
+#endif
+
void
shared_page_write(int base, int size, const void *data)
{
@@ -255,6 +259,36 @@
}
#endif
+#ifdef RANDOM_FENESTRASX
+void
+fxrng_push_seed_generation(uint64_t gen)
+{
+ if (fxrng_spage_mapping != NULL)
+ atomic_store_rel_64(fxrng_spage_mapping, gen);
+}
+
+static int
+alloc_sv_fxrng_generation(void)
+{
+ static const uint64_t zero;
+ int base;
+
+ /*
+ * Allocate a full cache line for the fxrng root generation (64-bit
+ * counter). It is important that the line is not shared with
+ * frequently dirtied data, and the shared page allocator lacks a
+ * __read_mostly mechanism. However, PAGE_SIZE is typically large
+ * relative to the amount of stuff we've got in it so far, so maybe the
+ * possible waste isn't an issue.
+ */
+ base = shared_page_alloc(CACHE_LINE_SIZE, CACHE_LINE_SIZE);
+ KASSERT(base != -1, ("%s: base allocation failed", __func__));
+ shared_page_write(base, sizeof(uint64_t), &zero);
+ fxrng_spage_mapping = (void *)(shared_page_mapping + base);
+ return (base);
+}
+#endif
+
void
exec_sysvec_init(void *param)
{
@@ -286,4 +320,10 @@
}
#endif
}
+#ifdef RANDOM_FENESTRASX
+ if ((sv->sv_flags & SV_RNG_SEED_VER) != 0) {
+ sv->sv_fxrng_gen_base = sv->sv_shared_page_base +
+ alloc_sv_fxrng_generation();
+ }
+#endif
}
Index: sys/sys/elf_common.h
===================================================================
--- sys/sys/elf_common.h
+++ sys/sys/elf_common.h
@@ -962,8 +962,9 @@
#define AT_EHDRFLAGS 24 /* e_flags field from elf hdr */
#define AT_HWCAP 25 /* CPU feature flags. */
#define AT_HWCAP2 26 /* CPU feature flags 2. */
+#define AT_FXRNG 27 /* Pointer to root RNG seed version. */
-#define AT_COUNT 27 /* Count of defined aux entry types. */
+#define AT_COUNT 28 /* Count of defined aux entry types. */
/*
* Relocation types.
Index: sys/sys/sysent.h
===================================================================
--- sys/sys/sysent.h
+++ sys/sys/sysent.h
@@ -136,6 +136,7 @@
int (*sv_trap)(struct thread *);
u_long *sv_hwcap; /* Value passed in AT_HWCAP. */
u_long *sv_hwcap2; /* Value passed in AT_HWCAP2. */
+ vm_offset_t sv_fxrng_gen_base;
};
#define SV_ILP32 0x000100 /* 32-bit executable. */
@@ -146,6 +147,7 @@
#define SV_CAPSICUM 0x020000 /* Force cap_enter() on startup. */
#define SV_TIMEKEEP 0x040000 /* Shared page timehands. */
#define SV_ASLR 0x080000 /* ASLR allowed. */
+#define SV_RNG_SEED_VER 0x100000 /* random(4) reseed generation. */
#define SV_ABI_MASK 0xff
#define SV_ABI_ERRNO(p, e) ((p)->p_sysent->sv_errsize <= 0 ? e : \
Index: sys/sys/vdso.h
===================================================================
--- sys/sys/vdso.h
+++ sys/sys/vdso.h
@@ -82,6 +82,9 @@
uint32_t sv_timekeep_gen;
};
+#ifdef RANDOM_FENESTRASX
+void fxrng_push_seed_generation(uint64_t gen);
+#endif
void timekeep_push_vdso(void);
uint32_t tc_fill_vdso_timehands(struct vdso_timehands *vdso_th);

File Metadata

Mime Type
text/plain
Expires
Sat, Jan 31, 6:49 PM (1 h, 18 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28158291
Default Alt Text
D22839.id65721.diff (9 KB)

Event Timeline