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 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> |
112#include "strtolctype.h" |
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 */ |
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) \ |
469 ((testaddr) - (uintptr_t)(baseaddr) < (basesz) && \ 470 (testaddr) + (testsz) - (uintptr_t)(baseaddr) <= (basesz) && \ |
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); |
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 */ |
725 if (DTRACE_INRANGE(addr, sz, vstate->dtvs_dynvars.dtds_base, |
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; |
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 */ |
810 if (DTRACE_INRANGE(addr, sz, mstate->dtms_difo->dtdo_strtab, |
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 |
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/* |
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 |
1339 if ((cr = CRED()) != NULL && s_cr->cr_zone == cr->cr_zone) |
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/* |
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: |
3165 if (!dtrace_priv_proc(state)) |
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 |
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/* |
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 |
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 |
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 |
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 |
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 |
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: |
5950 if (!dtrace_canload(regs[r1], 1, mstate, vstate)) |
5951 break; |
5952 /*FALLTHROUGH*/ 5953 case DIF_OP_LDSB: 5954 regs[rd] = (int8_t)dtrace_load8(regs[r1]); 5955 break; 5956 case DIF_OP_RLDSH: |
5957 if (!dtrace_canload(regs[r1], 2, mstate, vstate)) |
5958 break; |
5959 /*FALLTHROUGH*/ 5960 case DIF_OP_LDSH: 5961 regs[rd] = (int16_t)dtrace_load16(regs[r1]); 5962 break; 5963 case DIF_OP_RLDSW: |
5964 if (!dtrace_canload(regs[r1], 4, mstate, vstate)) |
5965 break; |
5966 /*FALLTHROUGH*/ 5967 case DIF_OP_LDSW: 5968 regs[rd] = (int32_t)dtrace_load32(regs[r1]); 5969 break; 5970 case DIF_OP_RLDUB: |
5971 if (!dtrace_canload(regs[r1], 1, mstate, vstate)) |
5972 break; |
5973 /*FALLTHROUGH*/ 5974 case DIF_OP_LDUB: 5975 regs[rd] = dtrace_load8(regs[r1]); 5976 break; 5977 case DIF_OP_RLDUH: |
5978 if (!dtrace_canload(regs[r1], 2, mstate, vstate)) |
5979 break; |
5980 /*FALLTHROUGH*/ 5981 case DIF_OP_LDUH: 5982 regs[rd] = dtrace_load16(regs[r1]); 5983 break; 5984 case DIF_OP_RLDUW: |
5985 if (!dtrace_canload(regs[r1], 4, mstate, vstate)) |
5986 break; |
5987 /*FALLTHROUGH*/ 5988 case DIF_OP_LDUW: 5989 regs[rd] = dtrace_load32(regs[r1]); 5990 break; 5991 case DIF_OP_RLDX: |
5992 if (!dtrace_canload(regs[r1], 8, mstate, vstate)) |
5993 break; |
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); |
6000 regs[rd] = (int8_t) 6001 dtrace_fuword8((void *)(uintptr_t)regs[r1]); |
6002 DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT); |
6003 break; 6004 case DIF_OP_ULDSH: |
6005 DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT); |
6006 regs[rd] = (int16_t) 6007 dtrace_fuword16((void *)(uintptr_t)regs[r1]); |
6008 DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT); |
6009 break; 6010 case DIF_OP_ULDSW: |
6011 DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT); |
6012 regs[rd] = (int32_t) 6013 dtrace_fuword32((void *)(uintptr_t)regs[r1]); |
6014 DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT); |
6015 break; 6016 case DIF_OP_ULDUB: |
6017 DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT); |
6018 regs[rd] = 6019 dtrace_fuword8((void *)(uintptr_t)regs[r1]); |
6020 DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT); |
6021 break; 6022 case DIF_OP_ULDUH: |
6023 DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT); |
6024 regs[rd] = 6025 dtrace_fuword16((void *)(uintptr_t)regs[r1]); |
6026 DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT); |
6027 break; 6028 case DIF_OP_ULDUW: |
6029 DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT); |
6030 regs[rd] = 6031 dtrace_fuword32((void *)(uintptr_t)regs[r1]); |
6032 DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT); |
6033 break; 6034 case DIF_OP_ULDX: |
6035 DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT); |
6036 regs[rd] = 6037 dtrace_fuword64((void *)(uintptr_t)regs[r1]); |
6038 DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT); |
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 |
6720 flags = (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags; |
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 |
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 |
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 |
7562 if (dp->dtdo_rtype.dtdt_flags & DIF_TF_BYREF || 7563 dp->dtdo_rtype.dtdt_flags & DIF_TF_BYUREF) { |
7564 uintptr_t end = valoffs + size; 7565 7566 if (tracememsize != 0 && 7567 valoffs + tracememsize < end) { 7568 end = valoffs + tracememsize; 7569 tracememsize = 0; 7570 } 7571 |
7572 if (dp->dtdo_rtype.dtdt_flags & DIF_TF_BYREF && 7573 !dtrace_vcanload((void *)(uintptr_t)val, |
7574 &dp->dtdo_rtype, &mstate, vstate)) 7575 continue; 7576 |
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); |
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 |
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 |
9721 if (!(dp->dtdo_rtype.dtdt_flags & (DIF_TF_BYREF | DIF_TF_BYUREF))) { |
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 || |
9972 subr == DIF_SUBR_LLTOSTR || |
9973 subr == DIF_SUBR_STRTOLL || |
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 |
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 |
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 |
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 |
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 --- |