diff options
author | markj <markj@FreeBSD.org> | 2013-10-16 01:39:26 +0000 |
---|---|---|
committer | markj <markj@FreeBSD.org> | 2013-10-16 01:39:26 +0000 |
commit | 3ecc6f129801776dd571d69cf9a262a97ad23968 (patch) | |
tree | bfa7528429d54368e90dad91f35cf9e0231549da | |
parent | 2d5c7e881ca033fc347da3e75f1c18da7564b82e (diff) | |
download | FreeBSD-src-3ecc6f129801776dd571d69cf9a262a97ad23968.zip FreeBSD-src-3ecc6f129801776dd571d69cf9a262a97ad23968.tar.gz |
Add a function, memstr, which can be used to convert a buffer of
null-separated strings to a single string. This can be used to print the
full arguments of a process using execsnoop (from the DTrace toolkit) or
with the following one-liner:
dtrace -n 'syscall::execve:return {trace(curpsinfo->pr_psargs);}'
Note that this relies on the process arguments being cached via the struct
proc, which means that it will not work for argvs longer than
kern.ps_arg_cache_limit. However, the following rather non-portable
script can be used to extract any argv at exec time:
fbt::kern_execve:entry
{
printf("%s", memstr(args[1]->begin_argv, ' ',
args[1]->begin_envv - args[1]->begin_argv));
}
The debug.dtrace.memstr_max sysctl limits the maximum argument size to
memstr(). Thanks to Brendan Gregg for helpful comments on freebsd-dtrace.
Tested by: Fabian Keil (earlier version)
MFC after: 2 weeks
-rw-r--r-- | cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c | 4 | ||||
-rw-r--r-- | cddl/lib/libdtrace/psinfo.d | 3 | ||||
-rw-r--r-- | sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c | 45 | ||||
-rw-r--r-- | sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h | 3 | ||||
-rw-r--r-- | sys/cddl/dev/dtrace/dtrace_sysctl.c | 2 |
5 files changed, 55 insertions, 2 deletions
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c index 9c9b2a6..469924a 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c @@ -311,6 +311,10 @@ static const dt_ident_t _dtrace_globals[] = { &dt_idops_func, "void(@)" }, { "memref", DT_IDENT_FUNC, 0, DIF_SUBR_MEMREF, DT_ATTR_STABCMN, DT_VERS_1_1, &dt_idops_func, "uintptr_t *(void *, size_t)" }, +#if !defined(sun) +{ "memstr", DT_IDENT_FUNC, 0, DIF_SUBR_MEMSTR, DT_ATTR_STABCMN, DT_VERS_1_0, + &dt_idops_func, "string(void *, char, size_t)" }, +#endif { "min", DT_IDENT_AGGFUNC, 0, DTRACEAGG_MIN, DT_ATTR_STABCMN, DT_VERS_1_0, &dt_idops_func, "void(@)" }, { "mod", DT_IDENT_ACTFUNC, 0, DT_ACT_MOD, DT_ATTR_STABCMN, diff --git a/cddl/lib/libdtrace/psinfo.d b/cddl/lib/libdtrace/psinfo.d index 068e72e..c2219f7 100644 --- a/cddl/lib/libdtrace/psinfo.d +++ b/cddl/lib/libdtrace/psinfo.d @@ -57,7 +57,8 @@ translator psinfo_t < struct proc *T > { pr_gid = T->p_ucred->cr_rgid; pr_egid = T->p_ucred->cr_groups[0]; pr_addr = 0; - pr_psargs = stringof(T->p_args->ar_args); + pr_psargs = (T->p_args->ar_args == 0) ? "" : + memstr(T->p_args->ar_args, ' ', T->p_args->ar_length); pr_arglen = T->p_args->ar_length; pr_jailid = T->p_ucred->cr_prison->pr_id; }; diff --git a/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c b/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c index dae6dba..f35cf73 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c +++ b/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c @@ -185,6 +185,9 @@ hrtime_t dtrace_deadman_interval = NANOSEC; hrtime_t dtrace_deadman_timeout = (hrtime_t)10 * NANOSEC; hrtime_t dtrace_deadman_user = (hrtime_t)30 * NANOSEC; hrtime_t dtrace_unregister_defunct_reap = (hrtime_t)60 * NANOSEC; +#if !defined(sun) +int dtrace_memstr_max = 4096; +#endif /* * DTrace External Variables @@ -4920,6 +4923,45 @@ inetout: regs[rd] = (uintptr_t)end + 1; break; } +#if !defined(sun) + case DIF_SUBR_MEMSTR: { + char *str = (char *)mstate->dtms_scratch_ptr; + uintptr_t mem = tupregs[0].dttk_value; + char c = tupregs[1].dttk_value; + size_t size = tupregs[2].dttk_value; + uint8_t n; + int i; + + regs[rd] = 0; + + if (size == 0) + break; + + if (!dtrace_canload(mem, size - 1, mstate, vstate)) + break; + + if (!DTRACE_INSCRATCH(mstate, size)) { + DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH); + break; + } + + if (dtrace_memstr_max != 0 && size > dtrace_memstr_max) { + *flags |= CPU_DTRACE_ILLOP; + break; + } + + for (i = 0; i < size - 1; i++) { + n = dtrace_load8(mem++); + str[i] = (n == 0) ? c : n; + } + str[size - 1] = 0; + + regs[rd] = (uintptr_t)str; + mstate->dtms_scratch_ptr += size; + break; + } +#endif + case DIF_SUBR_TYPEREF: { uintptr_t size = 4 * sizeof(uintptr_t); uintptr_t *typeref = (uintptr_t *) P2ROUNDUP(mstate->dtms_scratch_ptr, sizeof(uintptr_t)); @@ -9102,6 +9144,9 @@ dtrace_difo_validate_helper(dtrace_difo_t *dp) subr == DIF_SUBR_NTOHL || subr == DIF_SUBR_NTOHLL || subr == DIF_SUBR_MEMREF || +#if !defined(sun) + subr == DIF_SUBR_MEMSTR || +#endif subr == DIF_SUBR_TYPEREF) break; diff --git a/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h b/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h index 8728e30..295457c 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h +++ b/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h @@ -311,8 +311,9 @@ typedef enum dtrace_probespec { #define DIF_SUBR_SX_SHARED_HELD 48 #define DIF_SUBR_SX_EXCLUSIVE_HELD 49 #define DIF_SUBR_SX_ISEXCLUSIVE 50 +#define DIF_SUBR_MEMSTR 51 -#define DIF_SUBR_MAX 50 /* max subroutine value */ +#define DIF_SUBR_MAX 51 /* max subroutine value */ typedef uint32_t dif_instr_t; diff --git a/sys/cddl/dev/dtrace/dtrace_sysctl.c b/sys/cddl/dev/dtrace/dtrace_sysctl.c index 00ed709..1b5b3ab 100644 --- a/sys/cddl/dev/dtrace/dtrace_sysctl.c +++ b/sys/cddl/dev/dtrace/dtrace_sysctl.c @@ -80,3 +80,5 @@ sysctl_dtrace_providers(SYSCTL_HANDLER_ARGS) SYSCTL_PROC(_debug_dtrace, OID_AUTO, providers, CTLTYPE_STRING | CTLFLAG_RD, 0, 0, sysctl_dtrace_providers, "A", ""); +SYSCTL_INT(_debug_dtrace, OID_AUTO, memstr_max, CTLFLAG_RW, &dtrace_memstr_max, + 0, "largest allowed argument to memstr(), 0 indicates no limit"); |