--- old/usr/src/cmd/dtrace/test/tst/common/aggs/tst.subr.d	Fri Jun 22 23:48:16 2012
+++ new/usr/src/cmd/dtrace/test/tst/common/aggs/tst.subr.d	Fri Jun 22 23:48:16 2012
@@ -98,6 +98,7 @@
 STRFUNC(inet_ntop(AF_INET, (void *)alloca(sizeof (ipaddr_t))))
 STRFUNC(toupper("foo"))
 STRFUNC(tolower("BAR"))
+INTFUNC(getf(0))
 
 BEGIN
 /subr == DIF_SUBR_MAX + 1/
--- /dev/null	Fri Jun 22 23:48:16 2012
+++ new/usr/src/cmd/dtrace/test/tst/common/privs/tst.fds.ksh	Fri Jun 22 23:48:16 2012
@@ -0,0 +1,91 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2012, Joyent, Inc. All rights reserved.
+#
+
+tmpin=/tmp/tst.fds.$$.d
+tmpout1=/tmp/tst.fds.$$.out1
+tmpout2=/tmp/tst.fds.$$.out2
+
+cat > $tmpin <<EOF
+#define DUMPFIELD(fd, fmt, field) \
+	errmsg = "could not dump field"; \
+	printf("%d: field =fmt\n", fd, fds[fd].field);
+
+/*
+ * Note that we are explicitly not looking at fi_mount -- it (by design) does
+ * not work if not running with kernel permissions.
+ */
+#define DUMP(fd)	\
+	DUMPFIELD(fd, %s, fi_name); \
+	DUMPFIELD(fd, %s, fi_dirname); \
+	DUMPFIELD(fd, %s, fi_pathname); \
+	DUMPFIELD(fd, %d, fi_offset); \
+	DUMPFIELD(fd, %s, fi_fs); \
+	DUMPFIELD(fd, %o, fi_oflags);
+
+BEGIN
+{
+	DUMP(0);
+	DUMP(1);
+	DUMP(2);
+	DUMP(3);
+	DUMP(4);
+	exit(0);
+}
+
+ERROR
+{
+	printf("error: %s\n", errmsg);
+	exit(1);
+}
+EOF
+
+#
+# First, with all privs
+#
+/usr/sbin/dtrace -q -Cs /dev/stdin < $tmpin > $tmpout2
+mv $tmpout2 $tmpout1
+
+#
+# And now with only dtrace_proc and dtrace_user -- the output should be
+# identical.
+#
+ppriv -s A=basic,dtrace_proc,dtrace_user $$
+
+/usr/sbin/dtrace -q -Cs /dev/stdin < $tmpin > $tmpout2
+
+echo ">>> $tmpout1"
+cat $tmpout1
+
+echo ">>> $tmpout2"
+cat $tmpout2
+
+rval=0
+
+if ! cmp $tmpout1 $tmpout2 ; then
+	rval=1
+fi
+
+rm $tmpout1 $tmpout2 $tmpin
+exit $rval
--- /dev/null	Fri Jun 22 23:48:17 2012
+++ new/usr/src/cmd/dtrace/test/tst/common/privs/tst.getf.ksh	Fri Jun 22 23:48:17 2012
@@ -0,0 +1,98 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2012, Joyent, Inc. All rights reserved.
+#
+
+ppriv -s A=basic,dtrace_proc,dtrace_user $$
+
+/usr/sbin/dtrace -q -Cs /dev/stdin <<EOF
+
+#define CANREAD(field) \
+	BEGIN { this->fp = getf(0); errmsg = "can't read field"; \
+	    printf("field: "); trace(this->fp->field); printf("\n"); }
+
+#define CANTREAD(field) \
+	BEGIN { errmsg = ""; this->fp = getf(0); trace(this->fp->field); \
+	    printf("\nable to successfully read field!"); exit(1); }
+
+CANREAD(f_flag)
+CANREAD(f_flag2)
+CANREAD(f_vnode)
+CANREAD(f_offset)
+CANREAD(f_cred)
+CANREAD(f_audit_data)
+CANREAD(f_count)
+
+/*
+ * We can potentially read parts of our cred, but we can't dereference
+ * through cr_zone.
+ */
+CANTREAD(f_cred->cr_zone->zone_id)
+
+CANREAD(f_vnode->v_path)
+CANREAD(f_vnode->v_op)
+CANREAD(f_vnode->v_op->vnop_name)
+
+CANTREAD(f_vnode->v_flag)
+CANTREAD(f_vnode->v_count)
+CANTREAD(f_vnode->v_pages)
+CANTREAD(f_vnode->v_type)
+CANTREAD(f_vnode->v_vfsmountedhere)
+CANTREAD(f_vnode->v_op->vop_open)
+
+BEGIN
+{
+	errmsg = "";
+	this->fp = getf(0);
+	this->fp2 = getf(1);
+
+	trace(this->fp->f_vnode);
+	printf("\nable to successfully read this->fp!");
+	exit(1);
+}
+
+BEGIN
+{
+	errmsg = "";
+	this->fp = getf(0);
+}
+
+BEGIN
+{
+	trace(this->fp->f_vnode);
+	printf("\nable to successfully read this->fp from prior clause!");
+}
+
+BEGIN
+{
+	exit(0);
+}
+
+ERROR
+/errmsg != ""/
+{
+	printf("fatal error: %s", errmsg);
+	exit(1);
+}
+
+EOF
--- old/usr/src/lib/libdtrace/common/dt_open.c	Fri Jun 22 23:48:17 2012
+++ new/usr/src/lib/libdtrace/common/dt_open.c	Fri Jun 22 23:48:17 2012
@@ -21,7 +21,7 @@
 
 /*
  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2012, Joyent, Inc. All rights reserved.
  * Copyright (c) 2011 by Delphix. All rights reserved.
  */
 
@@ -110,8 +110,9 @@
 #define	DT_VERS_1_8	DT_VERSION_NUMBER(1, 8, 0)
 #define	DT_VERS_1_8_1	DT_VERSION_NUMBER(1, 8, 1)
 #define	DT_VERS_1_9	DT_VERSION_NUMBER(1, 9, 0)
-#define	DT_VERS_LATEST	DT_VERS_1_9
-#define	DT_VERS_STRING	"Sun D 1.9"
+#define	DT_VERS_1_10	DT_VERSION_NUMBER(1, 10, 0)
+#define	DT_VERS_LATEST	DT_VERS_1_10
+#define	DT_VERS_STRING	"Sun D 1.10"
 
 const dt_version_t _dtrace_versions[] = {
 	DT_VERS_1_0,	/* D API 1.0.0 (PSARC 2001/466) Solaris 10 FCS */
@@ -132,6 +133,7 @@
 	DT_VERS_1_8,	/* D API 1.8 */
 	DT_VERS_1_8_1,	/* D API 1.8.1 */
 	DT_VERS_1_9,	/* D API 1.9 */
+	DT_VERS_1_10,	/* D API 1.10 */
 	0
 };
 
@@ -245,6 +247,8 @@
 	&dt_idops_func, "uint64_t(uint64_t)" },
 { "htons", DT_IDENT_FUNC, 0, DIF_SUBR_HTONS, DT_ATTR_EVOLCMN, DT_VERS_1_3,
 	&dt_idops_func, "uint16_t(uint16_t)" },
+{ "getf", DT_IDENT_FUNC, 0, DIF_SUBR_GETF, DT_ATTR_STABCMN, DT_VERS_1_10,
+	&dt_idops_func, "file_t *(int)" },
 { "gid", DT_IDENT_SCALAR, 0, DIF_VAR_GID, DT_ATTR_STABCMN, DT_VERS_1_0,
 	&dt_idops_type, "gid_t" },
 { "id", DT_IDENT_SCALAR, 0, DIF_VAR_ID, DT_ATTR_STABCMN, DT_VERS_1_0,
--- old/usr/src/lib/libdtrace/common/io.d.in	Fri Jun 22 23:48:17 2012
+++ new/usr/src/lib/libdtrace/common/io.d.in	Fri Jun 22 23:48:17 2012
@@ -23,7 +23,9 @@
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
+/*
+ * Copyright (c) 2012, Joyent, Inc. All rights reserved.
+ */
 
 #pragma D depends_on module unix
 #pragma D depends_on provider io
@@ -197,9 +199,7 @@
 	fi_oflags = F == NULL ? 0 : F->f_flag + (int)@FOPEN@;
 };
 
-inline fileinfo_t fds[int fd] = xlate <fileinfo_t> (
-    fd >= 0 && fd < curthread->t_procp->p_user.u_finfo.fi_nfiles ?
-    curthread->t_procp->p_user.u_finfo.fi_list[fd].uf_file : NULL);
+inline fileinfo_t fds[int fd] = xlate <fileinfo_t> (getf(fd));
 
 #pragma D attributes Stable/Stable/Common fds
 #pragma D binding "1.1" fds
--- old/usr/src/uts/common/dtrace/dtrace.c	Fri Jun 22 23:48:18 2012
+++ new/usr/src/uts/common/dtrace/dtrace.c	Fri Jun 22 23:48:18 2012
@@ -170,6 +170,7 @@
 static dtrace_meta_t	*dtrace_meta_pid;	/* user-land meta provider */
 static int		dtrace_opens;		/* number of opens */
 static int		dtrace_helpers;		/* number of helpers */
+static int		dtrace_getf;		/* number of unpriv getf()s */
 static void		*dtrace_softstate;	/* softstate pointer */
 static dtrace_hash_t	*dtrace_bymod;		/* probes hashed by module */
 static dtrace_hash_t	*dtrace_byfunc;		/* probes hashed by function */
@@ -475,6 +476,7 @@
 static int dtrace_ecb_create_enable(dtrace_probe_t *, void *);
 static void dtrace_helper_provider_destroy(dtrace_helper_provider_t *);
 static int dtrace_priv_proc(dtrace_state_t *, dtrace_mstate_t *);
+static void dtrace_getf_barrier(void);
 
 /*
  * DTrace Probe Context Functions
@@ -686,6 +688,7 @@
     dtrace_vstate_t *vstate)
 {
 	volatile uintptr_t *illval = &cpu_core[CPU->cpu_id].cpuc_dtrace_illval;
+	file_t *fp;
 
 	/*
 	 * If we hold the privilege to read from kernel memory, then
@@ -751,6 +754,51 @@
 		}
 	}
 
+	if ((fp = mstate->dtms_getf) != NULL) {
+		uintptr_t psz = sizeof (void *);
+		vnode_t *vp;
+		vnodeops_t *op;
+
+		/*
+		 * When getf() returns a file_t, the enabling is implicitly
+		 * granted the (transient) right to read the returned file_t
+		 * as well as the v_path and v_op->vnop_name of the underlying
+		 * vnode.  These accesses are allowed after a successful
+		 * getf() because the members that they refer to cannot change
+		 * once set -- and the barrier logic in the kernel's closef()
+		 * path assures that the file_t and its referenced vode_t
+		 * cannot themselves be stale (that is, it impossible for
+		 * either dtms_getf itself or its f_vnode member to reference
+		 * freed memory).
+		 */
+		if (DTRACE_INRANGE(addr, sz, fp, sizeof (file_t)))
+			return (1);
+
+		if ((vp = fp->f_vnode) != NULL) {
+			if (DTRACE_INRANGE(addr, sz, &vp->v_path, psz))
+				return (1);
+
+			if (vp->v_path != NULL && DTRACE_INRANGE(addr, sz,
+			    vp->v_path, strlen(vp->v_path) + 1)) {
+				return (1);
+			}
+
+			if (DTRACE_INRANGE(addr, sz, &vp->v_op, psz))
+				return (1);
+
+			if ((op = vp->v_op) != NULL &&
+			    DTRACE_INRANGE(addr, sz, &op->vnop_name, psz)) {
+				return (1);
+			}
+
+			if (op != NULL && op->vnop_name != NULL &&
+			    DTRACE_INRANGE(addr, sz, op->vnop_name,
+			    strlen(op->vnop_name) + 1)) {
+				return (1);
+			}
+		}
+	}
+
 	DTRACE_CPUFLAG_SET(CPU_DTRACE_KPRIV);
 	*illval = addr;
 	return (0);
@@ -1129,8 +1177,7 @@
 	 */
 	ASSERT(s_cr != NULL);
 
-	if ((cr = CRED()) != NULL &&
-	    s_cr->cr_zone == cr->cr_zone)
+	if ((cr = CRED()) != NULL && s_cr->cr_zone == cr->cr_zone)
 		return (1);
 
 	return (0);
@@ -4465,11 +4512,35 @@
 		break;
 	}
 
+	case DIF_SUBR_GETF: {
+		uintptr_t fd = tupregs[0].dttk_value;
+		uf_info_t *finfo = &curthread->t_procp->p_user.u_finfo;
+		file_t *fp;
+
+		if (!dtrace_priv_proc(state, mstate)) {
+			regs[rd] = NULL;
+			break;
+		}
+
+		/*
+		 * This is safe because fi_nfiles only increases, and the
+		 * fi_list array is not freed when the array size doubles.
+		 * (See the comment in flist_grow() for details on the
+		 * management of the u_finfo structure.)
+		 */
+		fp = fd < finfo->fi_nfiles ? finfo->fi_list[fd].uf_file : NULL;
+
+		mstate->dtms_getf = fp;
+		regs[rd] = (uintptr_t)fp;
+		break;
+	}
+
 	case DIF_SUBR_CLEANPATH: {
 		char *dest = (char *)mstate->dtms_scratch_ptr, c;
 		uint64_t size = state->dts_options[DTRACEOPT_STRSIZE];
 		uintptr_t src = tupregs[0].dttk_value;
 		int i = 0, j = 0;
+		zone_t *z;
 
 		if (!dtrace_strcanload(src, size, mstate, vstate)) {
 			regs[rd] = NULL;
@@ -4568,6 +4639,23 @@
 		} while (c != '\0');
 
 		dest[j] = '\0';
+
+		if (mstate->dtms_getf != NULL &&
+		    !(mstate->dtms_access & DTRACE_ACCESS_KERNEL) &&
+		    (z = state->dts_cred.dcr_cred->cr_zone) != kcred->cr_zone) {
+			/*
+			 * If we've done a getf() as a part of this ECB and we
+			 * don't have kernel access (and we're not in the global
+			 * zone), check if the path we cleaned up begins with
+			 * the zone's root path, and trim it off if so.  Note
+			 * that this is an output cleanliness issue, not a
+			 * security issue: knowing one's zone root path does
+			 * not enable privilege escalation.
+			 */
+			if (strstr(dest, z->zone_rootpath) == dest)
+				dest += strlen(z->zone_rootpath) - 1;
+		}
+
 		regs[rd] = (uintptr_t)dest;
 		mstate->dtms_scratch_ptr += size;
 		break;
@@ -5932,6 +6020,8 @@
 
 		mstate.dtms_present = DTRACE_MSTATE_ARGS | DTRACE_MSTATE_PROBE;
 		mstate.dtms_access = DTRACE_ACCESS_ARGS | DTRACE_ACCESS_PROC;
+		mstate.dtms_getf = NULL;
+
 		*flags &= ~CPU_DTRACE_ERROR;
 
 		if (prov == dtrace_provider) {
@@ -8410,6 +8500,20 @@
 			    subr == DIF_SUBR_COPYOUTSTR) {
 				dp->dtdo_destructive = 1;
 			}
+
+			if (subr == DIF_SUBR_GETF) {
+				/*
+				 * If we have a getf() we need to record that
+				 * in our state.  Note that our state can be
+				 * NULL if this is a helper -- but in that
+				 * case, the call to getf() is itself illegal,
+				 * and will be caught (slightly later) when
+				 * the helper is validated.
+				 */
+				if (vstate->dtvs_state != NULL)
+					vstate->dtvs_state->dts_getf++;
+			}
+
 			break;
 		case DIF_OP_PUSHTR:
 			if (type != DIF_TYPE_STRING && type != DIF_TYPE_CTF)
@@ -13084,6 +13188,22 @@
 
 	state->dts_activity = DTRACE_ACTIVITY_WARMUP;
 
+	if (state->dts_getf != 0 &&
+	    !(state->dts_cred.dcr_visible & DTRACE_CRV_KERNEL)) {
+		/*
+		 * We don't have kernel privs but we have at least one call
+		 * to getf(); we need to bump our zone's count, and (if
+		 * this is the first enabling to have an unprivileged call
+		 * to getf()) we need to hook into closef().
+		 */
+		state->dts_cred.dcr_cred->cr_zone->zone_dtrace_getf++;
+
+		if (dtrace_getf++ == 0) {
+			ASSERT(dtrace_closef == NULL);
+			dtrace_closef = dtrace_getf_barrier;
+		}
+	}
+
 	/*
 	 * Now it's time to actually fire the BEGIN probe.  We need to disable
 	 * interrupts here both to record the CPU on which we fired the BEGIN
@@ -13200,6 +13320,24 @@
 	state->dts_activity = DTRACE_ACTIVITY_STOPPED;
 	dtrace_sync();
 
+	if (state->dts_getf != 0 &&
+	    !(state->dts_cred.dcr_visible & DTRACE_CRV_KERNEL)) {
+		/*
+		 * We don't have kernel privs but we have at least one call
+		 * to getf(); we need to lower our zone's count, and (if
+		 * this is the last enabling to have an unprivileged call
+		 * to getf()) we need to clear the closef() hook.
+		 */
+		ASSERT(state->dts_cred.dcr_cred->cr_zone->zone_dtrace_getf > 0);
+		ASSERT(dtrace_closef == dtrace_getf_barrier);
+		ASSERT(dtrace_getf > 0);
+
+		state->dts_cred.dcr_cred->cr_zone->zone_dtrace_getf--;
+
+		if (--dtrace_getf == 0)
+			dtrace_closef = NULL;
+	}
+
 	return (0);
 }
 
@@ -14760,6 +14898,23 @@
 	dtrace_toxranges++;
 }
 
+static void
+dtrace_getf_barrier()
+{
+	/*
+	 * When we have unprivileged (that is, non-DTRACE_CRV_KERNEL) enablings
+	 * that contain calls to getf(), this routine will be called on every
+	 * closef() before either the underlying vnode is released or the
+	 * file_t itself is freed.  By the time we are here, it is essential
+	 * that the file_t can no longer be accessed from a call to getf()
+	 * in probe context -- that assures that a dtrace_sync() can be used
+	 * to clear out any enablings referring to the old structures.
+	 */
+	if (curthread->t_procp->p_zone->zone_dtrace_getf != 0 ||
+	    kcred->cr_zone->zone_dtrace_getf != 0)
+		dtrace_sync();
+}
+
 /*
  * DTrace Driver Cookbook Functions
  */
@@ -15914,6 +16069,9 @@
 	dtrace_modload = NULL;
 	dtrace_modunload = NULL;
 
+	ASSERT(dtrace_getf == 0);
+	ASSERT(dtrace_closef == NULL);
+
 	mutex_exit(&cpu_lock);
 
 	if (dtrace_helptrace_enabled) {
--- old/usr/src/uts/common/os/dtrace_subr.c	Fri Jun 22 23:48:25 2012
+++ new/usr/src/uts/common/os/dtrace_subr.c	Fri Jun 22 23:48:25 2012
@@ -44,6 +44,7 @@
 void (*dtrace_cpustart_init)(void);
 void (*dtrace_cpustart_fini)(void);
 void (*dtrace_cpc_fire)(uint64_t);
+void (*dtrace_closef)(void);
 
 void (*dtrace_debugger_init)(void);
 void (*dtrace_debugger_fini)(void);
--- old/usr/src/uts/common/os/fio.c	Fri Jun 22 23:48:25 2012
+++ new/usr/src/uts/common/os/fio.c	Fri Jun 22 23:48:25 2012
@@ -21,6 +21,7 @@
 
 /*
  * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, Joyent Inc. All rights reserved.
  */
 
 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
@@ -54,6 +55,7 @@
 #include <sys/poll.h>
 #include <sys/rctl.h>
 #include <sys/port_impl.h>
+#include <sys/dtrace.h>
 
 #include <c2/audit.h>
 #include <sys/nbmlock.h>
@@ -952,6 +954,18 @@
 	ASSERT(fp->f_count == 0);
 	mutex_exit(&fp->f_tlock);
 
+	/*
+	 * If DTrace has getf() subroutines active, it will set dtrace_closef
+	 * to point to code that implements a barrier with respect to probe
+	 * context.  This must be called before the file_t is freed (and the
+	 * vnode that it refers to is released) -- but it must be after the
+	 * file_t has been removed from the uf_entry_t.  That is, there must
+	 * be no way for a racing getf() in probe context to yield the fp that
+	 * we're operating upon.
+	 */
+	if (dtrace_closef != NULL)
+		(*dtrace_closef)();
+
 	VN_RELE(vp);
 	/*
 	 * deallocate resources to audit_data
--- old/usr/src/uts/common/sys/dtrace.h	Fri Jun 22 23:48:26 2012
+++ new/usr/src/uts/common/sys/dtrace.h	Fri Jun 22 23:48:26 2012
@@ -287,8 +287,9 @@
 #define	DIF_SUBR_INET_NTOA6		43
 #define	DIF_SUBR_TOUPPER		44
 #define	DIF_SUBR_TOLOWER		45
+#define	DIF_SUBR_GETF			46
 
-#define	DIF_SUBR_MAX			45	/* max subroutine value */
+#define	DIF_SUBR_MAX			46	/* max subroutine value */
 
 typedef uint32_t dif_instr_t;
 
@@ -2243,6 +2244,7 @@
 extern void (*dtrace_helpers_fork)(proc_t *parent, proc_t *child);
 extern void (*dtrace_cpustart_init)();
 extern void (*dtrace_cpustart_fini)();
+extern void (*dtrace_closef)();
 
 extern void (*dtrace_debugger_init)();
 extern void (*dtrace_debugger_fini)();
--- old/usr/src/uts/common/sys/dtrace_impl.h	Fri Jun 22 23:48:26 2012
+++ new/usr/src/uts/common/sys/dtrace_impl.h	Fri Jun 22 23:48:26 2012
@@ -917,6 +917,7 @@
 	uintptr_t dtms_strtok;			/* saved strtok() pointer */
 	uint32_t dtms_access;			/* memory access rights */
 	dtrace_difo_t *dtms_difo;		/* current dif object */
+	file_t *dtms_getf;			/* cached rval of getf() */
 } dtrace_mstate_t;
 
 #define	DTRACE_COND_OWNER	0x1
@@ -1137,6 +1138,7 @@
 	dtrace_optval_t dts_options[DTRACEOPT_MAX]; /* options */
 	dtrace_cred_t dts_cred;			/* credentials */
 	size_t dts_nretained;			/* number of retained enabs */
+	int dts_getf;				/* number of getf() calls */
 };
 
 struct dtrace_provider {
--- old/usr/src/uts/common/sys/zone.h	Fri Jun 22 23:48:27 2012
+++ new/usr/src/uts/common/sys/zone.h	Fri Jun 22 23:48:27 2012
@@ -534,6 +534,11 @@
 	rctl_qty_t	zone_nprocs_ctl;	/* current limit protected by */
 						/* zone_rctls->rcs_lock */
 	kstat_t		*zone_nprocs_kstat;
+
+	/*
+	 * DTrace-private per-zone state
+	 */
+	int		zone_dtrace_getf;	/* # of unprivileged getf()s */
 } zone_t;
 
 /*
