Author: markj
Date: Tue Jun  3 00:55:15 2014
New Revision: 266986
URL: http://svnweb.freebsd.org/changeset/base/266986

Log:
  2915 DTrace in a zone should see "cpu", "curpsinfo", et al
  2916 DTrace in a zone should be able to access fds[]
  2917 DTrace in a zone should have limited provider access
  
  illumos/illumos-gate@b0f673c4626e4cb1db7785287eaeed2731dfefe8

Modified:
  vendor-sys/illumos/dist/uts/common/dtrace/dtrace.c
  vendor-sys/illumos/dist/uts/common/dtrace/sdt_subr.c
  vendor-sys/illumos/dist/uts/common/sys/dtrace.h
  vendor-sys/illumos/dist/uts/common/sys/dtrace_impl.h

Changes in other areas also in this revision:
Added:
  vendor/illumos/dist/cmd/dtrace/test/tst/common/privs/tst.fds.ksh
  vendor/illumos/dist/cmd/dtrace/test/tst/common/privs/tst.getf.ksh
  vendor/illumos/dist/cmd/dtrace/test/tst/common/privs/tst.procpriv.ksh
  vendor/illumos/dist/cmd/dtrace/test/tst/common/privs/tst.providers.ksh
Modified:
  vendor/illumos/dist/cmd/dtrace/test/tst/common/aggs/tst.subr.d
  vendor/illumos/dist/lib/libdtrace/common/dt_open.c

Modified: vendor-sys/illumos/dist/uts/common/dtrace/dtrace.c
==============================================================================
--- vendor-sys/illumos/dist/uts/common/dtrace/dtrace.c  Mon Jun  2 23:50:19 
2014        (r266985)
+++ vendor-sys/illumos/dist/uts/common/dtrace/dtrace.c  Tue Jun  3 00:55:15 
2014        (r266986)
@@ -171,6 +171,7 @@ static dtrace_provider_t *dtrace_provide
 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 */
@@ -373,8 +374,8 @@ static kmutex_t dtrace_errlock;
  * disallow all negative sizes.  Ranges of size 0 are allowed.
  */
 #define        DTRACE_INRANGE(testaddr, testsz, baseaddr, basesz) \
-       ((testaddr) - (baseaddr) < (basesz) && \
-       (testaddr) + (testsz) - (baseaddr) <= (basesz) && \
+       ((testaddr) - (uintptr_t)(baseaddr) < (basesz) && \
+       (testaddr) + (testsz) - (uintptr_t)(baseaddr) <= (basesz) && \
        (testaddr) + (testsz) >= (testaddr))
 
 /*
@@ -475,6 +476,8 @@ static int dtrace_state_option(dtrace_st
     dtrace_optval_t);
 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
@@ -619,7 +622,7 @@ dtrace_canstore(uint64_t addr, size_t sz
         * up both thread-local variables and any global dynamically-allocated
         * variables.
         */
-       if (DTRACE_INRANGE(addr, sz, (uintptr_t)vstate->dtvs_dynvars.dtds_base,
+       if (DTRACE_INRANGE(addr, sz, vstate->dtvs_dynvars.dtds_base,
            vstate->dtvs_dynvars.dtds_size)) {
                dtrace_dstate_t *dstate = &vstate->dtvs_dynvars;
                uintptr_t base = (uintptr_t)dstate->dtds_base +
@@ -686,6 +689,7 @@ dtrace_canload(uint64_t addr, size_t sz,
     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
@@ -703,10 +707,99 @@ dtrace_canload(uint64_t addr, size_t sz,
        /*
         * We're allowed to read from our own string table.
         */
-       if (DTRACE_INRANGE(addr, sz, (uintptr_t)mstate->dtms_difo->dtdo_strtab,
+       if (DTRACE_INRANGE(addr, sz, mstate->dtms_difo->dtdo_strtab,
            mstate->dtms_difo->dtdo_strlen))
                return (1);
 
+       if (vstate->dtvs_state != NULL &&
+           dtrace_priv_proc(vstate->dtvs_state, mstate)) {
+               proc_t *p;
+
+               /*
+                * When we have privileges to the current process, there are
+                * several context-related kernel structures that are safe to
+                * read, even absent the privilege to read from kernel memory.
+                * These reads are safe because these structures contain only
+                * state that (1) we're permitted to read, (2) is harmless or
+                * (3) contains pointers to additional kernel state that we're
+                * not permitted to read (and as such, do not present an
+                * opportunity for privilege escalation).  Finally (and
+                * critically), because of the nature of their relation with
+                * the current thread context, the memory associated with these
+                * structures cannot change over the duration of probe context,
+                * and it is therefore impossible for this memory to be
+                * deallocated and reallocated as something else while it's
+                * being operated upon.
+                */
+               if (DTRACE_INRANGE(addr, sz, curthread, sizeof (kthread_t)))
+                       return (1);
+
+               if ((p = curthread->t_procp) != NULL && DTRACE_INRANGE(addr,
+                   sz, curthread->t_procp, sizeof (proc_t))) {
+                       return (1);
+               }
+
+               if (curthread->t_cred != NULL && DTRACE_INRANGE(addr, sz,
+                   curthread->t_cred, sizeof (cred_t))) {
+                       return (1);
+               }
+
+               if (p != NULL && p->p_pidp != NULL && DTRACE_INRANGE(addr, sz,
+                   &(p->p_pidp->pid_id), sizeof (pid_t))) {
+                       return (1);
+               }
+
+               if (curthread->t_cpu != NULL && DTRACE_INRANGE(addr, sz,
+                   curthread->t_cpu, offsetof(cpu_t, cpu_pause_thread))) {
+                       return (1);
+               }
+       }
+
+       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);
@@ -1085,8 +1178,7 @@ dtrace_priv_proc_common_zone(dtrace_stat
         */
        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);
@@ -1209,19 +1301,17 @@ dtrace_priv_probe(dtrace_state_t *state,
                mode = pops->dtps_mode(prov->dtpv_arg,
                    probe->dtpr_id, probe->dtpr_arg);
 
-               ASSERT((mode & DTRACE_MODE_USER) ||
-                   (mode & DTRACE_MODE_KERNEL));
-               ASSERT((mode & DTRACE_MODE_NOPRIV_RESTRICT) ||
-                   (mode & DTRACE_MODE_NOPRIV_DROP));
+               ASSERT(mode & (DTRACE_MODE_USER | DTRACE_MODE_KERNEL));
+               ASSERT(mode & (DTRACE_MODE_NOPRIV_RESTRICT |
+                   DTRACE_MODE_NOPRIV_DROP));
        }
 
        /*
         * If the dte_cond bits indicate that this consumer is only allowed to
-        * see user-mode firings of this probe, call the provider's dtps_mode()
-        * entry point to check that the probe was fired while in a user
-        * context.  If that's not the case, use the policy specified by the
-        * provider to determine if we drop the probe or merely restrict
-        * operation.
+        * see user-mode firings of this probe, check that the probe was fired
+        * while in a user context.  If that's not the case, use the policy
+        * specified by the provider to determine if we drop the probe or
+        * merely restrict operation.
         */
        if (ecb->dte_cond & DTRACE_COND_USERMODE) {
                ASSERT(mode != DTRACE_MODE_NOPRIV_DROP);
@@ -1288,6 +1378,15 @@ dtrace_priv_probe(dtrace_state_t *state,
                }
        }
 
+       /*
+        * By merits of being in this code path at all, we have limited
+        * privileges.  If the provider has indicated that limited privileges
+        * are to denote restricted operation, strip off the ability to access
+        * arguments.
+        */
+       if (mode & DTRACE_MODE_LIMITEDPRIV_RESTRICT)
+               mstate->dtms_access &= ~DTRACE_ACCESS_ARGS;
+
        return (1);
 }
 
@@ -2924,7 +3023,7 @@ dtrace_dif_variable(dtrace_mstate_t *mst
        }
 
        case DIF_VAR_CURTHREAD:
-               if (!dtrace_priv_kernel(state))
+               if (!dtrace_priv_proc(state, mstate))
                        return (0);
                return ((uint64_t)(uintptr_t)curthread);
 
@@ -4452,11 +4551,35 @@ case DIF_SUBR_GETMAJOR:
                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;
@@ -4555,6 +4678,23 @@ next:
                } 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;
@@ -4939,71 +5079,50 @@ dtrace_dif_emulate(dtrace_difo_t *difo, 
                                pc = DIF_INSTR_LABEL(instr);
                        break;
                case DIF_OP_RLDSB:
-                       if (!dtrace_canstore(regs[r1], 1, mstate, vstate)) {
-                               *flags |= CPU_DTRACE_KPRIV;
-                               *illval = regs[r1];
+                       if (!dtrace_canload(regs[r1], 1, mstate, vstate))
                                break;
-                       }
                        /*FALLTHROUGH*/
                case DIF_OP_LDSB:
                        regs[rd] = (int8_t)dtrace_load8(regs[r1]);
                        break;
                case DIF_OP_RLDSH:
-                       if (!dtrace_canstore(regs[r1], 2, mstate, vstate)) {
-                               *flags |= CPU_DTRACE_KPRIV;
-                               *illval = regs[r1];
+                       if (!dtrace_canload(regs[r1], 2, mstate, vstate))
                                break;
-                       }
                        /*FALLTHROUGH*/
                case DIF_OP_LDSH:
                        regs[rd] = (int16_t)dtrace_load16(regs[r1]);
                        break;
                case DIF_OP_RLDSW:
-                       if (!dtrace_canstore(regs[r1], 4, mstate, vstate)) {
-                               *flags |= CPU_DTRACE_KPRIV;
-                               *illval = regs[r1];
+                       if (!dtrace_canload(regs[r1], 4, mstate, vstate))
                                break;
-                       }
                        /*FALLTHROUGH*/
                case DIF_OP_LDSW:
                        regs[rd] = (int32_t)dtrace_load32(regs[r1]);
                        break;
                case DIF_OP_RLDUB:
-                       if (!dtrace_canstore(regs[r1], 1, mstate, vstate)) {
-                               *flags |= CPU_DTRACE_KPRIV;
-                               *illval = regs[r1];
+                       if (!dtrace_canload(regs[r1], 1, mstate, vstate))
                                break;
-                       }
                        /*FALLTHROUGH*/
                case DIF_OP_LDUB:
                        regs[rd] = dtrace_load8(regs[r1]);
                        break;
                case DIF_OP_RLDUH:
-                       if (!dtrace_canstore(regs[r1], 2, mstate, vstate)) {
-                               *flags |= CPU_DTRACE_KPRIV;
-                               *illval = regs[r1];
+                       if (!dtrace_canload(regs[r1], 2, mstate, vstate))
                                break;
-                       }
                        /*FALLTHROUGH*/
                case DIF_OP_LDUH:
                        regs[rd] = dtrace_load16(regs[r1]);
                        break;
                case DIF_OP_RLDUW:
-                       if (!dtrace_canstore(regs[r1], 4, mstate, vstate)) {
-                               *flags |= CPU_DTRACE_KPRIV;
-                               *illval = regs[r1];
+                       if (!dtrace_canload(regs[r1], 4, mstate, vstate))
                                break;
-                       }
                        /*FALLTHROUGH*/
                case DIF_OP_LDUW:
                        regs[rd] = dtrace_load32(regs[r1]);
                        break;
                case DIF_OP_RLDX:
-                       if (!dtrace_canstore(regs[r1], 8, mstate, vstate)) {
-                               *flags |= CPU_DTRACE_KPRIV;
-                               *illval = regs[r1];
+                       if (!dtrace_canload(regs[r1], 8, mstate, vstate))
                                break;
-                       }
                        /*FALLTHROUGH*/
                case DIF_OP_LDX:
                        regs[rd] = dtrace_load64(regs[r1]);
@@ -5942,6 +6061,8 @@ dtrace_probe(dtrace_id_t id, uintptr_t a
 
                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) {
@@ -8448,6 +8569,20 @@ dtrace_difo_validate(dtrace_difo_t *dp, 
                            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)
@@ -13090,6 +13225,22 @@ dtrace_state_go(dtrace_state_t *state, p
 
        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
@@ -13206,6 +13357,24 @@ dtrace_state_stop(dtrace_state_t *state,
        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);
 }
 
@@ -14766,6 +14935,23 @@ dtrace_toxrange_add(uintptr_t base, uint
        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
  */
@@ -15922,6 +16108,9 @@ dtrace_detach(dev_info_t *dip, ddi_detac
        dtrace_modload = NULL;
        dtrace_modunload = NULL;
 
+       ASSERT(dtrace_getf == 0);
+       ASSERT(dtrace_closef == NULL);
+
        mutex_exit(&cpu_lock);
 
        if (dtrace_helptrace_enabled) {

Modified: vendor-sys/illumos/dist/uts/common/dtrace/sdt_subr.c
==============================================================================
--- vendor-sys/illumos/dist/uts/common/dtrace/sdt_subr.c        Mon Jun  2 
23:50:19 2014        (r266985)
+++ vendor-sys/illumos/dist/uts/common/dtrace/sdt_subr.c        Tue Jun  3 
00:55:15 2014        (r266986)
@@ -20,6 +20,7 @@
  */
 /*
  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, Joyent, Inc. All rights reserved.
  */
 
 #include <sys/sdt_impl.h>
@@ -97,26 +98,26 @@ static dtrace_pattr_t iscsi_attr = {
 };
 
 sdt_provider_t sdt_providers[] = {
-       { "vtrace", "__vtrace_", &vtrace_attr, 0 },
-       { "sysinfo", "__cpu_sysinfo_", &info_attr, 0 },
-       { "vminfo", "__cpu_vminfo_", &info_attr, 0 },
-       { "fpuinfo", "__fpuinfo_", &fpu_attr, 0 },
-       { "sched", "__sched_", &stab_attr, 0 },
-       { "proc", "__proc_", &stab_attr, 0 },
-       { "io", "__io_", &stab_attr, 0 },
-       { "ip", "__ip_", &stab_attr, 0 },
-       { "tcp", "__tcp_", &stab_attr, 0 },
-       { "udp", "__udp_", &stab_attr, 0 },
-       { "mib", "__mib_", &stab_attr, 0 },
-       { "fsinfo", "__fsinfo_", &fsinfo_attr, 0 },
-       { "iscsi", "__iscsi_", &iscsi_attr, 0 },
-       { "nfsv3", "__nfsv3_", &stab_attr, 0 },
-       { "nfsv4", "__nfsv4_", &stab_attr, 0 },
-       { "xpv", "__xpv_", &xpv_attr, 0 },
-       { "fc", "__fc_", &fc_attr, 0 },
-       { "srp", "__srp_", &fc_attr, 0 },
-       { "sysevent", "__sysevent_", &stab_attr, 0 },
-       { "sdt", NULL, &sdt_attr, 0 },
+       { "vtrace", "__vtrace_", &vtrace_attr },
+       { "sysinfo", "__cpu_sysinfo_", &info_attr, DTRACE_PRIV_USER },
+       { "vminfo", "__cpu_vminfo_", &info_attr, DTRACE_PRIV_USER },
+       { "fpuinfo", "__fpuinfo_", &fpu_attr },
+       { "sched", "__sched_", &stab_attr, DTRACE_PRIV_USER },
+       { "proc", "__proc_", &stab_attr, DTRACE_PRIV_USER },
+       { "io", "__io_", &stab_attr },
+       { "ip", "__ip_", &stab_attr },
+       { "tcp", "__tcp_", &stab_attr },
+       { "udp", "__udp_", &stab_attr },
+       { "mib", "__mib_", &stab_attr },
+       { "fsinfo", "__fsinfo_", &fsinfo_attr },
+       { "iscsi", "__iscsi_", &iscsi_attr },
+       { "nfsv3", "__nfsv3_", &stab_attr },
+       { "nfsv4", "__nfsv4_", &stab_attr },
+       { "xpv", "__xpv_", &xpv_attr },
+       { "fc", "__fc_", &fc_attr },
+       { "srp", "__srp_", &fc_attr },
+       { "sysevent", "__sysevent_", &stab_attr },
+       { "sdt", NULL, &sdt_attr },
        { NULL }
 };
 
@@ -1155,6 +1156,20 @@ sdt_argdesc_t sdt_args[] = {
 };
 
 /*ARGSUSED*/
+int
+sdt_mode(void *arg, dtrace_id_t id, void *parg)
+{
+       /*
+        * We tell DTrace that we're in kernel mode, that the firing needs to
+        * be dropped for anything that doesn't have necessary privileges, and
+        * that it needs to be restricted for anything that has restricted
+        * (i.e., not all-zone) privileges.
+        */
+       return (DTRACE_MODE_KERNEL | DTRACE_MODE_NOPRIV_DROP |
+           DTRACE_MODE_LIMITEDPRIV_RESTRICT);
+}
+
+/*ARGSUSED*/
 void
 sdt_getargdesc(void *arg, dtrace_id_t id, void *parg, dtrace_argdesc_t *desc)
 {

Modified: vendor-sys/illumos/dist/uts/common/sys/dtrace.h
==============================================================================
--- vendor-sys/illumos/dist/uts/common/sys/dtrace.h     Mon Jun  2 23:50:19 
2014        (r266985)
+++ vendor-sys/illumos/dist/uts/common/sys/dtrace.h     Tue Jun  3 00:55:15 
2014        (r266986)
@@ -25,7 +25,7 @@
  */
 
 /*
- * Copyright (c) 2011, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2012, Joyent, Inc. All rights reserved.
  * Copyright (c) 2012 by Delphix. All rights reserved.
  */
 
@@ -288,8 +288,9 @@ typedef enum dtrace_probespec {
 #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;
 
@@ -1649,13 +1650,20 @@ typedef struct dof_helper {
  *
  *   A bitwise OR that encapsulates both the mode (either DTRACE_MODE_KERNEL
  *   or DTRACE_MODE_USER) and the policy when the privilege of the enabling
- *   is insufficient for that mode (either DTRACE_MODE_NOPRIV_DROP or
- *   DTRACE_MODE_NOPRIV_RESTRICT).  If the policy is DTRACE_MODE_NOPRIV_DROP,
- *   insufficient privilege will result in the probe firing being silently
- *   ignored for the enabling; if the policy is DTRACE_NODE_NOPRIV_RESTRICT,
- *   insufficient privilege will not prevent probe processing for the
- *   enabling, but restrictions will be in place that induce a UPRIV fault
- *   upon attempt to examine probe arguments or current process state.
+ *   is insufficient for that mode (a combination of DTRACE_MODE_NOPRIV_DROP,
+ *   DTRACE_MODE_NOPRIV_RESTRICT, and DTRACE_MODE_LIMITEDPRIV_RESTRICT).  If
+ *   DTRACE_MODE_NOPRIV_DROP bit is set, insufficient privilege will result
+ *   in the probe firing being silently ignored for the enabling; if the
+ *   DTRACE_NODE_NOPRIV_RESTRICT bit is set, insufficient privilege will not
+ *   prevent probe processing for the enabling, but restrictions will be in
+ *   place that induce a UPRIV fault upon attempt to examine probe arguments
+ *   or current process state.  If the DTRACE_MODE_LIMITEDPRIV_RESTRICT bit
+ *   is set, similar restrictions will be placed upon operation if the
+ *   privilege is sufficient to process the enabling, but does not otherwise
+ *   entitle the enabling to all zones.  The DTRACE_MODE_NOPRIV_DROP and
+ *   DTRACE_MODE_NOPRIV_RESTRICT are mutually exclusive (and one of these
+ *   two policies must be specified), but either may be combined (or not)
+ *   with DTRACE_MODE_LIMITEDPRIV_RESTRICT.
  *
  * 1.10.4  Caller's context
  *
@@ -2054,6 +2062,7 @@ typedef struct dtrace_pops {
 #define        DTRACE_MODE_USER                        0x02
 #define        DTRACE_MODE_NOPRIV_DROP                 0x10
 #define        DTRACE_MODE_NOPRIV_RESTRICT             0x20
+#define        DTRACE_MODE_LIMITEDPRIV_RESTRICT        0x40
 
 typedef uintptr_t      dtrace_provider_id_t;
 
@@ -2268,6 +2277,7 @@ extern void (*dtrace_helpers_cleanup)();
 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)();

Modified: vendor-sys/illumos/dist/uts/common/sys/dtrace_impl.h
==============================================================================
--- vendor-sys/illumos/dist/uts/common/sys/dtrace_impl.h        Mon Jun  2 
23:50:19 2014        (r266985)
+++ vendor-sys/illumos/dist/uts/common/sys/dtrace_impl.h        Tue Jun  3 
00:55:15 2014        (r266986)
@@ -924,6 +924,7 @@ typedef struct dtrace_mstate {
        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
@@ -1144,6 +1145,7 @@ struct dtrace_state {
        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 {
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to