Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F143502519
D22839.id65721.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D22839.id65721.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D22839: random(4) fenestrasX: Push root seed version to arc4random(3)
Attached
Detach File
Event Timeline
Log In to Comment