Deleted Added
full compact
dtrace.c (268572) dtrace.c (268578)
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE

--- 4 unchanged lines hidden (view full) ---

13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 *
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE

--- 4 unchanged lines hidden (view full) ---

13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 *
21 * $FreeBSD: stable/10/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c 268572 2014-07-12 18:23:35Z pfg $
21 * $FreeBSD: stable/10/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c 268578 2014-07-12 22:56:41Z rpaulo $
22 */
23
24/*
25 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
26 * Copyright (c) 2013, Joyent, Inc. All rights reserved.
27 * Copyright (c) 2012 by Delphix. All rights reserved.
28 */
29

--- 74 unchanged lines hidden (view full) ---

104#include <sys/taskq.h>
105#if defined(sun)
106#include <sys/mkdev.h>
107#include <sys/kdi.h>
108#endif
109#include <sys/zone.h>
110#include <sys/socket.h>
111#include <netinet/in.h>
22 */
23
24/*
25 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
26 * Copyright (c) 2013, Joyent, Inc. All rights reserved.
27 * Copyright (c) 2012 by Delphix. All rights reserved.
28 */
29

--- 74 unchanged lines hidden (view full) ---

104#include <sys/taskq.h>
105#if defined(sun)
106#include <sys/mkdev.h>
107#include <sys/kdi.h>
108#endif
109#include <sys/zone.h>
110#include <sys/socket.h>
111#include <netinet/in.h>
112#include "strtolctype.h"
112
113/* FreeBSD includes: */
114#if !defined(sun)
115#include <sys/callout.h>
116#include <sys/ctype.h>
117#include <sys/eventhandler.h>
118#include <sys/limits.h>
119#include <sys/kdb.h>

--- 89 unchanged lines hidden (view full) ---

209static struct unrhdr *dtrace_arena; /* Probe ID number. */
210#endif
211static dtrace_probe_t **dtrace_probes; /* array of all probes */
212static int dtrace_nprobes; /* number of probes */
213static dtrace_provider_t *dtrace_provider; /* provider list */
214static dtrace_meta_t *dtrace_meta_pid; /* user-land meta provider */
215static int dtrace_opens; /* number of opens */
216static int dtrace_helpers; /* number of helpers */
113
114/* FreeBSD includes: */
115#if !defined(sun)
116#include <sys/callout.h>
117#include <sys/ctype.h>
118#include <sys/eventhandler.h>
119#include <sys/limits.h>
120#include <sys/kdb.h>

--- 89 unchanged lines hidden (view full) ---

210static struct unrhdr *dtrace_arena; /* Probe ID number. */
211#endif
212static dtrace_probe_t **dtrace_probes; /* array of all probes */
213static int dtrace_nprobes; /* number of probes */
214static dtrace_provider_t *dtrace_provider; /* provider list */
215static dtrace_meta_t *dtrace_meta_pid; /* user-land meta provider */
216static int dtrace_opens; /* number of opens */
217static int dtrace_helpers; /* number of helpers */
218static int dtrace_getf; /* number of unpriv getf()s */
217#if defined(sun)
218static void *dtrace_softstate; /* softstate pointer */
219#endif
220static dtrace_hash_t *dtrace_bymod; /* probes hashed by module */
221static dtrace_hash_t *dtrace_byfunc; /* probes hashed by function */
222static dtrace_hash_t *dtrace_byname; /* probes hashed by name */
223static dtrace_toxrange_t *dtrace_toxrange; /* toxic range array */
224static int dtrace_toxranges; /* number of toxic ranges */

--- 234 unchanged lines hidden (view full) ---

459
460/*
461 * Test whether a range of memory starting at testaddr of size testsz falls
462 * within the range of memory described by addr, sz. We take care to avoid
463 * problems with overflow and underflow of the unsigned quantities, and
464 * disallow all negative sizes. Ranges of size 0 are allowed.
465 */
466#define DTRACE_INRANGE(testaddr, testsz, baseaddr, basesz) \
219#if defined(sun)
220static void *dtrace_softstate; /* softstate pointer */
221#endif
222static dtrace_hash_t *dtrace_bymod; /* probes hashed by module */
223static dtrace_hash_t *dtrace_byfunc; /* probes hashed by function */
224static dtrace_hash_t *dtrace_byname; /* probes hashed by name */
225static dtrace_toxrange_t *dtrace_toxrange; /* toxic range array */
226static int dtrace_toxranges; /* number of toxic ranges */

--- 234 unchanged lines hidden (view full) ---

461
462/*
463 * Test whether a range of memory starting at testaddr of size testsz falls
464 * within the range of memory described by addr, sz. We take care to avoid
465 * problems with overflow and underflow of the unsigned quantities, and
466 * disallow all negative sizes. Ranges of size 0 are allowed.
467 */
468#define DTRACE_INRANGE(testaddr, testsz, baseaddr, basesz) \
467 ((testaddr) - (baseaddr) < (basesz) && \
468 (testaddr) + (testsz) - (baseaddr) <= (basesz) && \
469 ((testaddr) - (uintptr_t)(baseaddr) < (basesz) && \
470 (testaddr) + (testsz) - (uintptr_t)(baseaddr) <= (basesz) && \
469 (testaddr) + (testsz) >= (testaddr))
470
471/*
472 * Test whether alloc_sz bytes will fit in the scratch region. We isolate
473 * alloc_sz on the righthand side of the comparison in order to avoid overflow
474 * or underflow in the comparison with it. This is simpler than the INRANGE
475 * check above, because we know that the dtms_scratch_ptr is valid in the
476 * range. Allocations of size zero are allowed.

--- 92 unchanged lines hidden (view full) ---

569uint16_t dtrace_load16(uintptr_t);
570uint32_t dtrace_load32(uintptr_t);
571uint64_t dtrace_load64(uintptr_t);
572uint8_t dtrace_load8(uintptr_t);
573void dtrace_dynvar_clean(dtrace_dstate_t *);
574dtrace_dynvar_t *dtrace_dynvar(dtrace_dstate_t *, uint_t, dtrace_key_t *,
575 size_t, dtrace_dynvar_op_t, dtrace_mstate_t *, dtrace_vstate_t *);
576uintptr_t dtrace_dif_varstr(uintptr_t, dtrace_state_t *, dtrace_mstate_t *);
471 (testaddr) + (testsz) >= (testaddr))
472
473/*
474 * Test whether alloc_sz bytes will fit in the scratch region. We isolate
475 * alloc_sz on the righthand side of the comparison in order to avoid overflow
476 * or underflow in the comparison with it. This is simpler than the INRANGE
477 * check above, because we know that the dtms_scratch_ptr is valid in the
478 * range. Allocations of size zero are allowed.

--- 92 unchanged lines hidden (view full) ---

571uint16_t dtrace_load16(uintptr_t);
572uint32_t dtrace_load32(uintptr_t);
573uint64_t dtrace_load64(uintptr_t);
574uint8_t dtrace_load8(uintptr_t);
575void dtrace_dynvar_clean(dtrace_dstate_t *);
576dtrace_dynvar_t *dtrace_dynvar(dtrace_dstate_t *, uint_t, dtrace_key_t *,
577 size_t, dtrace_dynvar_op_t, dtrace_mstate_t *, dtrace_vstate_t *);
578uintptr_t dtrace_dif_varstr(uintptr_t, dtrace_state_t *, dtrace_mstate_t *);
579static int dtrace_priv_proc(dtrace_state_t *);
580static void dtrace_getf_barrier(void);
577
578/*
579 * DTrace Probe Context Functions
580 *
581 * These functions are called from probe context. Because probe context is
582 * any context in which C may be called, arbitrarily locks may be held,
583 * interrupts may be disabled, we may be in arbitrary dispatched state, etc.
584 * As a result, functions called from probe context may only call other DTrace

--- 128 unchanged lines hidden (view full) ---

713 mstate->dtms_scratch_size))
714 return (1);
715
716 /*
717 * Now check to see if it's a dynamic variable. This check will pick
718 * up both thread-local variables and any global dynamically-allocated
719 * variables.
720 */
581
582/*
583 * DTrace Probe Context Functions
584 *
585 * These functions are called from probe context. Because probe context is
586 * any context in which C may be called, arbitrarily locks may be held,
587 * interrupts may be disabled, we may be in arbitrary dispatched state, etc.
588 * As a result, functions called from probe context may only call other DTrace

--- 128 unchanged lines hidden (view full) ---

717 mstate->dtms_scratch_size))
718 return (1);
719
720 /*
721 * Now check to see if it's a dynamic variable. This check will pick
722 * up both thread-local variables and any global dynamically-allocated
723 * variables.
724 */
721 if (DTRACE_INRANGE(addr, sz, (uintptr_t)vstate->dtvs_dynvars.dtds_base,
725 if (DTRACE_INRANGE(addr, sz, vstate->dtvs_dynvars.dtds_base,
722 vstate->dtvs_dynvars.dtds_size)) {
723 dtrace_dstate_t *dstate = &vstate->dtvs_dynvars;
724 uintptr_t base = (uintptr_t)dstate->dtds_base +
725 (dstate->dtds_hashsize * sizeof (dtrace_dynhash_t));
726 uintptr_t chunkoffs;
727
728 /*
729 * Before we assume that we can store here, we need to make

--- 50 unchanged lines hidden (view full) ---

780 * DTrace subroutines (DIF_SUBR_*) should use this helper to implement
781 * appropriate memory access protection.
782 */
783static int
784dtrace_canload(uint64_t addr, size_t sz, dtrace_mstate_t *mstate,
785 dtrace_vstate_t *vstate)
786{
787 volatile uintptr_t *illval = &cpu_core[curcpu].cpuc_dtrace_illval;
726 vstate->dtvs_dynvars.dtds_size)) {
727 dtrace_dstate_t *dstate = &vstate->dtvs_dynvars;
728 uintptr_t base = (uintptr_t)dstate->dtds_base +
729 (dstate->dtds_hashsize * sizeof (dtrace_dynhash_t));
730 uintptr_t chunkoffs;
731
732 /*
733 * Before we assume that we can store here, we need to make

--- 50 unchanged lines hidden (view full) ---

784 * DTrace subroutines (DIF_SUBR_*) should use this helper to implement
785 * appropriate memory access protection.
786 */
787static int
788dtrace_canload(uint64_t addr, size_t sz, dtrace_mstate_t *mstate,
789 dtrace_vstate_t *vstate)
790{
791 volatile uintptr_t *illval = &cpu_core[curcpu].cpuc_dtrace_illval;
792 file_t *fp;
788
789 /*
790 * If we hold the privilege to read from kernel memory, then
791 * everything is readable.
792 */
793 if ((mstate->dtms_access & DTRACE_ACCESS_KERNEL) != 0)
794 return (1);
795
796 /*
797 * You can obviously read that which you can store.
798 */
799 if (dtrace_canstore(addr, sz, mstate, vstate))
800 return (1);
801
802 /*
803 * We're allowed to read from our own string table.
804 */
793
794 /*
795 * If we hold the privilege to read from kernel memory, then
796 * everything is readable.
797 */
798 if ((mstate->dtms_access & DTRACE_ACCESS_KERNEL) != 0)
799 return (1);
800
801 /*
802 * You can obviously read that which you can store.
803 */
804 if (dtrace_canstore(addr, sz, mstate, vstate))
805 return (1);
806
807 /*
808 * We're allowed to read from our own string table.
809 */
805 if (DTRACE_INRANGE(addr, sz, (uintptr_t)mstate->dtms_difo->dtdo_strtab,
810 if (DTRACE_INRANGE(addr, sz, mstate->dtms_difo->dtdo_strtab,
806 mstate->dtms_difo->dtdo_strlen))
807 return (1);
808
811 mstate->dtms_difo->dtdo_strlen))
812 return (1);
813
814 if (vstate->dtvs_state != NULL &&
815 dtrace_priv_proc(vstate->dtvs_state)) {
816 proc_t *p;
817
818 /*
819 * When we have privileges to the current process, there are
820 * several context-related kernel structures that are safe to
821 * read, even absent the privilege to read from kernel memory.
822 * These reads are safe because these structures contain only
823 * state that (1) we're permitted to read, (2) is harmless or
824 * (3) contains pointers to additional kernel state that we're
825 * not permitted to read (and as such, do not present an
826 * opportunity for privilege escalation). Finally (and
827 * critically), because of the nature of their relation with
828 * the current thread context, the memory associated with these
829 * structures cannot change over the duration of probe context,
830 * and it is therefore impossible for this memory to be
831 * deallocated and reallocated as something else while it's
832 * being operated upon.
833 */
834 if (DTRACE_INRANGE(addr, sz, curthread, sizeof (kthread_t)))
835 return (1);
836
837 if ((p = curthread->t_procp) != NULL && DTRACE_INRANGE(addr,
838 sz, curthread->t_procp, sizeof (proc_t))) {
839 return (1);
840 }
841
842 if (curthread->t_cred != NULL && DTRACE_INRANGE(addr, sz,
843 curthread->t_cred, sizeof (cred_t))) {
844 return (1);
845 }
846
847#if defined(sun)
848 if (p != NULL && p->p_pidp != NULL && DTRACE_INRANGE(addr, sz,
849 &(p->p_pidp->pid_id), sizeof (pid_t))) {
850 return (1);
851 }
852
853 if (curthread->t_cpu != NULL && DTRACE_INRANGE(addr, sz,
854 curthread->t_cpu, offsetof(cpu_t, cpu_pause_thread))) {
855 return (1);
856 }
857#endif
858 }
859
860 if ((fp = mstate->dtms_getf) != NULL) {
861 uintptr_t psz = sizeof (void *);
862 vnode_t *vp;
863 vnodeops_t *op;
864
865 /*
866 * When getf() returns a file_t, the enabling is implicitly
867 * granted the (transient) right to read the returned file_t
868 * as well as the v_path and v_op->vnop_name of the underlying
869 * vnode. These accesses are allowed after a successful
870 * getf() because the members that they refer to cannot change
871 * once set -- and the barrier logic in the kernel's closef()
872 * path assures that the file_t and its referenced vode_t
873 * cannot themselves be stale (that is, it impossible for
874 * either dtms_getf itself or its f_vnode member to reference
875 * freed memory).
876 */
877 if (DTRACE_INRANGE(addr, sz, fp, sizeof (file_t)))
878 return (1);
879
880 if ((vp = fp->f_vnode) != NULL) {
881#if defined(sun)
882 if (DTRACE_INRANGE(addr, sz, &vp->v_path, psz))
883 return (1);
884 if (vp->v_path != NULL && DTRACE_INRANGE(addr, sz,
885 vp->v_path, strlen(vp->v_path) + 1)) {
886 return (1);
887 }
888#endif
889
890 if (DTRACE_INRANGE(addr, sz, &vp->v_op, psz))
891 return (1);
892
893#if defined(sun)
894 if ((op = vp->v_op) != NULL &&
895 DTRACE_INRANGE(addr, sz, &op->vnop_name, psz)) {
896 return (1);
897 }
898
899 if (op != NULL && op->vnop_name != NULL &&
900 DTRACE_INRANGE(addr, sz, op->vnop_name,
901 strlen(op->vnop_name) + 1)) {
902 return (1);
903 }
904#endif
905 }
906 }
907
809 DTRACE_CPUFLAG_SET(CPU_DTRACE_KPRIV);
810 *illval = addr;
811 return (0);
812}
813
814/*
815 * Convenience routine to check to see if a given string is within a memory
816 * region in which a load may be issued given the user's privilege level;

--- 43 unchanged lines hidden (view full) ---

860 vstate->dtvs_state->dts_options[DTRACEOPT_STRSIZE]) + 1;
861 else
862 sz = type->dtdt_size;
863
864 return (dtrace_canload((uintptr_t)src, sz, mstate, vstate));
865}
866
867/*
908 DTRACE_CPUFLAG_SET(CPU_DTRACE_KPRIV);
909 *illval = addr;
910 return (0);
911}
912
913/*
914 * Convenience routine to check to see if a given string is within a memory
915 * region in which a load may be issued given the user's privilege level;

--- 43 unchanged lines hidden (view full) ---

959 vstate->dtvs_state->dts_options[DTRACEOPT_STRSIZE]) + 1;
960 else
961 sz = type->dtdt_size;
962
963 return (dtrace_canload((uintptr_t)src, sz, mstate, vstate));
964}
965
966/*
967 * Convert a string to a signed integer using safe loads.
968 *
969 * NOTE: This function uses various macros from strtolctype.h to manipulate
970 * digit values, etc -- these have all been checked to ensure they make
971 * no additional function calls.
972 */
973static int64_t
974dtrace_strtoll(char *input, int base, size_t limit)
975{
976 uintptr_t pos = (uintptr_t)input;
977 int64_t val = 0;
978 int x;
979 boolean_t neg = B_FALSE;
980 char c, cc, ccc;
981 uintptr_t end = pos + limit;
982
983 /*
984 * Consume any whitespace preceding digits.
985 */
986 while ((c = dtrace_load8(pos)) == ' ' || c == '\t')
987 pos++;
988
989 /*
990 * Handle an explicit sign if one is present.
991 */
992 if (c == '-' || c == '+') {
993 if (c == '-')
994 neg = B_TRUE;
995 c = dtrace_load8(++pos);
996 }
997
998 /*
999 * Check for an explicit hexadecimal prefix ("0x" or "0X") and skip it
1000 * if present.
1001 */
1002 if (base == 16 && c == '0' && ((cc = dtrace_load8(pos + 1)) == 'x' ||
1003 cc == 'X') && isxdigit(ccc = dtrace_load8(pos + 2))) {
1004 pos += 2;
1005 c = ccc;
1006 }
1007
1008 /*
1009 * Read in contiguous digits until the first non-digit character.
1010 */
1011 for (; pos < end && c != '\0' && lisalnum(c) && (x = DIGIT(c)) < base;
1012 c = dtrace_load8(++pos))
1013 val = val * base + x;
1014
1015 return (neg ? -val : val);
1016}
1017
1018/*
868 * Compare two strings using safe loads.
869 */
870static int
871dtrace_strncmp(char *s1, char *s2, size_t limit)
872{
873 uint8_t c1, c2;
874 volatile uint16_t *flags;
875

--- 304 unchanged lines hidden (view full) ---

1180 cred_t *cr, *s_cr = state->dts_cred.dcr_cred;
1181
1182 /*
1183 * We should always have a non-NULL state cred here, since if cred
1184 * is null (anonymous tracing), we fast-path bypass this routine.
1185 */
1186 ASSERT(s_cr != NULL);
1187
1019 * Compare two strings using safe loads.
1020 */
1021static int
1022dtrace_strncmp(char *s1, char *s2, size_t limit)
1023{
1024 uint8_t c1, c2;
1025 volatile uint16_t *flags;
1026

--- 304 unchanged lines hidden (view full) ---

1331 cred_t *cr, *s_cr = state->dts_cred.dcr_cred;
1332
1333 /*
1334 * We should always have a non-NULL state cred here, since if cred
1335 * is null (anonymous tracing), we fast-path bypass this routine.
1336 */
1337 ASSERT(s_cr != NULL);
1338
1188 if ((cr = CRED()) != NULL &&
1189 s_cr->cr_zone == cr->cr_zone)
1339 if ((cr = CRED()) != NULL && s_cr->cr_zone == cr->cr_zone)
1190 return (1);
1191
1192 return (0);
1193#else
1194 return (1);
1195#endif
1196}
1197

--- 83 unchanged lines hidden (view full) ---

1281 return (1);
1282
1283 cpu_core[curcpu].cpuc_dtrace_flags |= CPU_DTRACE_KPRIV;
1284
1285 return (0);
1286}
1287
1288/*
1340 return (1);
1341
1342 return (0);
1343#else
1344 return (1);
1345#endif
1346}
1347

--- 83 unchanged lines hidden (view full) ---

1431 return (1);
1432
1433 cpu_core[curcpu].cpuc_dtrace_flags |= CPU_DTRACE_KPRIV;
1434
1435 return (0);
1436}
1437
1438/*
1439 * Determine if the dte_cond of the specified ECB allows for processing of
1440 * the current probe to continue. Note that this routine may allow continued
1441 * processing, but with access(es) stripped from the mstate's dtms_access
1442 * field.
1443 */
1444static int
1445dtrace_priv_probe(dtrace_state_t *state, dtrace_mstate_t *mstate,
1446 dtrace_ecb_t *ecb)
1447{
1448 dtrace_probe_t *probe = ecb->dte_probe;
1449 dtrace_provider_t *prov = probe->dtpr_provider;
1450 dtrace_pops_t *pops = &prov->dtpv_pops;
1451 int mode = DTRACE_MODE_NOPRIV_DROP;
1452
1453 ASSERT(ecb->dte_cond);
1454
1455#if defined(sun)
1456 if (pops->dtps_mode != NULL) {
1457 mode = pops->dtps_mode(prov->dtpv_arg,
1458 probe->dtpr_id, probe->dtpr_arg);
1459
1460 ASSERT((mode & DTRACE_MODE_USER) ||
1461 (mode & DTRACE_MODE_KERNEL));
1462 ASSERT((mode & DTRACE_MODE_NOPRIV_RESTRICT) ||
1463 (mode & DTRACE_MODE_NOPRIV_DROP));
1464 }
1465
1466 /*
1467 * If the dte_cond bits indicate that this consumer is only allowed to
1468 * see user-mode firings of this probe, call the provider's dtps_mode()
1469 * entry point to check that the probe was fired while in a user
1470 * context. If that's not the case, use the policy specified by the
1471 * provider to determine if we drop the probe or merely restrict
1472 * operation.
1473 */
1474 if (ecb->dte_cond & DTRACE_COND_USERMODE) {
1475 ASSERT(mode != DTRACE_MODE_NOPRIV_DROP);
1476
1477 if (!(mode & DTRACE_MODE_USER)) {
1478 if (mode & DTRACE_MODE_NOPRIV_DROP)
1479 return (0);
1480
1481 mstate->dtms_access &= ~DTRACE_ACCESS_ARGS;
1482 }
1483 }
1484#endif
1485
1486 /*
1487 * This is more subtle than it looks. We have to be absolutely certain
1488 * that CRED() isn't going to change out from under us so it's only
1489 * legit to examine that structure if we're in constrained situations.
1490 * Currently, the only times we'll this check is if a non-super-user
1491 * has enabled the profile or syscall providers -- providers that
1492 * allow visibility of all processes. For the profile case, the check
1493 * above will ensure that we're examining a user context.
1494 */
1495 if (ecb->dte_cond & DTRACE_COND_OWNER) {
1496 cred_t *cr;
1497 cred_t *s_cr = state->dts_cred.dcr_cred;
1498 proc_t *proc;
1499
1500 ASSERT(s_cr != NULL);
1501
1502 if ((cr = CRED()) == NULL ||
1503 s_cr->cr_uid != cr->cr_uid ||
1504 s_cr->cr_uid != cr->cr_ruid ||
1505 s_cr->cr_uid != cr->cr_suid ||
1506 s_cr->cr_gid != cr->cr_gid ||
1507 s_cr->cr_gid != cr->cr_rgid ||
1508 s_cr->cr_gid != cr->cr_sgid ||
1509 (proc = ttoproc(curthread)) == NULL ||
1510 (proc->p_flag & SNOCD)) {
1511 if (mode & DTRACE_MODE_NOPRIV_DROP)
1512 return (0);
1513
1514#if defined(sun)
1515 mstate->dtms_access &= ~DTRACE_ACCESS_PROC;
1516#endif
1517 }
1518 }
1519
1520#if defined(sun)
1521 /*
1522 * If our dte_cond is set to DTRACE_COND_ZONEOWNER and we are not
1523 * in our zone, check to see if our mode policy is to restrict rather
1524 * than to drop; if to restrict, strip away both DTRACE_ACCESS_PROC
1525 * and DTRACE_ACCESS_ARGS
1526 */
1527 if (ecb->dte_cond & DTRACE_COND_ZONEOWNER) {
1528 cred_t *cr;
1529 cred_t *s_cr = state->dts_cred.dcr_cred;
1530
1531 ASSERT(s_cr != NULL);
1532
1533 if ((cr = CRED()) == NULL ||
1534 s_cr->cr_zone->zone_id != cr->cr_zone->zone_id) {
1535 if (mode & DTRACE_MODE_NOPRIV_DROP)
1536 return (0);
1537
1538 mstate->dtms_access &=
1539 ~(DTRACE_ACCESS_PROC | DTRACE_ACCESS_ARGS);
1540 }
1541 }
1542#endif
1543
1544 return (1);
1545}
1546
1547/*
1289 * Note: not called from probe context. This function is called
1290 * asynchronously (and at a regular interval) from outside of probe context to
1291 * clean the dirty dynamic variable lists on all CPUs. Dynamic variable
1292 * cleaning is explained in detail in <sys/dtrace_impl.h>.
1293 */
1294void
1295dtrace_dynvar_clean(dtrace_dstate_t *dstate)
1296{

--- 1601 unchanged lines hidden (view full) ---

2898 return (0);
2899 }
2900
2901 return (dtrace_getreg(tframe, ndx));
2902 }
2903#endif
2904
2905 case DIF_VAR_CURTHREAD:
1548 * Note: not called from probe context. This function is called
1549 * asynchronously (and at a regular interval) from outside of probe context to
1550 * clean the dirty dynamic variable lists on all CPUs. Dynamic variable
1551 * cleaning is explained in detail in <sys/dtrace_impl.h>.
1552 */
1553void
1554dtrace_dynvar_clean(dtrace_dstate_t *dstate)
1555{

--- 1601 unchanged lines hidden (view full) ---

3157 return (0);
3158 }
3159
3160 return (dtrace_getreg(tframe, ndx));
3161 }
3162#endif
3163
3164 case DIF_VAR_CURTHREAD:
2906 if (!dtrace_priv_kernel(state))
3165 if (!dtrace_priv_proc(state))
2907 return (0);
2908 return ((uint64_t)(uintptr_t)curthread);
2909
2910 case DIF_VAR_TIMESTAMP:
2911 if (!(mstate->dtms_present & DTRACE_MSTATE_TIMESTAMP)) {
2912 mstate->dtms_timestamp = dtrace_gethrtime();
2913 mstate->dtms_present |= DTRACE_MSTATE_TIMESTAMP;
2914 }

--- 339 unchanged lines hidden (view full) ---

3254 }
3255#endif
3256 default:
3257 DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
3258 return (0);
3259 }
3260}
3261
3166 return (0);
3167 return ((uint64_t)(uintptr_t)curthread);
3168
3169 case DIF_VAR_TIMESTAMP:
3170 if (!(mstate->dtms_present & DTRACE_MSTATE_TIMESTAMP)) {
3171 mstate->dtms_timestamp = dtrace_gethrtime();
3172 mstate->dtms_present |= DTRACE_MSTATE_TIMESTAMP;
3173 }

--- 339 unchanged lines hidden (view full) ---

3513 }
3514#endif
3515 default:
3516 DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
3517 return (0);
3518 }
3519}
3520
3521
3522typedef enum dtrace_json_state {
3523 DTRACE_JSON_REST = 1,
3524 DTRACE_JSON_OBJECT,
3525 DTRACE_JSON_STRING,
3526 DTRACE_JSON_STRING_ESCAPE,
3527 DTRACE_JSON_STRING_ESCAPE_UNICODE,
3528 DTRACE_JSON_COLON,
3529 DTRACE_JSON_COMMA,
3530 DTRACE_JSON_VALUE,
3531 DTRACE_JSON_IDENTIFIER,
3532 DTRACE_JSON_NUMBER,
3533 DTRACE_JSON_NUMBER_FRAC,
3534 DTRACE_JSON_NUMBER_EXP,
3535 DTRACE_JSON_COLLECT_OBJECT
3536} dtrace_json_state_t;
3537
3262/*
3538/*
3539 * This function possesses just enough knowledge about JSON to extract a single
3540 * value from a JSON string and store it in the scratch buffer. It is able
3541 * to extract nested object values, and members of arrays by index.
3542 *
3543 * elemlist is a list of JSON keys, stored as packed NUL-terminated strings, to
3544 * be looked up as we descend into the object tree. e.g.
3545 *
3546 * foo[0].bar.baz[32] --> "foo" NUL "0" NUL "bar" NUL "baz" NUL "32" NUL
3547 * with nelems = 5.
3548 *
3549 * The run time of this function must be bounded above by strsize to limit the
3550 * amount of work done in probe context. As such, it is implemented as a
3551 * simple state machine, reading one character at a time using safe loads
3552 * until we find the requested element, hit a parsing error or run off the
3553 * end of the object or string.
3554 *
3555 * As there is no way for a subroutine to return an error without interrupting
3556 * clause execution, we simply return NULL in the event of a missing key or any
3557 * other error condition. Each NULL return in this function is commented with
3558 * the error condition it represents -- parsing or otherwise.
3559 *
3560 * The set of states for the state machine closely matches the JSON
3561 * specification (http://json.org/). Briefly:
3562 *
3563 * DTRACE_JSON_REST:
3564 * Skip whitespace until we find either a top-level Object, moving
3565 * to DTRACE_JSON_OBJECT; or an Array, moving to DTRACE_JSON_VALUE.
3566 *
3567 * DTRACE_JSON_OBJECT:
3568 * Locate the next key String in an Object. Sets a flag to denote
3569 * the next String as a key string and moves to DTRACE_JSON_STRING.
3570 *
3571 * DTRACE_JSON_COLON:
3572 * Skip whitespace until we find the colon that separates key Strings
3573 * from their values. Once found, move to DTRACE_JSON_VALUE.
3574 *
3575 * DTRACE_JSON_VALUE:
3576 * Detects the type of the next value (String, Number, Identifier, Object
3577 * or Array) and routes to the states that process that type. Here we also
3578 * deal with the element selector list if we are requested to traverse down
3579 * into the object tree.
3580 *
3581 * DTRACE_JSON_COMMA:
3582 * Skip whitespace until we find the comma that separates key-value pairs
3583 * in Objects (returning to DTRACE_JSON_OBJECT) or values in Arrays
3584 * (similarly DTRACE_JSON_VALUE). All following literal value processing
3585 * states return to this state at the end of their value, unless otherwise
3586 * noted.
3587 *
3588 * DTRACE_JSON_NUMBER, DTRACE_JSON_NUMBER_FRAC, DTRACE_JSON_NUMBER_EXP:
3589 * Processes a Number literal from the JSON, including any exponent
3590 * component that may be present. Numbers are returned as strings, which
3591 * may be passed to strtoll() if an integer is required.
3592 *
3593 * DTRACE_JSON_IDENTIFIER:
3594 * Processes a "true", "false" or "null" literal in the JSON.
3595 *
3596 * DTRACE_JSON_STRING, DTRACE_JSON_STRING_ESCAPE,
3597 * DTRACE_JSON_STRING_ESCAPE_UNICODE:
3598 * Processes a String literal from the JSON, whether the String denotes
3599 * a key, a value or part of a larger Object. Handles all escape sequences
3600 * present in the specification, including four-digit unicode characters,
3601 * but merely includes the escape sequence without converting it to the
3602 * actual escaped character. If the String is flagged as a key, we
3603 * move to DTRACE_JSON_COLON rather than DTRACE_JSON_COMMA.
3604 *
3605 * DTRACE_JSON_COLLECT_OBJECT:
3606 * This state collects an entire Object (or Array), correctly handling
3607 * embedded strings. If the full element selector list matches this nested
3608 * object, we return the Object in full as a string. If not, we use this
3609 * state to skip to the next value at this level and continue processing.
3610 *
3611 * NOTE: This function uses various macros from strtolctype.h to manipulate
3612 * digit values, etc -- these have all been checked to ensure they make
3613 * no additional function calls.
3614 */
3615static char *
3616dtrace_json(uint64_t size, uintptr_t json, char *elemlist, int nelems,
3617 char *dest)
3618{
3619 dtrace_json_state_t state = DTRACE_JSON_REST;
3620 int64_t array_elem = INT64_MIN;
3621 int64_t array_pos = 0;
3622 uint8_t escape_unicount = 0;
3623 boolean_t string_is_key = B_FALSE;
3624 boolean_t collect_object = B_FALSE;
3625 boolean_t found_key = B_FALSE;
3626 boolean_t in_array = B_FALSE;
3627 uint32_t braces = 0, brackets = 0;
3628 char *elem = elemlist;
3629 char *dd = dest;
3630 uintptr_t cur;
3631
3632 for (cur = json; cur < json + size; cur++) {
3633 char cc = dtrace_load8(cur);
3634 if (cc == '\0')
3635 return (NULL);
3636
3637 switch (state) {
3638 case DTRACE_JSON_REST:
3639 if (isspace(cc))
3640 break;
3641
3642 if (cc == '{') {
3643 state = DTRACE_JSON_OBJECT;
3644 break;
3645 }
3646
3647 if (cc == '[') {
3648 in_array = B_TRUE;
3649 array_pos = 0;
3650 array_elem = dtrace_strtoll(elem, 10, size);
3651 found_key = array_elem == 0 ? B_TRUE : B_FALSE;
3652 state = DTRACE_JSON_VALUE;
3653 break;
3654 }
3655
3656 /*
3657 * ERROR: expected to find a top-level object or array.
3658 */
3659 return (NULL);
3660 case DTRACE_JSON_OBJECT:
3661 if (isspace(cc))
3662 break;
3663
3664 if (cc == '"') {
3665 state = DTRACE_JSON_STRING;
3666 string_is_key = B_TRUE;
3667 break;
3668 }
3669
3670 /*
3671 * ERROR: either the object did not start with a key
3672 * string, or we've run off the end of the object
3673 * without finding the requested key.
3674 */
3675 return (NULL);
3676 case DTRACE_JSON_STRING:
3677 if (cc == '\\') {
3678 *dd++ = '\\';
3679 state = DTRACE_JSON_STRING_ESCAPE;
3680 break;
3681 }
3682
3683 if (cc == '"') {
3684 if (collect_object) {
3685 /*
3686 * We don't reset the dest here, as
3687 * the string is part of a larger
3688 * object being collected.
3689 */
3690 *dd++ = cc;
3691 collect_object = B_FALSE;
3692 state = DTRACE_JSON_COLLECT_OBJECT;
3693 break;
3694 }
3695 *dd = '\0';
3696 dd = dest; /* reset string buffer */
3697 if (string_is_key) {
3698 if (dtrace_strncmp(dest, elem,
3699 size) == 0)
3700 found_key = B_TRUE;
3701 } else if (found_key) {
3702 if (nelems > 1) {
3703 /*
3704 * We expected an object, not
3705 * this string.
3706 */
3707 return (NULL);
3708 }
3709 return (dest);
3710 }
3711 state = string_is_key ? DTRACE_JSON_COLON :
3712 DTRACE_JSON_COMMA;
3713 string_is_key = B_FALSE;
3714 break;
3715 }
3716
3717 *dd++ = cc;
3718 break;
3719 case DTRACE_JSON_STRING_ESCAPE:
3720 *dd++ = cc;
3721 if (cc == 'u') {
3722 escape_unicount = 0;
3723 state = DTRACE_JSON_STRING_ESCAPE_UNICODE;
3724 } else {
3725 state = DTRACE_JSON_STRING;
3726 }
3727 break;
3728 case DTRACE_JSON_STRING_ESCAPE_UNICODE:
3729 if (!isxdigit(cc)) {
3730 /*
3731 * ERROR: invalid unicode escape, expected
3732 * four valid hexidecimal digits.
3733 */
3734 return (NULL);
3735 }
3736
3737 *dd++ = cc;
3738 if (++escape_unicount == 4)
3739 state = DTRACE_JSON_STRING;
3740 break;
3741 case DTRACE_JSON_COLON:
3742 if (isspace(cc))
3743 break;
3744
3745 if (cc == ':') {
3746 state = DTRACE_JSON_VALUE;
3747 break;
3748 }
3749
3750 /*
3751 * ERROR: expected a colon.
3752 */
3753 return (NULL);
3754 case DTRACE_JSON_COMMA:
3755 if (isspace(cc))
3756 break;
3757
3758 if (cc == ',') {
3759 if (in_array) {
3760 state = DTRACE_JSON_VALUE;
3761 if (++array_pos == array_elem)
3762 found_key = B_TRUE;
3763 } else {
3764 state = DTRACE_JSON_OBJECT;
3765 }
3766 break;
3767 }
3768
3769 /*
3770 * ERROR: either we hit an unexpected character, or
3771 * we reached the end of the object or array without
3772 * finding the requested key.
3773 */
3774 return (NULL);
3775 case DTRACE_JSON_IDENTIFIER:
3776 if (islower(cc)) {
3777 *dd++ = cc;
3778 break;
3779 }
3780
3781 *dd = '\0';
3782 dd = dest; /* reset string buffer */
3783
3784 if (dtrace_strncmp(dest, "true", 5) == 0 ||
3785 dtrace_strncmp(dest, "false", 6) == 0 ||
3786 dtrace_strncmp(dest, "null", 5) == 0) {
3787 if (found_key) {
3788 if (nelems > 1) {
3789 /*
3790 * ERROR: We expected an object,
3791 * not this identifier.
3792 */
3793 return (NULL);
3794 }
3795 return (dest);
3796 } else {
3797 cur--;
3798 state = DTRACE_JSON_COMMA;
3799 break;
3800 }
3801 }
3802
3803 /*
3804 * ERROR: we did not recognise the identifier as one
3805 * of those in the JSON specification.
3806 */
3807 return (NULL);
3808 case DTRACE_JSON_NUMBER:
3809 if (cc == '.') {
3810 *dd++ = cc;
3811 state = DTRACE_JSON_NUMBER_FRAC;
3812 break;
3813 }
3814
3815 if (cc == 'x' || cc == 'X') {
3816 /*
3817 * ERROR: specification explicitly excludes
3818 * hexidecimal or octal numbers.
3819 */
3820 return (NULL);
3821 }
3822
3823 /* FALLTHRU */
3824 case DTRACE_JSON_NUMBER_FRAC:
3825 if (cc == 'e' || cc == 'E') {
3826 *dd++ = cc;
3827 state = DTRACE_JSON_NUMBER_EXP;
3828 break;
3829 }
3830
3831 if (cc == '+' || cc == '-') {
3832 /*
3833 * ERROR: expect sign as part of exponent only.
3834 */
3835 return (NULL);
3836 }
3837 /* FALLTHRU */
3838 case DTRACE_JSON_NUMBER_EXP:
3839 if (isdigit(cc) || cc == '+' || cc == '-') {
3840 *dd++ = cc;
3841 break;
3842 }
3843
3844 *dd = '\0';
3845 dd = dest; /* reset string buffer */
3846 if (found_key) {
3847 if (nelems > 1) {
3848 /*
3849 * ERROR: We expected an object, not
3850 * this number.
3851 */
3852 return (NULL);
3853 }
3854 return (dest);
3855 }
3856
3857 cur--;
3858 state = DTRACE_JSON_COMMA;
3859 break;
3860 case DTRACE_JSON_VALUE:
3861 if (isspace(cc))
3862 break;
3863
3864 if (cc == '{' || cc == '[') {
3865 if (nelems > 1 && found_key) {
3866 in_array = cc == '[' ? B_TRUE : B_FALSE;
3867 /*
3868 * If our element selector directs us
3869 * to descend into this nested object,
3870 * then move to the next selector
3871 * element in the list and restart the
3872 * state machine.
3873 */
3874 while (*elem != '\0')
3875 elem++;
3876 elem++; /* skip the inter-element NUL */
3877 nelems--;
3878 dd = dest;
3879 if (in_array) {
3880 state = DTRACE_JSON_VALUE;
3881 array_pos = 0;
3882 array_elem = dtrace_strtoll(
3883 elem, 10, size);
3884 found_key = array_elem == 0 ?
3885 B_TRUE : B_FALSE;
3886 } else {
3887 found_key = B_FALSE;
3888 state = DTRACE_JSON_OBJECT;
3889 }
3890 break;
3891 }
3892
3893 /*
3894 * Otherwise, we wish to either skip this
3895 * nested object or return it in full.
3896 */
3897 if (cc == '[')
3898 brackets = 1;
3899 else
3900 braces = 1;
3901 *dd++ = cc;
3902 state = DTRACE_JSON_COLLECT_OBJECT;
3903 break;
3904 }
3905
3906 if (cc == '"') {
3907 state = DTRACE_JSON_STRING;
3908 break;
3909 }
3910
3911 if (islower(cc)) {
3912 /*
3913 * Here we deal with true, false and null.
3914 */
3915 *dd++ = cc;
3916 state = DTRACE_JSON_IDENTIFIER;
3917 break;
3918 }
3919
3920 if (cc == '-' || isdigit(cc)) {
3921 *dd++ = cc;
3922 state = DTRACE_JSON_NUMBER;
3923 break;
3924 }
3925
3926 /*
3927 * ERROR: unexpected character at start of value.
3928 */
3929 return (NULL);
3930 case DTRACE_JSON_COLLECT_OBJECT:
3931 if (cc == '\0')
3932 /*
3933 * ERROR: unexpected end of input.
3934 */
3935 return (NULL);
3936
3937 *dd++ = cc;
3938 if (cc == '"') {
3939 collect_object = B_TRUE;
3940 state = DTRACE_JSON_STRING;
3941 break;
3942 }
3943
3944 if (cc == ']') {
3945 if (brackets-- == 0) {
3946 /*
3947 * ERROR: unbalanced brackets.
3948 */
3949 return (NULL);
3950 }
3951 } else if (cc == '}') {
3952 if (braces-- == 0) {
3953 /*
3954 * ERROR: unbalanced braces.
3955 */
3956 return (NULL);
3957 }
3958 } else if (cc == '{') {
3959 braces++;
3960 } else if (cc == '[') {
3961 brackets++;
3962 }
3963
3964 if (brackets == 0 && braces == 0) {
3965 if (found_key) {
3966 *dd = '\0';
3967 return (dest);
3968 }
3969 dd = dest; /* reset string buffer */
3970 state = DTRACE_JSON_COMMA;
3971 }
3972 break;
3973 }
3974 }
3975 return (NULL);
3976}
3977
3978/*
3263 * Emulate the execution of DTrace ID subroutines invoked by the call opcode.
3264 * Notice that we don't bother validating the proper number of arguments or
3265 * their types in the tuple stack. This isn't needed because all argument
3266 * interpretation is safe because of our load safety -- the worst that can
3267 * happen is that a bogus program can obtain bogus results.
3268 */
3269static void
3270dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs,

--- 779 unchanged lines hidden (view full) ---

4050
4051 d[i] = '\0';
4052
4053 mstate->dtms_scratch_ptr += size;
4054 regs[rd] = (uintptr_t)d;
4055 break;
4056 }
4057
3979 * Emulate the execution of DTrace ID subroutines invoked by the call opcode.
3980 * Notice that we don't bother validating the proper number of arguments or
3981 * their types in the tuple stack. This isn't needed because all argument
3982 * interpretation is safe because of our load safety -- the worst that can
3983 * happen is that a bogus program can obtain bogus results.
3984 */
3985static void
3986dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs,

--- 779 unchanged lines hidden (view full) ---

4766
4767 d[i] = '\0';
4768
4769 mstate->dtms_scratch_ptr += size;
4770 regs[rd] = (uintptr_t)d;
4771 break;
4772 }
4773
4774 case DIF_SUBR_JSON: {
4775 uint64_t size = state->dts_options[DTRACEOPT_STRSIZE];
4776 uintptr_t json = tupregs[0].dttk_value;
4777 size_t jsonlen = dtrace_strlen((char *)json, size);
4778 uintptr_t elem = tupregs[1].dttk_value;
4779 size_t elemlen = dtrace_strlen((char *)elem, size);
4780
4781 char *dest = (char *)mstate->dtms_scratch_ptr;
4782 char *elemlist = (char *)mstate->dtms_scratch_ptr + jsonlen + 1;
4783 char *ee = elemlist;
4784 int nelems = 1;
4785 uintptr_t cur;
4786
4787 if (!dtrace_canload(json, jsonlen + 1, mstate, vstate) ||
4788 !dtrace_canload(elem, elemlen + 1, mstate, vstate)) {
4789 regs[rd] = 0;
4790 break;
4791 }
4792
4793 if (!DTRACE_INSCRATCH(mstate, jsonlen + 1 + elemlen + 1)) {
4794 DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
4795 regs[rd] = 0;
4796 break;
4797 }
4798
4799 /*
4800 * Read the element selector and split it up into a packed list
4801 * of strings.
4802 */
4803 for (cur = elem; cur < elem + elemlen; cur++) {
4804 char cc = dtrace_load8(cur);
4805
4806 if (cur == elem && cc == '[') {
4807 /*
4808 * If the first element selector key is
4809 * actually an array index then ignore the
4810 * bracket.
4811 */
4812 continue;
4813 }
4814
4815 if (cc == ']')
4816 continue;
4817
4818 if (cc == '.' || cc == '[') {
4819 nelems++;
4820 cc = '\0';
4821 }
4822
4823 *ee++ = cc;
4824 }
4825 *ee++ = '\0';
4826
4827 if ((regs[rd] = (uintptr_t)dtrace_json(size, json, elemlist,
4828 nelems, dest)) != 0)
4829 mstate->dtms_scratch_ptr += jsonlen + 1;
4830 break;
4831 }
4832
4058 case DIF_SUBR_TOUPPER:
4059 case DIF_SUBR_TOLOWER: {
4060 uintptr_t s = tupregs[0].dttk_value;
4061 uint64_t size = state->dts_options[DTRACEOPT_STRSIZE];
4062 char *dest = (char *)mstate->dtms_scratch_ptr, c;
4063 size_t len = dtrace_strlen((char *)s, size);
4064 char lower, upper, convert;
4065 int64_t i;

--- 293 unchanged lines hidden (view full) ---

4359 if (i < size) {
4360 mstate->dtms_scratch_ptr += i;
4361 regs[rd] = (uintptr_t)d;
4362 }
4363
4364 break;
4365 }
4366
4833 case DIF_SUBR_TOUPPER:
4834 case DIF_SUBR_TOLOWER: {
4835 uintptr_t s = tupregs[0].dttk_value;
4836 uint64_t size = state->dts_options[DTRACEOPT_STRSIZE];
4837 char *dest = (char *)mstate->dtms_scratch_ptr, c;
4838 size_t len = dtrace_strlen((char *)s, size);
4839 char lower, upper, convert;
4840 int64_t i;

--- 293 unchanged lines hidden (view full) ---

5134 if (i < size) {
5135 mstate->dtms_scratch_ptr += i;
5136 regs[rd] = (uintptr_t)d;
5137 }
5138
5139 break;
5140 }
5141
5142 case DIF_SUBR_STRTOLL: {
5143 uintptr_t s = tupregs[0].dttk_value;
5144 uint64_t size = state->dts_options[DTRACEOPT_STRSIZE];
5145 int base = 10;
5146
5147 if (nargs > 1) {
5148 if ((base = tupregs[1].dttk_value) <= 1 ||
5149 base > ('z' - 'a' + 1) + ('9' - '0' + 1)) {
5150 *flags |= CPU_DTRACE_ILLOP;
5151 break;
5152 }
5153 }
5154
5155 if (!dtrace_strcanload(s, size, mstate, vstate)) {
5156 regs[rd] = INT64_MIN;
5157 break;
5158 }
5159
5160 regs[rd] = dtrace_strtoll((char *)s, base, size);
5161 break;
5162 }
5163
4367 case DIF_SUBR_LLTOSTR: {
4368 int64_t i = (int64_t)tupregs[0].dttk_value;
4369 uint64_t val, digit;
4370 uint64_t size = 65; /* enough room for 2^64 in binary */
4371 char *end = (char *)mstate->dtms_scratch_ptr + size - 1;
4372 int base = 10;
4373
4374 if (nargs > 1) {

--- 193 unchanged lines hidden (view full) ---

4568 dest[j] = dtrace_load8(src + i);
4569
4570 dest[j] = '\0';
4571 regs[rd] = (uintptr_t)dest;
4572 mstate->dtms_scratch_ptr += size;
4573 break;
4574 }
4575
5164 case DIF_SUBR_LLTOSTR: {
5165 int64_t i = (int64_t)tupregs[0].dttk_value;
5166 uint64_t val, digit;
5167 uint64_t size = 65; /* enough room for 2^64 in binary */
5168 char *end = (char *)mstate->dtms_scratch_ptr + size - 1;
5169 int base = 10;
5170
5171 if (nargs > 1) {

--- 193 unchanged lines hidden (view full) ---

5365 dest[j] = dtrace_load8(src + i);
5366
5367 dest[j] = '\0';
5368 regs[rd] = (uintptr_t)dest;
5369 mstate->dtms_scratch_ptr += size;
5370 break;
5371 }
5372
5373 case DIF_SUBR_GETF: {
5374 uintptr_t fd = tupregs[0].dttk_value;
5375 struct filedesc *fdp;
5376 file_t *fp;
5377
5378 if (!dtrace_priv_proc(state)) {
5379 regs[rd] = 0;
5380 break;
5381 }
5382 fdp = curproc->p_fd;
5383 FILEDESC_SLOCK(fdp);
5384 fp = fget_locked(fdp, fd);
5385 mstate->dtms_getf = fp;
5386 regs[rd] = (uintptr_t)fp;
5387 FILEDESC_SUNLOCK(fdp);
5388 break;
5389 }
5390
4576 case DIF_SUBR_CLEANPATH: {
4577 char *dest = (char *)mstate->dtms_scratch_ptr, c;
4578 uint64_t size = state->dts_options[DTRACEOPT_STRSIZE];
4579 uintptr_t src = tupregs[0].dttk_value;
4580 int i = 0, j = 0;
5391 case DIF_SUBR_CLEANPATH: {
5392 char *dest = (char *)mstate->dtms_scratch_ptr, c;
5393 uint64_t size = state->dts_options[DTRACEOPT_STRSIZE];
5394 uintptr_t src = tupregs[0].dttk_value;
5395 int i = 0, j = 0;
5396#if defined(sun)
5397 zone_t *z;
5398#endif
4581
4582 if (!dtrace_strcanload(src, size, mstate, vstate)) {
4583 regs[rd] = 0;
4584 break;
4585 }
4586
4587 if (!DTRACE_INSCRATCH(mstate, size)) {
4588 DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);

--- 82 unchanged lines hidden (view full) ---

4671 while (j != 0 && dest[--j] != '/')
4672 continue;
4673
4674 if (c == '\0')
4675 dest[++j] = '/';
4676 } while (c != '\0');
4677
4678 dest[j] = '\0';
5399
5400 if (!dtrace_strcanload(src, size, mstate, vstate)) {
5401 regs[rd] = 0;
5402 break;
5403 }
5404
5405 if (!DTRACE_INSCRATCH(mstate, size)) {
5406 DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);

--- 82 unchanged lines hidden (view full) ---

5489 while (j != 0 && dest[--j] != '/')
5490 continue;
5491
5492 if (c == '\0')
5493 dest[++j] = '/';
5494 } while (c != '\0');
5495
5496 dest[j] = '\0';
5497
5498#if defined(sun)
5499 if (mstate->dtms_getf != NULL &&
5500 !(mstate->dtms_access & DTRACE_ACCESS_KERNEL) &&
5501 (z = state->dts_cred.dcr_cred->cr_zone) != kcred->cr_zone) {
5502 /*
5503 * If we've done a getf() as a part of this ECB and we
5504 * don't have kernel access (and we're not in the global
5505 * zone), check if the path we cleaned up begins with
5506 * the zone's root path, and trim it off if so. Note
5507 * that this is an output cleanliness issue, not a
5508 * security issue: knowing one's zone root path does
5509 * not enable privilege escalation.
5510 */
5511 if (strstr(dest, z->zone_rootpath) == dest)
5512 dest += strlen(z->zone_rootpath) - 1;
5513 }
5514#endif
5515
4679 regs[rd] = (uintptr_t)dest;
4680 mstate->dtms_scratch_ptr += size;
4681 break;
4682 }
4683
4684 case DIF_SUBR_INET_NTOA:
4685 case DIF_SUBR_INET_NTOA6:
4686 case DIF_SUBR_INET_NTOP: {

--- 418 unchanged lines hidden (view full) ---

5105 if (cc_z | (cc_n ^ cc_v))
5106 pc = DIF_INSTR_LABEL(instr);
5107 break;
5108 case DIF_OP_BLEU:
5109 if (cc_c | cc_z)
5110 pc = DIF_INSTR_LABEL(instr);
5111 break;
5112 case DIF_OP_RLDSB:
5516 regs[rd] = (uintptr_t)dest;
5517 mstate->dtms_scratch_ptr += size;
5518 break;
5519 }
5520
5521 case DIF_SUBR_INET_NTOA:
5522 case DIF_SUBR_INET_NTOA6:
5523 case DIF_SUBR_INET_NTOP: {

--- 418 unchanged lines hidden (view full) ---

5942 if (cc_z | (cc_n ^ cc_v))
5943 pc = DIF_INSTR_LABEL(instr);
5944 break;
5945 case DIF_OP_BLEU:
5946 if (cc_c | cc_z)
5947 pc = DIF_INSTR_LABEL(instr);
5948 break;
5949 case DIF_OP_RLDSB:
5113 if (!dtrace_canstore(regs[r1], 1, mstate, vstate)) {
5114 *flags |= CPU_DTRACE_KPRIV;
5115 *illval = regs[r1];
5950 if (!dtrace_canload(regs[r1], 1, mstate, vstate))
5116 break;
5951 break;
5117 }
5118 /*FALLTHROUGH*/
5119 case DIF_OP_LDSB:
5120 regs[rd] = (int8_t)dtrace_load8(regs[r1]);
5121 break;
5122 case DIF_OP_RLDSH:
5952 /*FALLTHROUGH*/
5953 case DIF_OP_LDSB:
5954 regs[rd] = (int8_t)dtrace_load8(regs[r1]);
5955 break;
5956 case DIF_OP_RLDSH:
5123 if (!dtrace_canstore(regs[r1], 2, mstate, vstate)) {
5124 *flags |= CPU_DTRACE_KPRIV;
5125 *illval = regs[r1];
5957 if (!dtrace_canload(regs[r1], 2, mstate, vstate))
5126 break;
5958 break;
5127 }
5128 /*FALLTHROUGH*/
5129 case DIF_OP_LDSH:
5130 regs[rd] = (int16_t)dtrace_load16(regs[r1]);
5131 break;
5132 case DIF_OP_RLDSW:
5959 /*FALLTHROUGH*/
5960 case DIF_OP_LDSH:
5961 regs[rd] = (int16_t)dtrace_load16(regs[r1]);
5962 break;
5963 case DIF_OP_RLDSW:
5133 if (!dtrace_canstore(regs[r1], 4, mstate, vstate)) {
5134 *flags |= CPU_DTRACE_KPRIV;
5135 *illval = regs[r1];
5964 if (!dtrace_canload(regs[r1], 4, mstate, vstate))
5136 break;
5965 break;
5137 }
5138 /*FALLTHROUGH*/
5139 case DIF_OP_LDSW:
5140 regs[rd] = (int32_t)dtrace_load32(regs[r1]);
5141 break;
5142 case DIF_OP_RLDUB:
5966 /*FALLTHROUGH*/
5967 case DIF_OP_LDSW:
5968 regs[rd] = (int32_t)dtrace_load32(regs[r1]);
5969 break;
5970 case DIF_OP_RLDUB:
5143 if (!dtrace_canstore(regs[r1], 1, mstate, vstate)) {
5144 *flags |= CPU_DTRACE_KPRIV;
5145 *illval = regs[r1];
5971 if (!dtrace_canload(regs[r1], 1, mstate, vstate))
5146 break;
5972 break;
5147 }
5148 /*FALLTHROUGH*/
5149 case DIF_OP_LDUB:
5150 regs[rd] = dtrace_load8(regs[r1]);
5151 break;
5152 case DIF_OP_RLDUH:
5973 /*FALLTHROUGH*/
5974 case DIF_OP_LDUB:
5975 regs[rd] = dtrace_load8(regs[r1]);
5976 break;
5977 case DIF_OP_RLDUH:
5153 if (!dtrace_canstore(regs[r1], 2, mstate, vstate)) {
5154 *flags |= CPU_DTRACE_KPRIV;
5155 *illval = regs[r1];
5978 if (!dtrace_canload(regs[r1], 2, mstate, vstate))
5156 break;
5979 break;
5157 }
5158 /*FALLTHROUGH*/
5159 case DIF_OP_LDUH:
5160 regs[rd] = dtrace_load16(regs[r1]);
5161 break;
5162 case DIF_OP_RLDUW:
5980 /*FALLTHROUGH*/
5981 case DIF_OP_LDUH:
5982 regs[rd] = dtrace_load16(regs[r1]);
5983 break;
5984 case DIF_OP_RLDUW:
5163 if (!dtrace_canstore(regs[r1], 4, mstate, vstate)) {
5164 *flags |= CPU_DTRACE_KPRIV;
5165 *illval = regs[r1];
5985 if (!dtrace_canload(regs[r1], 4, mstate, vstate))
5166 break;
5986 break;
5167 }
5168 /*FALLTHROUGH*/
5169 case DIF_OP_LDUW:
5170 regs[rd] = dtrace_load32(regs[r1]);
5171 break;
5172 case DIF_OP_RLDX:
5987 /*FALLTHROUGH*/
5988 case DIF_OP_LDUW:
5989 regs[rd] = dtrace_load32(regs[r1]);
5990 break;
5991 case DIF_OP_RLDX:
5173 if (!dtrace_canstore(regs[r1], 8, mstate, vstate)) {
5174 *flags |= CPU_DTRACE_KPRIV;
5175 *illval = regs[r1];
5992 if (!dtrace_canload(regs[r1], 8, mstate, vstate))
5176 break;
5993 break;
5177 }
5178 /*FALLTHROUGH*/
5179 case DIF_OP_LDX:
5180 regs[rd] = dtrace_load64(regs[r1]);
5181 break;
5182 case DIF_OP_ULDSB:
5994 /*FALLTHROUGH*/
5995 case DIF_OP_LDX:
5996 regs[rd] = dtrace_load64(regs[r1]);
5997 break;
5998 case DIF_OP_ULDSB:
5999 DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
5183 regs[rd] = (int8_t)
5184 dtrace_fuword8((void *)(uintptr_t)regs[r1]);
6000 regs[rd] = (int8_t)
6001 dtrace_fuword8((void *)(uintptr_t)regs[r1]);
6002 DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
5185 break;
5186 case DIF_OP_ULDSH:
6003 break;
6004 case DIF_OP_ULDSH:
6005 DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
5187 regs[rd] = (int16_t)
5188 dtrace_fuword16((void *)(uintptr_t)regs[r1]);
6006 regs[rd] = (int16_t)
6007 dtrace_fuword16((void *)(uintptr_t)regs[r1]);
6008 DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
5189 break;
5190 case DIF_OP_ULDSW:
6009 break;
6010 case DIF_OP_ULDSW:
6011 DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
5191 regs[rd] = (int32_t)
5192 dtrace_fuword32((void *)(uintptr_t)regs[r1]);
6012 regs[rd] = (int32_t)
6013 dtrace_fuword32((void *)(uintptr_t)regs[r1]);
6014 DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
5193 break;
5194 case DIF_OP_ULDUB:
6015 break;
6016 case DIF_OP_ULDUB:
6017 DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
5195 regs[rd] =
5196 dtrace_fuword8((void *)(uintptr_t)regs[r1]);
6018 regs[rd] =
6019 dtrace_fuword8((void *)(uintptr_t)regs[r1]);
6020 DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
5197 break;
5198 case DIF_OP_ULDUH:
6021 break;
6022 case DIF_OP_ULDUH:
6023 DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
5199 regs[rd] =
5200 dtrace_fuword16((void *)(uintptr_t)regs[r1]);
6024 regs[rd] =
6025 dtrace_fuword16((void *)(uintptr_t)regs[r1]);
6026 DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
5201 break;
5202 case DIF_OP_ULDUW:
6027 break;
6028 case DIF_OP_ULDUW:
6029 DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
5203 regs[rd] =
5204 dtrace_fuword32((void *)(uintptr_t)regs[r1]);
6030 regs[rd] =
6031 dtrace_fuword32((void *)(uintptr_t)regs[r1]);
6032 DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
5205 break;
5206 case DIF_OP_ULDX:
6033 break;
6034 case DIF_OP_ULDX:
6035 DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
5207 regs[rd] =
5208 dtrace_fuword64((void *)(uintptr_t)regs[r1]);
6036 regs[rd] =
6037 dtrace_fuword64((void *)(uintptr_t)regs[r1]);
6038 DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
5209 break;
5210 case DIF_OP_RET:
5211 rval = regs[rd];
5212 pc = textlen;
5213 break;
5214 case DIF_OP_NOP:
5215 break;
5216 case DIF_OP_SETX:

--- 665 unchanged lines hidden (view full) ---

5882 cpu_t *cpu = CPU;
5883#else
5884 cpu_t *cpu = &solaris_cpu[curcpu];
5885#endif
5886
5887 if (dtrace_destructive_disallow)
5888 return;
5889
6039 break;
6040 case DIF_OP_RET:
6041 rval = regs[rd];
6042 pc = textlen;
6043 break;
6044 case DIF_OP_NOP:
6045 break;
6046 case DIF_OP_SETX:

--- 665 unchanged lines hidden (view full) ---

6712 cpu_t *cpu = CPU;
6713#else
6714 cpu_t *cpu = &solaris_cpu[curcpu];
6715#endif
6716
6717 if (dtrace_destructive_disallow)
6718 return;
6719
5890 flags = (volatile uint16_t *)&cpu_core[cpu->cpu_id].cpuc_dtrace_flags;
6720 flags = (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags;
5891
5892 now = dtrace_gethrtime();
5893
5894 if (now - cpu->cpu_dtrace_chillmark > dtrace_chill_interval) {
5895 /*
5896 * We need to advance the mark to the current time.
5897 */
5898 cpu->cpu_dtrace_chillmark = now;

--- 131 unchanged lines hidden (view full) ---

6030
6031 while (offs < strsize)
6032 str[offs++] = '\0';
6033
6034out:
6035 mstate->dtms_scratch_ptr = old;
6036}
6037
6721
6722 now = dtrace_gethrtime();
6723
6724 if (now - cpu->cpu_dtrace_chillmark > dtrace_chill_interval) {
6725 /*
6726 * We need to advance the mark to the current time.
6727 */
6728 cpu->cpu_dtrace_chillmark = now;

--- 131 unchanged lines hidden (view full) ---

6860
6861 while (offs < strsize)
6862 str[offs++] = '\0';
6863
6864out:
6865 mstate->dtms_scratch_ptr = old;
6866}
6867
6868static void
6869dtrace_store_by_ref(dtrace_difo_t *dp, caddr_t tomax, size_t size,
6870 size_t *valoffsp, uint64_t *valp, uint64_t end, int intuple, int dtkind)
6871{
6872 volatile uint16_t *flags;
6873 uint64_t val = *valp;
6874 size_t valoffs = *valoffsp;
6875
6876 flags = (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags;
6877 ASSERT(dtkind == DIF_TF_BYREF || dtkind == DIF_TF_BYUREF);
6878
6879 /*
6880 * If this is a string, we're going to only load until we find the zero
6881 * byte -- after which we'll store zero bytes.
6882 */
6883 if (dp->dtdo_rtype.dtdt_kind == DIF_TYPE_STRING) {
6884 char c = '\0' + 1;
6885 size_t s;
6886
6887 for (s = 0; s < size; s++) {
6888 if (c != '\0' && dtkind == DIF_TF_BYREF) {
6889 c = dtrace_load8(val++);
6890 } else if (c != '\0' && dtkind == DIF_TF_BYUREF) {
6891 DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
6892 c = dtrace_fuword8((void *)(uintptr_t)val++);
6893 DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
6894 if (*flags & CPU_DTRACE_FAULT)
6895 break;
6896 }
6897
6898 DTRACE_STORE(uint8_t, tomax, valoffs++, c);
6899
6900 if (c == '\0' && intuple)
6901 break;
6902 }
6903 } else {
6904 uint8_t c;
6905 while (valoffs < end) {
6906 if (dtkind == DIF_TF_BYREF) {
6907 c = dtrace_load8(val++);
6908 } else if (dtkind == DIF_TF_BYUREF) {
6909 DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
6910 c = dtrace_fuword8((void *)(uintptr_t)val++);
6911 DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
6912 if (*flags & CPU_DTRACE_FAULT)
6913 break;
6914 }
6915
6916 DTRACE_STORE(uint8_t, tomax,
6917 valoffs++, c);
6918 }
6919 }
6920
6921 *valp = val;
6922 *valoffsp = valoffs;
6923}
6924
6038/*
6039 * If you're looking for the epicenter of DTrace, you just found it. This
6040 * is the function called by the provider to fire a probe -- from which all
6041 * subsequent probe-context DTrace activity emanates.
6042 */
6043void
6044dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1,
6045 uintptr_t arg2, uintptr_t arg3, uintptr_t arg4)

--- 86 unchanged lines hidden (view full) ---

6132 * the action processing loop.) However, it must be declared
6133 * out of that scope because in the case of DIF expression
6134 * arguments to aggregating actions, one iteration of the
6135 * action loop will use the last iteration's value.
6136 */
6137 uint64_t val = 0;
6138
6139 mstate.dtms_present = DTRACE_MSTATE_ARGS | DTRACE_MSTATE_PROBE;
6925/*
6926 * If you're looking for the epicenter of DTrace, you just found it. This
6927 * is the function called by the provider to fire a probe -- from which all
6928 * subsequent probe-context DTrace activity emanates.
6929 */
6930void
6931dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1,
6932 uintptr_t arg2, uintptr_t arg3, uintptr_t arg4)

--- 86 unchanged lines hidden (view full) ---

7019 * the action processing loop.) However, it must be declared
7020 * out of that scope because in the case of DIF expression
7021 * arguments to aggregating actions, one iteration of the
7022 * action loop will use the last iteration's value.
7023 */
7024 uint64_t val = 0;
7025
7026 mstate.dtms_present = DTRACE_MSTATE_ARGS | DTRACE_MSTATE_PROBE;
7027 mstate.dtms_getf = NULL;
7028
6140 *flags &= ~CPU_DTRACE_ERROR;
6141
6142 if (prov == dtrace_provider) {
6143 /*
6144 * If dtrace itself is the provider of this probe,
6145 * we're only going to continue processing the ECB if
6146 * arg0 (the dtrace_state_t) is equal to the ECB's
6147 * creating state. (This prevents disjoint consumers

--- 517 unchanged lines hidden (view full) ---

6665
6666 break;
6667 }
6668
6669 default:
6670 ASSERT(0);
6671 }
6672
7029 *flags &= ~CPU_DTRACE_ERROR;
7030
7031 if (prov == dtrace_provider) {
7032 /*
7033 * If dtrace itself is the provider of this probe,
7034 * we're only going to continue processing the ECB if
7035 * arg0 (the dtrace_state_t) is equal to the ECB's
7036 * creating state. (This prevents disjoint consumers

--- 517 unchanged lines hidden (view full) ---

7554
7555 break;
7556 }
7557
7558 default:
7559 ASSERT(0);
7560 }
7561
6673 if (dp->dtdo_rtype.dtdt_flags & DIF_TF_BYREF) {
7562 if (dp->dtdo_rtype.dtdt_flags & DIF_TF_BYREF ||
7563 dp->dtdo_rtype.dtdt_flags & DIF_TF_BYUREF) {
6674 uintptr_t end = valoffs + size;
6675
6676 if (tracememsize != 0 &&
6677 valoffs + tracememsize < end) {
6678 end = valoffs + tracememsize;
6679 tracememsize = 0;
6680 }
6681
7564 uintptr_t end = valoffs + size;
7565
7566 if (tracememsize != 0 &&
7567 valoffs + tracememsize < end) {
7568 end = valoffs + tracememsize;
7569 tracememsize = 0;
7570 }
7571
6682 if (!dtrace_vcanload((void *)(uintptr_t)val,
7572 if (dp->dtdo_rtype.dtdt_flags & DIF_TF_BYREF &&
7573 !dtrace_vcanload((void *)(uintptr_t)val,
6683 &dp->dtdo_rtype, &mstate, vstate))
6684 continue;
6685
7574 &dp->dtdo_rtype, &mstate, vstate))
7575 continue;
7576
6686 /*
6687 * If this is a string, we're going to only
6688 * load until we find the zero byte -- after
6689 * which we'll store zero bytes.
6690 */
6691 if (dp->dtdo_rtype.dtdt_kind ==
6692 DIF_TYPE_STRING) {
6693 char c = '\0' + 1;
6694 int intuple = act->dta_intuple;
6695 size_t s;
6696
6697 for (s = 0; s < size; s++) {
6698 if (c != '\0')
6699 c = dtrace_load8(val++);
6700
6701 DTRACE_STORE(uint8_t, tomax,
6702 valoffs++, c);
6703
6704 if (c == '\0' && intuple)
6705 break;
6706 }
6707
6708 continue;
6709 }
6710
6711 while (valoffs < end) {
6712 DTRACE_STORE(uint8_t, tomax, valoffs++,
6713 dtrace_load8(val++));
6714 }
6715
7577 dtrace_store_by_ref(dp, tomax, size, &valoffs,
7578 &val, end, act->dta_intuple,
7579 dp->dtdo_rtype.dtdt_flags & DIF_TF_BYREF ?
7580 DIF_TF_BYREF: DIF_TF_BYUREF);
6716 continue;
6717 }
6718
6719 switch (size) {
6720 case 0:
6721 break;
6722
6723 case sizeof (uint8_t):

--- 2081 unchanged lines hidden (view full) ---

8805 err += efunc(pc, "invalid register %u\n", rd);
8806 if (rd == 0)
8807 err += efunc(pc, "cannot write to %r0\n");
8808
8809 if (subr == DIF_SUBR_COPYOUT ||
8810 subr == DIF_SUBR_COPYOUTSTR) {
8811 dp->dtdo_destructive = 1;
8812 }
7581 continue;
7582 }
7583
7584 switch (size) {
7585 case 0:
7586 break;
7587
7588 case sizeof (uint8_t):

--- 2081 unchanged lines hidden (view full) ---

9670 err += efunc(pc, "invalid register %u\n", rd);
9671 if (rd == 0)
9672 err += efunc(pc, "cannot write to %r0\n");
9673
9674 if (subr == DIF_SUBR_COPYOUT ||
9675 subr == DIF_SUBR_COPYOUTSTR) {
9676 dp->dtdo_destructive = 1;
9677 }
9678
9679 if (subr == DIF_SUBR_GETF) {
9680 /*
9681 * If we have a getf() we need to record that
9682 * in our state. Note that our state can be
9683 * NULL if this is a helper -- but in that
9684 * case, the call to getf() is itself illegal,
9685 * and will be caught (slightly later) when
9686 * the helper is validated.
9687 */
9688 if (vstate->dtvs_state != NULL)
9689 vstate->dtvs_state->dts_getf++;
9690 }
9691
8813 break;
8814 case DIF_OP_PUSHTR:
8815 if (type != DIF_TYPE_STRING && type != DIF_TYPE_CTF)
8816 err += efunc(pc, "invalid ref type %u\n", type);
8817 if (r2 >= nregs)
8818 err += efunc(pc, "invalid register %u\n", r2);
8819 if (rs >= nregs)
8820 err += efunc(pc, "invalid register %u\n", rs);

--- 13 unchanged lines hidden (view full) ---

8834 }
8835
8836 if (dp->dtdo_len != 0 &&
8837 DIF_INSTR_OP(dp->dtdo_buf[dp->dtdo_len - 1]) != DIF_OP_RET) {
8838 err += efunc(dp->dtdo_len - 1,
8839 "expected 'ret' as last DIF instruction\n");
8840 }
8841
9692 break;
9693 case DIF_OP_PUSHTR:
9694 if (type != DIF_TYPE_STRING && type != DIF_TYPE_CTF)
9695 err += efunc(pc, "invalid ref type %u\n", type);
9696 if (r2 >= nregs)
9697 err += efunc(pc, "invalid register %u\n", r2);
9698 if (rs >= nregs)
9699 err += efunc(pc, "invalid register %u\n", rs);

--- 13 unchanged lines hidden (view full) ---

9713 }
9714
9715 if (dp->dtdo_len != 0 &&
9716 DIF_INSTR_OP(dp->dtdo_buf[dp->dtdo_len - 1]) != DIF_OP_RET) {
9717 err += efunc(dp->dtdo_len - 1,
9718 "expected 'ret' as last DIF instruction\n");
9719 }
9720
8842 if (!(dp->dtdo_rtype.dtdt_flags & DIF_TF_BYREF)) {
9721 if (!(dp->dtdo_rtype.dtdt_flags & (DIF_TF_BYREF | DIF_TF_BYUREF))) {
8843 /*
8844 * If we're not returning by reference, the size must be either
8845 * 0 or the size of one of the base types.
8846 */
8847 switch (dp->dtdo_rtype.dtdt_size) {
8848 case 0:
8849 case sizeof (uint8_t):
8850 case sizeof (uint16_t):

--- 233 unchanged lines hidden (view full) ---

9084 subr == DIF_SUBR_BCOPY ||
9085 subr == DIF_SUBR_COPYIN ||
9086 subr == DIF_SUBR_COPYINTO ||
9087 subr == DIF_SUBR_COPYINSTR ||
9088 subr == DIF_SUBR_INDEX ||
9089 subr == DIF_SUBR_INET_NTOA ||
9090 subr == DIF_SUBR_INET_NTOA6 ||
9091 subr == DIF_SUBR_INET_NTOP ||
9722 /*
9723 * If we're not returning by reference, the size must be either
9724 * 0 or the size of one of the base types.
9725 */
9726 switch (dp->dtdo_rtype.dtdt_size) {
9727 case 0:
9728 case sizeof (uint8_t):
9729 case sizeof (uint16_t):

--- 233 unchanged lines hidden (view full) ---

9963 subr == DIF_SUBR_BCOPY ||
9964 subr == DIF_SUBR_COPYIN ||
9965 subr == DIF_SUBR_COPYINTO ||
9966 subr == DIF_SUBR_COPYINSTR ||
9967 subr == DIF_SUBR_INDEX ||
9968 subr == DIF_SUBR_INET_NTOA ||
9969 subr == DIF_SUBR_INET_NTOA6 ||
9970 subr == DIF_SUBR_INET_NTOP ||
9971 subr == DIF_SUBR_JSON ||
9092 subr == DIF_SUBR_LLTOSTR ||
9972 subr == DIF_SUBR_LLTOSTR ||
9973 subr == DIF_SUBR_STRTOLL ||
9093 subr == DIF_SUBR_RINDEX ||
9094 subr == DIF_SUBR_STRCHR ||
9095 subr == DIF_SUBR_STRJOIN ||
9096 subr == DIF_SUBR_STRRCHR ||
9097 subr == DIF_SUBR_STRSTR ||
9098 subr == DIF_SUBR_HTONS ||
9099 subr == DIF_SUBR_HTONL ||
9100 subr == DIF_SUBR_HTONLL ||

--- 4628 unchanged lines hidden (view full) ---

13729 callout_reset(&state->dts_cleaner, hz * opt[DTRACEOPT_CLEANRATE] / NANOSEC,
13730 dtrace_state_clean, state);
13731 callout_reset(&state->dts_deadman, hz * dtrace_deadman_interval / NANOSEC,
13732 dtrace_state_deadman, state);
13733#endif
13734
13735 state->dts_activity = DTRACE_ACTIVITY_WARMUP;
13736
9974 subr == DIF_SUBR_RINDEX ||
9975 subr == DIF_SUBR_STRCHR ||
9976 subr == DIF_SUBR_STRJOIN ||
9977 subr == DIF_SUBR_STRRCHR ||
9978 subr == DIF_SUBR_STRSTR ||
9979 subr == DIF_SUBR_HTONS ||
9980 subr == DIF_SUBR_HTONL ||
9981 subr == DIF_SUBR_HTONLL ||

--- 4628 unchanged lines hidden (view full) ---

14610 callout_reset(&state->dts_cleaner, hz * opt[DTRACEOPT_CLEANRATE] / NANOSEC,
14611 dtrace_state_clean, state);
14612 callout_reset(&state->dts_deadman, hz * dtrace_deadman_interval / NANOSEC,
14613 dtrace_state_deadman, state);
14614#endif
14615
14616 state->dts_activity = DTRACE_ACTIVITY_WARMUP;
14617
14618#if defined(sun)
14619 if (state->dts_getf != 0 &&
14620 !(state->dts_cred.dcr_visible & DTRACE_CRV_KERNEL)) {
14621 /*
14622 * We don't have kernel privs but we have at least one call
14623 * to getf(); we need to bump our zone's count, and (if
14624 * this is the first enabling to have an unprivileged call
14625 * to getf()) we need to hook into closef().
14626 */
14627 state->dts_cred.dcr_cred->cr_zone->zone_dtrace_getf++;
14628
14629 if (dtrace_getf++ == 0) {
14630 ASSERT(dtrace_closef == NULL);
14631 dtrace_closef = dtrace_getf_barrier;
14632 }
14633 }
14634#endif
14635
13737 /*
13738 * Now it's time to actually fire the BEGIN probe. We need to disable
13739 * interrupts here both to record the CPU on which we fired the BEGIN
13740 * probe (the data from this CPU will be processed first at user
13741 * level) and to manually activate the buffer for this CPU.
13742 */
13743 cookie = dtrace_interrupt_disable();
13744 *cpu = curcpu;

--- 100 unchanged lines hidden (view full) ---

13845 *cpu = curcpu;
13846 dtrace_probe(dtrace_probeid_end,
13847 (uint64_t)(uintptr_t)state, 0, 0, 0, 0);
13848 dtrace_interrupt_enable(cookie);
13849
13850 state->dts_activity = DTRACE_ACTIVITY_STOPPED;
13851 dtrace_sync();
13852
14636 /*
14637 * Now it's time to actually fire the BEGIN probe. We need to disable
14638 * interrupts here both to record the CPU on which we fired the BEGIN
14639 * probe (the data from this CPU will be processed first at user
14640 * level) and to manually activate the buffer for this CPU.
14641 */
14642 cookie = dtrace_interrupt_disable();
14643 *cpu = curcpu;

--- 100 unchanged lines hidden (view full) ---

14744 *cpu = curcpu;
14745 dtrace_probe(dtrace_probeid_end,
14746 (uint64_t)(uintptr_t)state, 0, 0, 0, 0);
14747 dtrace_interrupt_enable(cookie);
14748
14749 state->dts_activity = DTRACE_ACTIVITY_STOPPED;
14750 dtrace_sync();
14751
14752#if defined(sun)
14753 if (state->dts_getf != 0 &&
14754 !(state->dts_cred.dcr_visible & DTRACE_CRV_KERNEL)) {
14755 /*
14756 * We don't have kernel privs but we have at least one call
14757 * to getf(); we need to lower our zone's count, and (if
14758 * this is the last enabling to have an unprivileged call
14759 * to getf()) we need to clear the closef() hook.
14760 */
14761 ASSERT(state->dts_cred.dcr_cred->cr_zone->zone_dtrace_getf > 0);
14762 ASSERT(dtrace_closef == dtrace_getf_barrier);
14763 ASSERT(dtrace_getf > 0);
14764
14765 state->dts_cred.dcr_cred->cr_zone->zone_dtrace_getf--;
14766
14767 if (--dtrace_getf == 0)
14768 dtrace_closef = NULL;
14769 }
14770#endif
14771
13853 return (0);
13854}
13855
13856static int
13857dtrace_state_option(dtrace_state_t *state, dtrace_optid_t option,
13858 dtrace_optval_t val)
13859{
13860 ASSERT(MUTEX_HELD(&dtrace_lock));

--- 1653 unchanged lines hidden (view full) ---

15514 ASSERT(dtrace_toxrange[dtrace_toxranges].dtt_base == 0);
15515 ASSERT(dtrace_toxrange[dtrace_toxranges].dtt_limit == 0);
15516
15517 dtrace_toxrange[dtrace_toxranges].dtt_base = base;
15518 dtrace_toxrange[dtrace_toxranges].dtt_limit = limit;
15519 dtrace_toxranges++;
15520}
15521
14772 return (0);
14773}
14774
14775static int
14776dtrace_state_option(dtrace_state_t *state, dtrace_optid_t option,
14777 dtrace_optval_t val)
14778{
14779 ASSERT(MUTEX_HELD(&dtrace_lock));

--- 1653 unchanged lines hidden (view full) ---

16433 ASSERT(dtrace_toxrange[dtrace_toxranges].dtt_base == 0);
16434 ASSERT(dtrace_toxrange[dtrace_toxranges].dtt_limit == 0);
16435
16436 dtrace_toxrange[dtrace_toxranges].dtt_base = base;
16437 dtrace_toxrange[dtrace_toxranges].dtt_limit = limit;
16438 dtrace_toxranges++;
16439}
16440
16441static void
16442dtrace_getf_barrier()
16443{
16444#if defined(sun)
16445 /*
16446 * When we have unprivileged (that is, non-DTRACE_CRV_KERNEL) enablings
16447 * that contain calls to getf(), this routine will be called on every
16448 * closef() before either the underlying vnode is released or the
16449 * file_t itself is freed. By the time we are here, it is essential
16450 * that the file_t can no longer be accessed from a call to getf()
16451 * in probe context -- that assures that a dtrace_sync() can be used
16452 * to clear out any enablings referring to the old structures.
16453 */
16454 if (curthread->t_procp->p_zone->zone_dtrace_getf != 0 ||
16455 kcred->cr_zone->zone_dtrace_getf != 0)
16456 dtrace_sync();
16457#endif
16458}
16459
15522/*
15523 * DTrace Driver Cookbook Functions
15524 */
15525#if defined(sun)
15526/*ARGSUSED*/
15527static int
15528dtrace_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
15529{

--- 1247 unchanged lines hidden (view full) ---

16777 dtrace_helpers_fork = NULL;
16778 dtrace_cpustart_init = NULL;
16779 dtrace_cpustart_fini = NULL;
16780 dtrace_debugger_init = NULL;
16781 dtrace_debugger_fini = NULL;
16782 dtrace_modload = NULL;
16783 dtrace_modunload = NULL;
16784
16460/*
16461 * DTrace Driver Cookbook Functions
16462 */
16463#if defined(sun)
16464/*ARGSUSED*/
16465static int
16466dtrace_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
16467{

--- 1247 unchanged lines hidden (view full) ---

17715 dtrace_helpers_fork = NULL;
17716 dtrace_cpustart_init = NULL;
17717 dtrace_cpustart_fini = NULL;
17718 dtrace_debugger_init = NULL;
17719 dtrace_debugger_fini = NULL;
17720 dtrace_modload = NULL;
17721 dtrace_modunload = NULL;
17722
17723 ASSERT(dtrace_getf == 0);
17724 ASSERT(dtrace_closef == NULL);
17725
16785 mutex_exit(&cpu_lock);
16786
16787 if (dtrace_helptrace_enabled) {
16788 kmem_free(dtrace_helptrace_buffer, dtrace_helptrace_bufsize);
16789 dtrace_helptrace_buffer = NULL;
16790 }
16791
16792 kmem_free(dtrace_probes, dtrace_nprobes * sizeof (dtrace_probe_t *));

--- 191 unchanged lines hidden ---
17726 mutex_exit(&cpu_lock);
17727
17728 if (dtrace_helptrace_enabled) {
17729 kmem_free(dtrace_helptrace_buffer, dtrace_helptrace_bufsize);
17730 dtrace_helptrace_buffer = NULL;
17731 }
17732
17733 kmem_free(dtrace_probes, dtrace_nprobes * sizeof (dtrace_probe_t *));

--- 191 unchanged lines hidden ---