Print this page
2915 DTrace in a zone should see "cpu", "curpsinfo", et al

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/dtrace/dtrace.c
          +++ new/usr/src/uts/common/dtrace/dtrace.c
↓ open down ↓ 13 lines elided ↑ open up ↑
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  24      - * Copyright (c) 2011, Joyent, Inc. All rights reserved.
       24 + * Copyright (c) 2012, Joyent, Inc. All rights reserved.
  25   25   */
  26   26  
  27   27  /*
  28   28   * DTrace - Dynamic Tracing for Solaris
  29   29   *
  30   30   * This is the implementation of the Solaris Dynamic Tracing framework
  31   31   * (DTrace).  The user-visible interface to DTrace is described at length in
  32   32   * the "Solaris Dynamic Tracing Guide".  The interfaces between the libdtrace
  33   33   * library, the in-kernel DTrace framework, and the DTrace providers are
  34   34   * described in the block comments in the <sys/dtrace.h> header file.  The
↓ open down ↓ 330 lines elided ↑ open up ↑
 365  365  #define DTRACE_ALIGNCHECK(addr, size, flags)
 366  366  #endif
 367  367  
 368  368  /*
 369  369   * Test whether a range of memory starting at testaddr of size testsz falls
 370  370   * within the range of memory described by addr, sz.  We take care to avoid
 371  371   * problems with overflow and underflow of the unsigned quantities, and
 372  372   * disallow all negative sizes.  Ranges of size 0 are allowed.
 373  373   */
 374  374  #define DTRACE_INRANGE(testaddr, testsz, baseaddr, basesz) \
 375      -        ((testaddr) - (baseaddr) < (basesz) && \
 376      -        (testaddr) + (testsz) - (baseaddr) <= (basesz) && \
      375 +        ((testaddr) - (uintptr_t)(baseaddr) < (basesz) && \
      376 +        (testaddr) + (testsz) - (uintptr_t)(baseaddr) <= (basesz) && \
 377  377          (testaddr) + (testsz) >= (testaddr))
 378  378  
 379  379  /*
 380  380   * Test whether alloc_sz bytes will fit in the scratch region.  We isolate
 381  381   * alloc_sz on the righthand side of the comparison in order to avoid overflow
 382  382   * or underflow in the comparison with it.  This is simpler than the INRANGE
 383  383   * check above, because we know that the dtms_scratch_ptr is valid in the
 384  384   * range.  Allocations of size zero are allowed.
 385  385   */
 386  386  #define DTRACE_INSCRATCH(mstate, alloc_sz) \
↓ open down ↓ 80 lines elided ↑ open up ↑
 467  467      dtrace_state_t *, uint64_t, uint64_t);
 468  468  static dtrace_helpers_t *dtrace_helpers_create(proc_t *);
 469  469  static void dtrace_buffer_drop(dtrace_buffer_t *);
 470  470  static int dtrace_buffer_consumed(dtrace_buffer_t *, hrtime_t when);
 471  471  static intptr_t dtrace_buffer_reserve(dtrace_buffer_t *, size_t, size_t,
 472  472      dtrace_state_t *, dtrace_mstate_t *);
 473  473  static int dtrace_state_option(dtrace_state_t *, dtrace_optid_t,
 474  474      dtrace_optval_t);
 475  475  static int dtrace_ecb_create_enable(dtrace_probe_t *, void *);
 476  476  static void dtrace_helper_provider_destroy(dtrace_helper_provider_t *);
      477 +static int dtrace_priv_proc(dtrace_state_t *, dtrace_mstate_t *);
 477  478  
 478  479  /*
 479  480   * DTrace Probe Context Functions
 480  481   *
 481  482   * These functions are called from probe context.  Because probe context is
 482  483   * any context in which C may be called, arbitrarily locks may be held,
 483  484   * interrupts may be disabled, we may be in arbitrary dispatched state, etc.
 484  485   * As a result, functions called from probe context may only call other DTrace
 485  486   * support functions -- they may not interact at all with the system at large.
 486  487   * (Note that the ASSERT macro is made probe-context safe by redefining it in
↓ open down ↓ 124 lines elided ↑ open up ↑
 611  612           */
 612  613          if (DTRACE_INRANGE(addr, sz, mstate->dtms_scratch_base,
 613  614              mstate->dtms_scratch_size))
 614  615                  return (1);
 615  616  
 616  617          /*
 617  618           * Now check to see if it's a dynamic variable.  This check will pick
 618  619           * up both thread-local variables and any global dynamically-allocated
 619  620           * variables.
 620  621           */
 621      -        if (DTRACE_INRANGE(addr, sz, (uintptr_t)vstate->dtvs_dynvars.dtds_base,
      622 +        if (DTRACE_INRANGE(addr, sz, vstate->dtvs_dynvars.dtds_base,
 622  623              vstate->dtvs_dynvars.dtds_size)) {
 623  624                  dtrace_dstate_t *dstate = &vstate->dtvs_dynvars;
 624  625                  uintptr_t base = (uintptr_t)dstate->dtds_base +
 625  626                      (dstate->dtds_hashsize * sizeof (dtrace_dynhash_t));
 626  627                  uintptr_t chunkoffs;
 627  628  
 628  629                  /*
 629  630                   * Before we assume that we can store here, we need to make
 630  631                   * sure that it isn't in our metadata -- storing to our
 631  632                   * dynamic variable metadata would corrupt our state.  For
↓ open down ↓ 63 lines elided ↑ open up ↑
 695  696  
 696  697          /*
 697  698           * You can obviously read that which you can store.
 698  699           */
 699  700          if (dtrace_canstore(addr, sz, mstate, vstate))
 700  701                  return (1);
 701  702  
 702  703          /*
 703  704           * We're allowed to read from our own string table.
 704  705           */
 705      -        if (DTRACE_INRANGE(addr, sz, (uintptr_t)mstate->dtms_difo->dtdo_strtab,
      706 +        if (DTRACE_INRANGE(addr, sz, mstate->dtms_difo->dtdo_strtab,
 706  707              mstate->dtms_difo->dtdo_strlen))
 707  708                  return (1);
 708  709  
      710 +        if (vstate->dtvs_state != NULL &&
      711 +            dtrace_priv_proc(vstate->dtvs_state, mstate)) {
      712 +                proc_t *p;
      713 +
      714 +                /*
      715 +                 * When we have privileges to the current process, there are
      716 +                 * several context-related kernel structures that are safe to
      717 +                 * read, even absent the privilege to read from kernel memory.
      718 +                 * These reads are safe because these structures contain only
      719 +                 * state that (1) we're permitted to read, (2) is harmless or
      720 +                 * (3) contains pointers to additional kernel state that we're
      721 +                 * not permitted to read (and as such, do not present an
      722 +                 * opportunity for privilege escalation).  Finally (and
      723 +                 * critically), because of the nature of their relation with
      724 +                 * the current thread context, the memory associated with these
      725 +                 * structures cannot change over the duration of probe context,
      726 +                 * and it is therefore impossible for this memory to be
      727 +                 * deallocated and reallocated as something else while it's
      728 +                 * being operated upon.
      729 +                 */
      730 +                if (DTRACE_INRANGE(addr, sz, curthread, sizeof (kthread_t)))
      731 +                        return (1);
      732 +
      733 +                if ((p = curthread->t_procp) != NULL && DTRACE_INRANGE(addr,
      734 +                    sz, curthread->t_procp, sizeof (proc_t))) {
      735 +                        return (1);
      736 +                }
      737 +
      738 +                if (curthread->t_cred != NULL && DTRACE_INRANGE(addr, sz,
      739 +                    curthread->t_cred, sizeof (cred_t))) {
      740 +                        return (1);
      741 +                }
      742 +
      743 +                if (p != NULL && p->p_pidp != NULL && DTRACE_INRANGE(addr, sz,
      744 +                    &(p->p_pidp->pid_id), sizeof (pid_t))) {
      745 +                        return (1);
      746 +                }
      747 +
      748 +                if (curthread->t_cpu != NULL && DTRACE_INRANGE(addr, sz,
      749 +                    curthread->t_cpu, offsetof(cpu_t, cpu_pause_thread))) {
      750 +                        return (1);
      751 +                }
      752 +        }
      753 +
 709  754          DTRACE_CPUFLAG_SET(CPU_DTRACE_KPRIV);
 710  755          *illval = addr;
 711  756          return (0);
 712  757  }
 713  758  
 714  759  /*
 715  760   * Convenience routine to check to see if a given string is within a memory
 716  761   * region in which a load may be issued given the user's privilege level;
 717  762   * this exists so that we don't need to issue unnecessary dtrace_strlen()
 718  763   * calls in the event that the user has all privileges.
↓ open down ↓ 2166 lines elided ↑ open up ↑
2885 2930  
2886 2931                  rval = dtrace_getvmreg(ndx,
2887 2932                      &cpu_core[CPU->cpu_id].cpuc_dtrace_flags);
2888 2933  
2889 2934                  DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
2890 2935  
2891 2936                  return (rval);
2892 2937          }
2893 2938  
2894 2939          case DIF_VAR_CURTHREAD:
2895      -                if (!dtrace_priv_kernel(state))
     2940 +                if (!dtrace_priv_proc(state, mstate))
2896 2941                          return (0);
2897 2942                  return ((uint64_t)(uintptr_t)curthread);
2898 2943  
2899 2944          case DIF_VAR_TIMESTAMP:
2900 2945                  if (!(mstate->dtms_present & DTRACE_MSTATE_TIMESTAMP)) {
2901 2946                          mstate->dtms_timestamp = dtrace_gethrtime();
2902 2947                          mstate->dtms_present |= DTRACE_MSTATE_TIMESTAMP;
2903 2948                  }
2904 2949                  return (mstate->dtms_timestamp);
2905 2950  
↓ open down ↓ 1994 lines elided ↑ open up ↑
4900 4945                          break;
4901 4946                  case DIF_OP_BLE:
4902 4947                          if (cc_z | (cc_n ^ cc_v))
4903 4948                                  pc = DIF_INSTR_LABEL(instr);
4904 4949                          break;
4905 4950                  case DIF_OP_BLEU:
4906 4951                          if (cc_c | cc_z)
4907 4952                                  pc = DIF_INSTR_LABEL(instr);
4908 4953                          break;
4909 4954                  case DIF_OP_RLDSB:
4910      -                        if (!dtrace_canstore(regs[r1], 1, mstate, vstate)) {
4911      -                                *flags |= CPU_DTRACE_KPRIV;
4912      -                                *illval = regs[r1];
     4955 +                        if (!dtrace_canload(regs[r1], 1, mstate, vstate))
4913 4956                                  break;
4914      -                        }
4915 4957                          /*FALLTHROUGH*/
4916 4958                  case DIF_OP_LDSB:
4917 4959                          regs[rd] = (int8_t)dtrace_load8(regs[r1]);
4918 4960                          break;
4919 4961                  case DIF_OP_RLDSH:
4920      -                        if (!dtrace_canstore(regs[r1], 2, mstate, vstate)) {
4921      -                                *flags |= CPU_DTRACE_KPRIV;
4922      -                                *illval = regs[r1];
     4962 +                        if (!dtrace_canload(regs[r1], 2, mstate, vstate))
4923 4963                                  break;
4924      -                        }
4925 4964                          /*FALLTHROUGH*/
4926 4965                  case DIF_OP_LDSH:
4927 4966                          regs[rd] = (int16_t)dtrace_load16(regs[r1]);
4928 4967                          break;
4929 4968                  case DIF_OP_RLDSW:
4930      -                        if (!dtrace_canstore(regs[r1], 4, mstate, vstate)) {
4931      -                                *flags |= CPU_DTRACE_KPRIV;
4932      -                                *illval = regs[r1];
     4969 +                        if (!dtrace_canload(regs[r1], 4, mstate, vstate))
4933 4970                                  break;
4934      -                        }
4935 4971                          /*FALLTHROUGH*/
4936 4972                  case DIF_OP_LDSW:
4937 4973                          regs[rd] = (int32_t)dtrace_load32(regs[r1]);
4938 4974                          break;
4939 4975                  case DIF_OP_RLDUB:
4940      -                        if (!dtrace_canstore(regs[r1], 1, mstate, vstate)) {
4941      -                                *flags |= CPU_DTRACE_KPRIV;
4942      -                                *illval = regs[r1];
     4976 +                        if (!dtrace_canload(regs[r1], 1, mstate, vstate))
4943 4977                                  break;
4944      -                        }
4945 4978                          /*FALLTHROUGH*/
4946 4979                  case DIF_OP_LDUB:
4947 4980                          regs[rd] = dtrace_load8(regs[r1]);
4948 4981                          break;
4949 4982                  case DIF_OP_RLDUH:
4950      -                        if (!dtrace_canstore(regs[r1], 2, mstate, vstate)) {
4951      -                                *flags |= CPU_DTRACE_KPRIV;
4952      -                                *illval = regs[r1];
     4983 +                        if (!dtrace_canload(regs[r1], 2, mstate, vstate))
4953 4984                                  break;
4954      -                        }
4955 4985                          /*FALLTHROUGH*/
4956 4986                  case DIF_OP_LDUH:
4957 4987                          regs[rd] = dtrace_load16(regs[r1]);
4958 4988                          break;
4959 4989                  case DIF_OP_RLDUW:
4960      -                        if (!dtrace_canstore(regs[r1], 4, mstate, vstate)) {
4961      -                                *flags |= CPU_DTRACE_KPRIV;
4962      -                                *illval = regs[r1];
     4990 +                        if (!dtrace_canload(regs[r1], 4, mstate, vstate))
4963 4991                                  break;
4964      -                        }
4965 4992                          /*FALLTHROUGH*/
4966 4993                  case DIF_OP_LDUW:
4967 4994                          regs[rd] = dtrace_load32(regs[r1]);
4968 4995                          break;
4969 4996                  case DIF_OP_RLDX:
4970      -                        if (!dtrace_canstore(regs[r1], 8, mstate, vstate)) {
4971      -                                *flags |= CPU_DTRACE_KPRIV;
4972      -                                *illval = regs[r1];
     4997 +                        if (!dtrace_canload(regs[r1], 8, mstate, vstate))
4973 4998                                  break;
4974      -                        }
4975 4999                          /*FALLTHROUGH*/
4976 5000                  case DIF_OP_LDX:
4977 5001                          regs[rd] = dtrace_load64(regs[r1]);
4978 5002                          break;
4979 5003                  case DIF_OP_ULDSB:
4980 5004                          regs[rd] = (int8_t)
4981 5005                              dtrace_fuword8((void *)(uintptr_t)regs[r1]);
4982 5006                          break;
4983 5007                  case DIF_OP_ULDSH:
4984 5008                          regs[rd] = (int16_t)
↓ open down ↓ 11047 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX