40#include <sys/kernel.h>
42#include <sys/malloc.h>
43#include <sys/rwlock.h>
44#include <sys/stddef.h>
45#include <sys/sysent.h>
46#include <sys/sysctl.h>
50#include <vm/vm_param.h>
52#include <vm/vm_extern.h>
53#include <vm/vm_kern.h>
55#include <vm/vm_object.h>
56#include <vm/vm_page.h>
57#include <vm/vm_pager.h>
64#ifdef RANDOM_FENESTRASX
65static struct vdso_fxrng_generation *fxrng_shpage_mapping;
67static bool fxrng_enabled =
true;
68SYSCTL_BOOL(_debug, OID_AUTO, fxrng_vdso_enable, CTLFLAG_RWTUN, &fxrng_enabled,
69 0,
"Enable FXRNG VDSO");
124 VM_PROT_DEFAULT, 0, NULL);
130 addr = kva_alloc(PAGE_SIZE);
131 pmap_qenter(
addr, &m, 1);
148 struct vdso_timehands th;
149 struct vdso_timekeep *tk;
150 uint32_t enabled, idx;
154 idx = svtk->sv_timekeep_curr;
155 if (++idx >= VDSO_TH_NUM)
157 svtk->sv_timekeep_curr = idx;
158 if (++svtk->sv_timekeep_gen == 0)
159 svtk->sv_timekeep_gen = 1;
162 svtk->sv_timekeep_off);
163 tk->tk_th[idx].th_gen = 0;
164 atomic_thread_fence_rel();
167 atomic_store_rel_32(&tk->tk_th[idx].th_gen, svtk->sv_timekeep_gen);
168 atomic_store_rel_32(&tk->tk_current, idx);
174 tk->tk_enabled = enabled;
177#ifdef COMPAT_FREEBSD32
179timehands_update32(
struct vdso_sv_tk *svtk)
181 struct vdso_timehands32 th;
182 struct vdso_timekeep32 *tk;
183 uint32_t enabled, idx;
185 enabled = tc_fill_vdso_timehands32(&th);
187 idx = svtk->sv_timekeep_curr;
188 if (++idx >= VDSO_TH_NUM)
190 svtk->sv_timekeep_curr = idx;
191 if (++svtk->sv_timekeep_gen == 0)
192 svtk->sv_timekeep_gen = 1;
195 svtk->sv_timekeep_off);
196 tk->tk_th[idx].th_gen = 0;
197 atomic_thread_fence_rel();
200 atomic_store_rel_32(&tk->tk_th[idx].th_gen, svtk->sv_timekeep_gen);
201 atomic_store_rel_32(&tk->tk_current, idx);
202 tk->tk_enabled = enabled;
212#ifdef COMPAT_FREEBSD32
213static struct vdso_sv_tk *compat32_svtk;
222#ifdef COMPAT_FREEBSD32
223 if (compat32_svtk != NULL)
224 timehands_update32(compat32_svtk);
231 struct vdso_sv_tk *svtk;
235 tk_ver = VDSO_TK_VER_CURR;
236 svtk =
malloc(
sizeof(
struct vdso_sv_tk), M_TEMP, M_WAITOK | M_ZERO);
238 sizeof(
struct vdso_timehands) * VDSO_TH_NUM, 16);
239 KASSERT(tk_base != -1, (
"tk_base -1 for native"));
241 sizeof(uint32_t), &tk_ver);
242 svtk->sv_timekeep_off = tk_base;
247#ifdef COMPAT_FREEBSD32
249alloc_sv_tk_compat32(
void)
251 struct vdso_sv_tk *svtk;
255 svtk =
malloc(
sizeof(
struct vdso_sv_tk), M_TEMP, M_WAITOK | M_ZERO);
256 tk_ver = VDSO_TK_VER_CURR;
258 sizeof(
struct vdso_timehands32) * VDSO_TH_NUM, 16);
259 KASSERT(tk_base != -1, (
"tk_base -1 for 32bit"));
261 tk_ver),
sizeof(uint32_t), &tk_ver);
262 svtk->sv_timekeep_off = tk_base;
268#ifdef RANDOM_FENESTRASX
270fxrng_push_seed_generation(uint64_t gen)
272 if (fxrng_shpage_mapping == NULL || !fxrng_enabled)
274 KASSERT(gen < INT32_MAX,
275 (
"fxrng seed version shouldn't roll over a 32-bit counter "
276 "for approximately 456,000 years"));
277 atomic_store_rel_32(&fxrng_shpage_mapping->fx_generation32,
282alloc_sv_fxrng_generation(
void)
296 KASSERT(base != -1, (
"%s: base allocation failed", __func__));
298 *fxrng_shpage_mapping = (
struct vdso_fxrng_generation) {
299 .fx_vdso_version = VDSO_FXRNG_VER_CURR,
307 struct sysentvec *sv;
309#ifdef RANDOM_FENESTRASX
316 flags = sv->sv_flags;
317 if ((
flags & SV_SHP) == 0)
319 MPASS(sv->sv_shared_page_obj == NULL);
320 MPASS(sv->sv_shared_page_base != 0);
323 if ((
flags & SV_ABI_MASK) == SV_ABI_FREEBSD) {
324 if ((
flags & SV_DSO_SIG) != 0) {
325 sb = sv->sv_shared_page_base;
329 panic(
"copying sigtramp to shared page");
331 sv->sv_vdso_base = sb;
332 sb += sv->sv_sigcodeoff;
333 sv->sv_sigcode_base = sb;
335 sv->sv_sigcode_base = sv->sv_shared_page_base +
340 if ((
flags & SV_TIMEKEEP) != 0) {
341#ifdef COMPAT_FREEBSD32
342 if ((
flags & SV_ILP32) != 0) {
343 if ((
flags & SV_ABI_MASK) == SV_ABI_FREEBSD) {
344 KASSERT(compat32_svtk == NULL,
345 (
"Compat32 already registered"));
346 compat32_svtk = alloc_sv_tk_compat32();
348 KASSERT(compat32_svtk != NULL,
349 (
"Compat32 not registered"));
351 sv->sv_timekeep_base = sv->sv_shared_page_base +
352 compat32_svtk->sv_timekeep_off;
355 if ((
flags & SV_ABI_MASK) == SV_ABI_FREEBSD) {
357 (
"Host already registered"));
361 (
"Host not registered"));
363 sv->sv_timekeep_base = sv->sv_shared_page_base +
365#ifdef COMPAT_FREEBSD32
369#ifdef RANDOM_FENESTRASX
370 if ((
flags & (SV_ABI_MASK | SV_RNG_SEED_VER)) ==
371 (SV_ABI_FREEBSD | SV_RNG_SEED_VER)) {
376 if (fxrng_shpage_mapping == NULL)
377 alloc_sv_fxrng_generation();
379 sv->sv_fxrng_gen_base = sv->sv_shared_page_base + base;
387 MPASS((sv2->sv_flags & SV_ABI_MASK) == (sv->sv_flags & SV_ABI_MASK));
388 MPASS((sv2->sv_flags & SV_TIMEKEEP) == (sv->sv_flags & SV_TIMEKEEP));
389 MPASS((sv2->sv_flags & SV_SHP) != 0 && (sv->sv_flags & SV_SHP) != 0);
390 MPASS((sv2->sv_flags & SV_DSO_SIG) == (sv->sv_flags & SV_DSO_SIG));
391 MPASS((sv2->sv_flags & SV_RNG_SEED_VER) ==
392 (sv->sv_flags & SV_RNG_SEED_VER));
394 sv2->sv_shared_page_obj = sv->sv_shared_page_obj;
395 sv2->sv_sigcode_base = sv2->sv_shared_page_base +
396 (sv->sv_sigcode_base - sv->sv_shared_page_base);
397 if ((sv2->sv_flags & SV_DSO_SIG) != 0) {
398 sv2->sv_vdso_base = sv2->sv_shared_page_base +
399 (sv->sv_vdso_base - sv->sv_shared_page_base);
401 if ((sv2->sv_flags & SV_ABI_MASK) != SV_ABI_FREEBSD)
403 if ((sv2->sv_flags & SV_TIMEKEEP) != 0) {
404 sv2->sv_timekeep_base = sv2->sv_shared_page_base +
405 (sv->sv_timekeep_base - sv->sv_shared_page_base);
407 if ((sv2->sv_flags & SV_RNG_SEED_VER) != 0) {
408 sv2->sv_fxrng_gen_base = sv2->sv_shared_page_base +
409 (sv->sv_fxrng_gen_base - sv->sv_shared_page_base);
SYSCTL_BOOL(__CONCAT(_kern_elf, __ELF_WORD_SIZE), OID_AUTO, allow_wx, CTLFLAG_RWTUN, &__elfN(allow_wx), 0, "Allow pages to be mapped simultaneously writable and executable")
void *() malloc(size_t size, struct malloc_type *mtp, int flags)
void exec_sysvec_init(void *param)
struct vdso_sv_tk * alloc_sv_tk(void)
int shared_page_fill(int size, int align, const void *data)
SYSINIT(shp, SI_SUB_EXEC, SI_ORDER_FIRST,(sysinit_cfunc_t) shared_page_init, NULL)
char * shared_page_mapping
static void timehands_update(struct vdso_sv_tk *svtk)
static vm_object_t shared_page_obj
void timekeep_push_vdso(void)
static struct vdso_sv_tk * host_svtk
void shared_page_write(int base, int size, const void *data)
static int shared_page_alloc_locked(int size, int align)
static void shared_page_init(void *dummy __unused)
static struct sx shared_page_alloc_sx
static int shared_page_free
int shared_page_alloc(int size, int align)
void exec_sysvec_init_secondary(struct sysentvec *sv, struct sysentvec *sv2)
void panic(const char *fmt,...)
uint32_t tc_fill_vdso_timehands(struct vdso_timehands *vdso_th)