From 00bb01a40c811f9645a4b4a956a94e76b0ba5d43 Mon Sep 17 00:00:00 2001 From: "George V. Neville-Neil" Date: Fri, 3 Feb 2017 22:26:19 +0000 Subject: Replace the implementation of DTrace's RAND subroutine for generating low-quality random numbers with a modern implementation (xoroshiro128+) that is capable of generating better quality randomness without compromising performance. Submitted by: Graeme Jenkinson Reviewed by: markj MFC after: 2 weeks Sponsored by: DARPA, AFRL Differential Revision: https://reviews.freebsd.org/D9051 --- .../contrib/opensolaris/uts/common/dtrace/dtrace.c | 23 ++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c') diff --git a/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c b/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c index 7c97c2db0562..1e3d21491b31 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c +++ b/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c @@ -124,6 +124,7 @@ #include #include #include +#include #include #include #include @@ -136,6 +137,8 @@ #include "dtrace_debug.c" #endif +#include "dtrace_xoroshiro128_plus.h" + /* * DTrace Tunable Variables * @@ -298,7 +301,6 @@ static kmutex_t dtrace_meta_lock; /* meta-provider state lock */ #define vuprintf vprintf #define ttoproc(_a) ((_a)->td_proc) #define crgetzoneid(_a) 0 -#define NCPU MAXCPU #define SNOCD 0 #define CPU_ON_INTR(_a) 0 @@ -4236,7 +4238,8 @@ dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs, switch (subr) { case DIF_SUBR_RAND: - regs[rd] = (dtrace_gethrtime() * 2416 + 374441) % 1771875; + regs[rd] = dtrace_xoroshiro128_plus_next( + state->dts_rstate[curcpu]); break; #ifdef illumos @@ -14495,6 +14498,7 @@ dtrace_state_create(struct cdev *dev, struct ucred *cred __unused) dtrace_state_t *state; dtrace_optval_t *opt; int bufsize = NCPU * sizeof (dtrace_buffer_t), i; + int cpu_it; ASSERT(MUTEX_HELD(&dtrace_lock)); ASSERT(MUTEX_HELD(&cpu_lock)); @@ -14550,6 +14554,21 @@ dtrace_state_create(struct cdev *dev, struct ucred *cred __unused) state->dts_buffer = kmem_zalloc(bufsize, KM_SLEEP); state->dts_aggbuffer = kmem_zalloc(bufsize, KM_SLEEP); + /* + * Allocate and initialise the per-process per-CPU random state. + * SI_SUB_RANDOM < SI_SUB_DTRACE_ANON therefore entropy device is + * assumed to be seeded at this point (if from Fortuna seed file). + */ + (void) read_random(&state->dts_rstate[0], 2 * sizeof(uint64_t)); + for (cpu_it = 1; cpu_it < NCPU; cpu_it++) { + /* + * Each CPU is assigned a 2^64 period, non-overlapping + * subsequence. + */ + dtrace_xoroshiro128_plus_jump(state->dts_rstate[cpu_it-1], + state->dts_rstate[cpu_it]); + } + #ifdef illumos state->dts_cleaner = CYCLIC_NONE; state->dts_deadman = CYCLIC_NONE; -- cgit v1.2.3 From e801af6fba428bbac170018f9ff69e4596d06b3b Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Sun, 5 Feb 2017 02:39:12 +0000 Subject: Use PC-relative relocations for USDT probe sites on i386 and amd64. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When recording probe site addresses in the output DOF file, dtrace -G needs to emit relocations for the .SUNW_dof section in order to obtain the addresses of functions containing probe sites. DTrace expects the addresses to be relative to the base address of the final ELF file, and the amd64 USDT implementation was relying on some unspecified and incorrect behaviour in the base system GNU ld to achieve this. This change reimplements the probe site relocation handling to allow USDT to be used with lld and newer GNU binutils. Specifically, it makes use of R_X86_64_PC64/R_386_PC32 relocations to obtain the probe site address relative to the DOF file address, and adds and uses a new DOF relocation type which computes the final probe site address using these relative offsets. Reported by and discussed with: Rafael EspĂ­ndola MFC after: 1 month Differential Revision: https://reviews.freebsd.org/D9374 --- .../contrib/opensolaris/uts/common/dtrace/dtrace.c | 24 ++++++++++++++-------- 1 file changed, 15 insertions(+), 9 deletions(-) (limited to 'sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c') diff --git a/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c b/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c index 1e3d21491b31..323eaa33525b 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c +++ b/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c @@ -13917,12 +13917,13 @@ err: /* * Apply the relocations from the specified 'sec' (a DOF_SECT_URELHDR) to the - * specified DOF. At present, this amounts to simply adding 'ubase' to the - * site of any user SETX relocations to account for load object base address. - * In the future, if we need other relocations, this function can be extended. + * specified DOF. SETX relocations are computed using 'ubase', the base load + * address of the object containing the DOF, and DOFREL relocations are relative + * to the relocation offset within the DOF. */ static int -dtrace_dof_relocate(dof_hdr_t *dof, dof_sec_t *sec, uint64_t ubase) +dtrace_dof_relocate(dof_hdr_t *dof, dof_sec_t *sec, uint64_t ubase, + uint64_t udaddr) { uintptr_t daddr = (uintptr_t)dof; dof_relohdr_t *dofr = @@ -13960,6 +13961,7 @@ dtrace_dof_relocate(dof_hdr_t *dof, dof_sec_t *sec, uint64_t ubase) case DOF_RELO_NONE: break; case DOF_RELO_SETX: + case DOF_RELO_DOFREL: if (r->dofr_offset >= ts->dofs_size || r->dofr_offset + sizeof (uint64_t) > ts->dofs_size) { dtrace_dof_error(dof, "bad relocation offset"); @@ -13971,7 +13973,11 @@ dtrace_dof_relocate(dof_hdr_t *dof, dof_sec_t *sec, uint64_t ubase) return (-1); } - *(uint64_t *)taddr += ubase; + if (r->dofr_type == DOF_RELO_SETX) + *(uint64_t *)taddr += ubase; + else + *(uint64_t *)taddr += + udaddr + ts->dofs_offset + r->dofr_offset; break; default: dtrace_dof_error(dof, "invalid relocation type"); @@ -13992,7 +13998,7 @@ dtrace_dof_relocate(dof_hdr_t *dof, dof_sec_t *sec, uint64_t ubase) */ static int dtrace_dof_slurp(dof_hdr_t *dof, dtrace_vstate_t *vstate, cred_t *cr, - dtrace_enabling_t **enabp, uint64_t ubase, int noprobes) + dtrace_enabling_t **enabp, uint64_t ubase, uint64_t udaddr, int noprobes) { uint64_t len = dof->dofh_loadsz, seclen; uintptr_t daddr = (uintptr_t)dof; @@ -14154,7 +14160,7 @@ dtrace_dof_slurp(dof_hdr_t *dof, dtrace_vstate_t *vstate, cred_t *cr, switch (sec->dofs_type) { case DOF_SECT_URELHDR: - if (dtrace_dof_relocate(dof, sec, ubase) != 0) + if (dtrace_dof_relocate(dof, sec, ubase, udaddr) != 0) return (-1); break; } @@ -15519,7 +15525,7 @@ dtrace_anon_property(void) } rv = dtrace_dof_slurp(dof, &state->dts_vstate, CRED(), - &dtrace_anon.dta_enabling, 0, B_TRUE); + &dtrace_anon.dta_enabling, 0, 0, B_TRUE); if (rv == 0) rv = dtrace_dof_options(dof, state); @@ -16290,7 +16296,7 @@ dtrace_helper_slurp(dof_hdr_t *dof, dof_helper_t *dhp, struct proc *p) vstate = &help->dthps_vstate; if ((rv = dtrace_dof_slurp(dof, vstate, NULL, &enab, dhp->dofhp_addr, - B_FALSE)) != 0) { + dhp->dofhp_dof, B_FALSE)) != 0) { dtrace_dof_destroy(dof); return (rv); } -- cgit v1.2.3 From 9613442e8388c66a89997769bc09af94b64e77cb Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Sun, 5 Feb 2017 02:47:34 +0000 Subject: Ensure that the DOF string length is divisible by 2. It is an ASCII encoding of a hexadecimal representation of the DOF file used to enable anonymous tracing, so its length should always be even. MFC after: 1 week --- sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c') diff --git a/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c b/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c index 323eaa33525b..c37af1a8307c 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c +++ b/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c @@ -13346,8 +13346,11 @@ dtrace_dof_property(const char *name) data += strlen(name) + 1; /* skip past the '=' */ len = eol - data; + if (len % 2 != 0) { + dtrace_dof_error(NULL, "invalid DOF encoding length"); + goto doferr; + } bytes = len / 2; - if (bytes < sizeof(dof_hdr_t)) { dtrace_dof_error(NULL, "truncated header"); goto doferr; -- cgit v1.2.3