Complete support for dtrace's -x setenv option.

This allows one to override the environment for processes created with
dtrace -c. By default, the environment is inherited.

This support was originally merged from illumos in r249367 but was lost
when the commit was later reverted and then brought back piecemeal.

Reported by:	Samuel Lepetit <slepetit@apple.com>
MFC after:	2 weeks
This commit is contained in:
Mark Johnston 2017-12-03 16:57:28 +00:00
parent 5577b8a709
commit 04006780d9
19 changed files with 304 additions and 23 deletions

View File

@ -0,0 +1,25 @@
/*
* CDDL HEADER START
*
* This file and its contents are supplied under the terms of the
* Common Development and Distribution License ("CDDL"), version 1.0.
* You may only use this file in accordance with the terms of version
* 1.0 of the CDDL.
*
* A full copy of the text of the CDDL should have accompanied this
* source. A copy of the CDDL is also available via the Internet at
* http://www.illumos.org/license/CDDL.
*
* CDDL HEADER END
*/
/*
* Copyright (c) 2012 by Delphix. All rights reserved.
*/
#pragma D option setenv=balloon=something_bad_happens
BEGIN
{
exit(0);
}

View File

@ -0,0 +1,25 @@
/*
* CDDL HEADER START
*
* This file and its contents are supplied under the terms of the
* Common Development and Distribution License ("CDDL"), version 1.0.
* You may only use this file in accordance with the terms of version
* 1.0 of the CDDL.
*
* A full copy of the text of the CDDL should have accompanied this
* source. A copy of the CDDL is also available via the Internet at
* http://www.illumos.org/license/CDDL.
*
* CDDL HEADER END
*/
/*
* Copyright (c) 2012 by Delphix. All rights reserved.
*/
#pragma D option unsetenv=rectalexambot
BEGIN
{
exit(0);
}

View File

@ -0,0 +1,33 @@
#
# CDDL HEADER START
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source. A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#
# CDDL HEADER END
#
#
# Copyright (c) 2012 by Delphix. All rights reserved.
#
#
# Check that the LD_NOLAZYLOAD variable is set to 1 as expected.
#
if [ $# != 1 ]; then
echo expected one argument: '<'dtrace-path'>'
exit 2
fi
dtrace=$1
$dtrace -q -Z -n doogle -c 'printenv LD_NOLAZYLOAD'
exit $?

View File

@ -0,0 +1,33 @@
#
# CDDL HEADER START
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source. A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#
# CDDL HEADER END
#
#
# Copyright (c) 2012 by Delphix. All rights reserved.
#
#
# Reset an environment variable we already know to be set.
#
if [ $# != 1 ]; then
echo expected one argument: '<'dtrace-path'>'
exit 2
fi
dtrace=$1
$dtrace -q -Z -n doogle -xsetenv=LD_NOLAZYLOAD=0 -c 'printenv LD_NOLAZYLOAD'
exit $?

View File

@ -0,0 +1,2 @@
0

View File

@ -0,0 +1,33 @@
#
# CDDL HEADER START
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source. A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#
# CDDL HEADER END
#
#
# Copyright (c) 2012 by Delphix. All rights reserved.
#
#
# Test setting a variable that we isn't already set.
#
if [ $# != 1 ]; then
echo expected one argument: '<'dtrace-path'>'
exit 2
fi
dtrace=$1
$dtrace -q -Z -n doogle -xsetenv=CORPORATIONS=PEOPLE -c 'printenv CORPORATIONS'
exit $?

View File

@ -0,0 +1,2 @@
PEOPLE

View File

@ -0,0 +1,33 @@
#
# CDDL HEADER START
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source. A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#
# CDDL HEADER END
#
#
# Copyright (c) 2012 by Delphix. All rights reserved.
#
#
# Test unsetting a variable we know to be set.
#
if [ $# != 1 ]; then
echo expected one argument: '<'dtrace-path'>'
exit 2
fi
dtrace=$1
$dtrace -q -Z -n doogle -xunsetenv=LD_NOLAZYLOAD -c 'printenv LD_NOLAZYLOAD'
exit $?

View File

@ -0,0 +1,35 @@
#
# CDDL HEADER START
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source. A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#
# CDDL HEADER END
#
#
# Copyright (c) 2012 by Delphix. All rights reserved.
#
#
# Test invalid syntax to the unsetenv option.
#
if [ $# != 1 ]; then
echo expected one argument: '<'dtrace-path'>'
exit 2
fi
dtrace=$1
$dtrace -q -Z -n doogle -xunsetenv=ed=screven -c 'true' 2>&1
[[ $? -eq 1 ]] && exit 0
exit 1

View File

@ -0,0 +1 @@
dtrace: failed to set -x unsetenv: Invalid value for specified option

View File

@ -1182,7 +1182,7 @@ dt_vopen(int version, int flags, int *errp,
#endif #endif
dtp->dt_provbuckets = _dtrace_strbuckets; dtp->dt_provbuckets = _dtrace_strbuckets;
dtp->dt_provs = calloc(dtp->dt_provbuckets, sizeof (dt_provider_t *)); dtp->dt_provs = calloc(dtp->dt_provbuckets, sizeof (dt_provider_t *));
dt_proc_hash_create(dtp); dt_proc_init(dtp);
dtp->dt_vmax = DT_VERS_LATEST; dtp->dt_vmax = DT_VERS_LATEST;
dtp->dt_cpp_path = strdup(_dtrace_defcpp); dtp->dt_cpp_path = strdup(_dtrace_defcpp);
dtp->dt_cpp_argv = malloc(sizeof (char *)); dtp->dt_cpp_argv = malloc(sizeof (char *));
@ -1199,12 +1199,13 @@ dt_vopen(int version, int flags, int *errp,
(void) uname(&dtp->dt_uts); (void) uname(&dtp->dt_uts);
if (dtp->dt_mods == NULL || dtp->dt_provs == NULL || if (dtp->dt_mods == NULL || dtp->dt_provs == NULL ||
dtp->dt_procs == NULL || dtp->dt_ld_path == NULL || dtp->dt_procs == NULL || dtp->dt_proc_env == NULL ||
dtp->dt_ld_path == NULL || dtp->dt_cpp_path == NULL ||
#ifdef __FreeBSD__ #ifdef __FreeBSD__
dtp->dt_kmods == NULL || dtp->dt_kmods == NULL ||
dtp->dt_objcopy_path == NULL || dtp->dt_objcopy_path == NULL ||
#endif #endif
dtp->dt_cpp_path == NULL || dtp->dt_cpp_argv == NULL) dtp->dt_cpp_argv == NULL)
return (set_open_errno(dtp, errp, EDT_NOMEM)); return (set_open_errno(dtp, errp, EDT_NOMEM));
for (i = 0; i < DTRACEOPT_MAX; i++) for (i = 0; i < DTRACEOPT_MAX; i++)
@ -1631,7 +1632,7 @@ dtrace_close(dtrace_hdl_t *dtp)
int i; int i;
if (dtp->dt_procs != NULL) if (dtp->dt_procs != NULL)
dt_proc_hash_destroy(dtp); dt_proc_fini(dtp);
while ((pgp = dt_list_next(&dtp->dt_programs)) != NULL) while ((pgp = dt_list_next(&dtp->dt_programs)) != NULL)
dt_program_destroy(dtp, pgp); dt_program_destroy(dtp, pgp);

View File

@ -24,6 +24,10 @@
* Use is subject to license terms. * Use is subject to license terms.
*/ */
/*
* Copyright (c) 2012 by Delphix. All rights reserved.
*/
/* /*
* DTrace Process Control * DTrace Process Control
* *
@ -504,7 +508,7 @@ dt_proc_control(void *arg)
dt_proc_control_data_t *datap = arg; dt_proc_control_data_t *datap = arg;
dtrace_hdl_t *dtp = datap->dpcd_hdl; dtrace_hdl_t *dtp = datap->dpcd_hdl;
dt_proc_t *dpr = datap->dpcd_proc; dt_proc_t *dpr = datap->dpcd_proc;
dt_proc_hash_t *dph = dpr->dpr_hdl->dt_procs; dt_proc_hash_t *dph = dtp->dt_procs;
struct ps_prochandle *P = dpr->dpr_proc; struct ps_prochandle *P = dpr->dpr_proc;
int pid = dpr->dpr_pid; int pid = dpr->dpr_pid;
@ -965,14 +969,18 @@ dt_proc_create(dtrace_hdl_t *dtp, const char *file, char *const *argv,
(void) pthread_cond_init(&dpr->dpr_cv, NULL); (void) pthread_cond_init(&dpr->dpr_cv, NULL);
#ifdef illumos #ifdef illumos
if ((dpr->dpr_proc = Pcreate(file, argv, &err, NULL, 0)) == NULL) { dpr->dpr_proc = Pxcreate(file, argv, dtp->dt_proc_env, &err, NULL, 0);
#else if (dpr->dpr_proc == NULL) {
if ((err = proc_create(file, argv, NULL, pcf, child_arg,
&dpr->dpr_proc)) != 0) {
#endif
return (dt_proc_error(dtp, dpr, return (dt_proc_error(dtp, dpr,
"failed to execute %s: %s\n", file, Pcreate_error(err))); "failed to execute %s: %s\n", file, Pcreate_error(err)));
} }
#else
if ((err = proc_create(file, argv, dtp->dt_proc_env, pcf, child_arg,
&dpr->dpr_proc)) != 0) {
return (dt_proc_error(dtp, dpr,
"failed to execute %s: %s\n", file, Pcreate_error(err)));
}
#endif
dpr->dpr_hdl = dtp; dpr->dpr_hdl = dtp;
#ifdef illumos #ifdef illumos
@ -1141,30 +1149,74 @@ dt_proc_unlock(dtrace_hdl_t *dtp, struct ps_prochandle *P)
} }
void void
dt_proc_hash_create(dtrace_hdl_t *dtp) dt_proc_init(dtrace_hdl_t *dtp)
{ {
extern char **environ;
static char *envdef[] = {
"LD_NOLAZYLOAD=1", /* linker lazy loading hides funcs */
NULL
};
char **p;
int i;
if ((dtp->dt_procs = dt_zalloc(dtp, sizeof (dt_proc_hash_t) + if ((dtp->dt_procs = dt_zalloc(dtp, sizeof (dt_proc_hash_t) +
sizeof (dt_proc_t *) * _dtrace_pidbuckets - 1)) != NULL) { sizeof (dt_proc_t *) * _dtrace_pidbuckets - 1)) == NULL)
return;
(void) pthread_mutex_init(&dtp->dt_procs->dph_lock, NULL); (void) pthread_mutex_init(&dtp->dt_procs->dph_lock, NULL);
(void) pthread_cond_init(&dtp->dt_procs->dph_cv, NULL); (void) pthread_cond_init(&dtp->dt_procs->dph_cv, NULL);
dtp->dt_procs->dph_hashlen = _dtrace_pidbuckets; dtp->dt_procs->dph_hashlen = _dtrace_pidbuckets;
dtp->dt_procs->dph_lrulim = _dtrace_pidlrulim; dtp->dt_procs->dph_lrulim = _dtrace_pidlrulim;
/*
* Count how big our environment needs to be.
*/
for (i = 1, p = environ; *p != NULL; i++, p++)
continue;
for (p = envdef; *p != NULL; i++, p++)
continue;
if ((dtp->dt_proc_env = dt_zalloc(dtp, sizeof (char *) * i)) == NULL)
return;
for (i = 0, p = environ; *p != NULL; i++, p++) {
if ((dtp->dt_proc_env[i] = strdup(*p)) == NULL)
goto err;
} }
for (p = envdef; *p != NULL; i++, p++) {
if ((dtp->dt_proc_env[i] = strdup(*p)) == NULL)
goto err;
}
return;
err:
while (--i != 0) {
dt_free(dtp, dtp->dt_proc_env[i]);
}
dt_free(dtp, dtp->dt_proc_env);
dtp->dt_proc_env = NULL;
} }
void void
dt_proc_hash_destroy(dtrace_hdl_t *dtp) dt_proc_fini(dtrace_hdl_t *dtp)
{ {
dt_proc_hash_t *dph = dtp->dt_procs; dt_proc_hash_t *dph = dtp->dt_procs;
dt_proc_t *dpr; dt_proc_t *dpr;
char **p;
while ((dpr = dt_list_next(&dph->dph_lrulist)) != NULL) while ((dpr = dt_list_next(&dph->dph_lrulist)) != NULL)
dt_proc_destroy(dtp, dpr->dpr_proc); dt_proc_destroy(dtp, dpr->dpr_proc);
dtp->dt_procs = NULL; dtp->dt_procs = NULL;
dt_free(dtp, dph); dt_free(dtp, dph);
for (p = dtp->dt_proc_env; *p != NULL; p++)
dt_free(dtp, *p);
dt_free(dtp, dtp->dt_proc_env);
dtp->dt_proc_env = NULL;
} }
struct ps_prochandle * struct ps_prochandle *

View File

@ -24,11 +24,13 @@
* Use is subject to license terms. * Use is subject to license terms.
*/ */
/*
* Copyright (c) 2012 by Delphix. All rights reserved.
*/
#ifndef _DT_PROC_H #ifndef _DT_PROC_H
#define _DT_PROC_H #define _DT_PROC_H
#pragma ident "%Z%%M% %I% %E% SMI"
#include <libproc.h> #include <libproc.h>
#include <dtrace.h> #include <dtrace.h>
#include <pthread.h> #include <pthread.h>
@ -106,8 +108,8 @@ extern void dt_proc_lock(dtrace_hdl_t *, struct ps_prochandle *);
extern void dt_proc_unlock(dtrace_hdl_t *, struct ps_prochandle *); extern void dt_proc_unlock(dtrace_hdl_t *, struct ps_prochandle *);
extern dt_proc_t *dt_proc_lookup(dtrace_hdl_t *, struct ps_prochandle *, int); extern dt_proc_t *dt_proc_lookup(dtrace_hdl_t *, struct ps_prochandle *, int);
extern void dt_proc_hash_create(dtrace_hdl_t *); extern void dt_proc_init(dtrace_hdl_t *);
extern void dt_proc_hash_destroy(dtrace_hdl_t *); extern void dt_proc_fini(dtrace_hdl_t *);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -19,6 +19,7 @@ TESTS_SUBDIRS+= aggs \
drops \ drops \
dtraceUtil \ dtraceUtil \
end \ end \
env \
enum \ enum \
error \ error \
exit \ exit \

View File

@ -35,5 +35,4 @@ CFILES= \
tst.probestar.c \ tst.probestar.c \
.include "../../dtrace.test.mk" .include "../../dtrace.test.mk"

View File

@ -70,7 +70,6 @@ ${PACKAGE}FILES= \
TESTEXES= \ TESTEXES= \
tst.NoSpecBuffer.exe \ tst.NoSpecBuffer.exe \
CFILES= \ CFILES= \

View File

@ -101,6 +101,8 @@
.. ..
end end
.. ..
env
..
enum enum
.. ..
error error