Print this page
8956 Implement KPTI
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
9210 remove KMDB branch debugging support
9211 ::crregs could do with cr2/cr3 support
9209 ::ttrace should be able to filter by thread
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
Reviewed by: Yuri Pankov <yuripv@yuripv.net>

Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/mdb/intel/kmdb/kaif.c
          +++ new/usr/src/cmd/mdb/intel/kmdb/kaif.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   * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  23   23   * Use is subject to license terms.
       24 + *
       25 + * Copyright 2018 Joyent, Inc.
  24   26   */
  25   27  
  26      -#pragma ident   "%Z%%M% %I%     %E% SMI"
  27      -
  28   28  /*
  29   29   * The debugger/"PROM" interface layer
  30   30   *
  31   31   * It makes more sense on SPARC. In reality, these interfaces deal with three
  32   32   * things: setting break/watchpoints, stepping, and interfacing with the KDI to
  33   33   * set up kmdb's IDT handlers.
  34   34   */
  35   35  
  36   36  #include <kmdb/kmdb_dpi_impl.h>
  37   37  #include <kmdb/kmdb_kdi.h>
↓ open down ↓ 5 lines elided ↑ open up ↑
  43   43  #include <mdb/mdb_debug.h>
  44   44  #include <mdb/mdb_isautil.h>
  45   45  #include <mdb/mdb_io_impl.h>
  46   46  #include <mdb/mdb_kreg_impl.h>
  47   47  #include <mdb/mdb.h>
  48   48  
  49   49  #include <sys/types.h>
  50   50  #include <sys/bitmap.h>
  51   51  #include <sys/termios.h>
  52   52  #include <sys/kdi_impl.h>
       53 +#include <sys/sysmacros.h>
  53   54  
  54   55  /*
  55   56   * This is the area containing the saved state when we enter
  56   57   * via kmdb's IDT entries.
  57   58   */
  58   59  kdi_cpusave_t   *kaif_cpusave;
  59   60  int             kaif_ncpusave;
  60   61  kdi_drreg_t     kaif_drreg;
  61   62  
  62   63  uint32_t        kaif_waptmap;
↓ open down ↓ 186 lines elided ↑ open up ↑
 249  250          kreg_t *regp;
 250  251  
 251  252          if ((regp = kaif_find_regp(regname)) == NULL)
 252  253                  return (-1);
 253  254  
 254  255          *regp = val;
 255  256  
 256  257          return (0);
 257  258  }
 258  259  
      260 +/*
      261 + * Refuse to single-step or break within any stub that loads a user %cr3 value.
      262 + * As the KDI traps are not careful to restore such a %cr3, this can all go
      263 + * wrong, both spectacularly and subtly.
      264 + */
      265 +static boolean_t
      266 +kaif_toxic_text(uintptr_t addr)
      267 +{
      268 +        static GElf_Sym toxic_syms[2] = { 0, };
      269 +        size_t i;
      270 +
      271 +        if (toxic_syms[0].st_name == NULL) {
      272 +                if (mdb_tgt_lookup_by_name(mdb.m_target, MDB_TGT_OBJ_EXEC,
      273 +                    "tr_iret_user", &toxic_syms[0], NULL) != 0)
      274 +                        warn("couldn't find tr_iret_user\n");
      275 +                if (mdb_tgt_lookup_by_name(mdb.m_target, MDB_TGT_OBJ_EXEC,
      276 +                    "tr_mmu_flush_user_range", &toxic_syms[1], NULL) != 0)
      277 +                        warn("couldn't find tr_mmu_flush_user_range\n");
      278 +        }
      279 +
      280 +        for (i = 0; i < ARRAY_SIZE(toxic_syms); i++) {
      281 +                if (addr >= toxic_syms[i].st_value &&
      282 +                    addr - toxic_syms[i].st_value < toxic_syms[i].st_size)
      283 +                        return (B_TRUE);
      284 +        }
      285 +
      286 +        return (B_FALSE);
      287 +}
      288 +
 259  289  static int
 260  290  kaif_brkpt_arm(uintptr_t addr, mdb_instr_t *instrp)
 261  291  {
 262  292          mdb_instr_t bkpt = KAIF_BREAKPOINT_INSTR;
 263  293  
      294 +        if (kaif_toxic_text(addr)) {
      295 +                warn("%a cannot be a breakpoint target\n", addr);
      296 +                return (set_errno(EMDB_TGTNOTSUP));
      297 +        }
      298 +
 264  299          if (mdb_tgt_vread(mdb.m_target, instrp, sizeof (mdb_instr_t), addr) !=
 265  300              sizeof (mdb_instr_t))
 266  301                  return (-1); /* errno is set for us */
 267  302  
 268  303          if (mdb_tgt_vwrite(mdb.m_target, &bkpt, sizeof (mdb_instr_t), addr) !=
 269  304              sizeof (mdb_instr_t))
 270  305                  return (-1); /* errno is set for us */
 271  306  
 272  307          return (0);
 273  308  }
↓ open down ↓ 164 lines elided ↑ open up ↑
 438  473  kaif_step(void)
 439  474  {
 440  475          kreg_t pc, fl, oldfl, newfl, sp;
 441  476          mdb_tgt_addr_t npc;
 442  477          mdb_instr_t instr;
 443  478          int emulated = 0, rchk = 0;
 444  479          size_t pcoff = 0;
 445  480  
 446  481          (void) kmdb_dpi_get_register("pc", &pc);
 447  482  
      483 +        if (kaif_toxic_text(pc)) {
      484 +                warn("%a cannot be stepped\n", pc);
      485 +                return (set_errno(EMDB_TGTNOTSUP));
      486 +        }
      487 +
 448  488          if ((npc = mdb_dis_nextins(mdb.m_disasm, mdb.m_target,
 449  489              MDB_TGT_AS_VIRT, pc)) == pc) {
 450  490                  warn("failed to decode instruction at %a for step\n", pc);
 451  491                  return (set_errno(EINVAL));
 452  492          }
 453  493  
 454  494          /*
 455  495           * Stepping behavior depends on the type of instruction.  It does not
 456  496           * depend on the presence of a REX prefix, as the action we take for a
 457  497           * given instruction doesn't currently vary for 32-bit instructions
↓ open down ↓ 138 lines elided ↑ open up ↑
 596  636                   * pre-step value.  We'll also need to turn TF back off.
 597  637                   */
 598  638                  (void) kmdb_dpi_get_register(FLAGS_REG_NAME, &fl);
 599  639                  (void) kmdb_dpi_set_register(FLAGS_REG_NAME,
 600  640                      ((fl & ~(KREG_EFLAGS_TF_MASK|KREG_EFLAGS_IF_MASK)) |
 601  641                      (oldfl & KREG_EFLAGS_IF_MASK)));
 602  642                  return (0);
 603  643          }
 604  644  }
 605  645  
 606      -/*
 607      - * The target has already configured the chip for branch step, leaving us to
 608      - * actually make the machine go.  Due to a number of issues involving
 609      - * the potential alteration of system state via instructions like sti, cli,
 610      - * pushfl, and popfl, we're going to treat this like a normal system resume.
 611      - * All CPUs will be released, on the kernel's IDT.  Our primary concern is
 612      - * the alteration/storage of our TF'd EFLAGS via pushfl and popfl.  There's no
 613      - * real workaround - we don't have opcode breakpoints - so the best we can do is
 614      - * to ensure that the world won't end if someone does bad things to EFLAGS.
 615      - *
 616      - * Two things can happen:
 617      - *  1. EFLAGS.TF may be cleared, either maliciously or via a popfl from saved
 618      - *     state.  The CPU will continue execution beyond the branch, and will not
 619      - *     reenter the debugger unless brought/sent in by other means.
 620      - *  2. Someone may pushlf the TF'd EFLAGS, and may stash a copy of it somewhere.
 621      - *     When the saved version is popfl'd back into place, the debugger will be
 622      - *     re-entered on a single-step trap.
 623      - */
 624      -static void
 625      -kaif_step_branch(void)
 626      -{
 627      -        kreg_t fl;
 628      -
 629      -        (void) kmdb_dpi_get_register(FLAGS_REG_NAME, &fl);
 630      -        (void) kmdb_dpi_set_register(FLAGS_REG_NAME,
 631      -            (fl | (1 << KREG_EFLAGS_TF_SHIFT)));
 632      -
 633      -        kmdb_dpi_resume_master();
 634      -
 635      -        (void) kmdb_dpi_set_register(FLAGS_REG_NAME, fl);
 636      -}
 637      -
 638  646  /*ARGSUSED*/
 639  647  static uintptr_t
 640  648  kaif_call(uintptr_t funcva, uint_t argc, const uintptr_t argv[])
 641  649  {
 642  650          return (kaif_invoke(funcva, argc, argv));
 643  651  }
 644  652  
 645  653  static void
 646  654  dump_crumb(kdi_crumb_t *krmp)
 647  655  {
↓ open down ↓ 69 lines elided ↑ open up ↑
 717  725  }
 718  726  
 719  727  static void
 720  728  kaif_modchg_cancel(void)
 721  729  {
 722  730          ASSERT(kaif_modchg_cb != NULL);
 723  731  
 724  732          kaif_modchg_cb = NULL;
 725  733  }
 726  734  
 727      -static void
 728      -kaif_msr_add(const kdi_msr_t *msrs)
 729      -{
 730      -        kdi_msr_t *save;
 731      -        size_t nr_msrs = 0;
 732      -        size_t i;
 733      -
 734      -        while (msrs[nr_msrs].msr_num != 0)
 735      -                nr_msrs++;
 736      -        /* we want to copy the terminating kdi_msr_t too */
 737      -        nr_msrs++;
 738      -
 739      -        save = mdb_zalloc(sizeof (kdi_msr_t) * nr_msrs * kaif_ncpusave,
 740      -            UM_SLEEP);
 741      -
 742      -        for (i = 0; i < kaif_ncpusave; i++)
 743      -                bcopy(msrs, &save[nr_msrs * i], sizeof (kdi_msr_t) * nr_msrs);
 744      -
 745      -        kmdb_kdi_set_debug_msrs(save);
 746      -}
 747      -
 748      -static uint64_t
 749      -kaif_msr_get(int cpuid, uint_t num)
 750      -{
 751      -        kdi_cpusave_t *save;
 752      -        kdi_msr_t *msr;
 753      -        int i;
 754      -
 755      -        if ((save = kaif_cpuid2save(cpuid)) == NULL)
 756      -                return (-1); /* errno is set for us */
 757      -
 758      -        msr = save->krs_msr;
 759      -
 760      -        for (i = 0; msr[i].msr_num != 0; i++) {
 761      -                if (msr[i].msr_num == num && (msr[i].msr_type & KDI_MSR_READ))
 762      -                        return (msr[i].kdi_msr_val);
 763      -        }
 764      -
 765      -        return (0);
 766      -}
 767      -
 768  735  void
 769  736  kaif_trap_set_debugger(void)
 770  737  {
 771  738          kmdb_kdi_idt_switch(NULL);
 772  739  }
 773  740  
 774  741  void
 775  742  kaif_trap_set_saved(kaif_cpusave_t *cpusave)
 776  743  {
 777  744          kmdb_kdi_idt_switch(cpusave);
↓ open down ↓ 99 lines elided ↑ open up ↑
 877  844          kaif_set_register,
 878  845          kaif_brkpt_arm,
 879  846          kaif_brkpt_disarm,
 880  847          kaif_wapt_validate,
 881  848          kaif_wapt_reserve,
 882  849          kaif_wapt_release,
 883  850          kaif_wapt_arm,
 884  851          kaif_wapt_disarm,
 885  852          kaif_wapt_match,
 886  853          kaif_step,
 887      -        kaif_step_branch,
 888  854          kaif_call,
 889  855          kaif_dump_crumbs,
 890      -        kaif_msr_add,
 891      -        kaif_msr_get,
 892  856  };
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX