Print this page
NEX-3997 Kernel BAD TRAP type=d panic from di_mem_addr on bogus di_state_t structure
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/io/devinfo.c
          +++ new/usr/src/uts/common/io/devinfo.c
↓ open down ↓ 550 lines elided ↑ open up ↑
 551  551          return (0);
 552  552  }
 553  553  
 554  554  /*ARGSUSED*/
 555  555  static int
 556  556  di_close(dev_t dev, int flag, int otype, cred_t *cred_p)
 557  557  {
 558  558          struct di_state *st;
 559  559          int             m = (int)getminor(dev) - DI_NODE_SPECIES;
 560  560  
 561      -        if (m < 0) {
      561 +        if (m < 0 || m >= di_max_opens) {
 562  562                  cmn_err(CE_WARN, "closing non-existent devinfo minor %d",
 563  563                      m + DI_NODE_SPECIES);
 564  564                  return (ENXIO);
 565  565          }
 566  566  
 567      -        st = di_states[m];
 568      -        ASSERT(m < di_max_opens && st != NULL);
 569      -
 570      -        di_freemem(st);
 571      -        kmem_free(st, sizeof (struct di_state));
 572      -
 573  567          /*
 574  568           * empty slot in state table
 575  569           */
 576  570          mutex_enter(&di_lock);
      571 +        st = di_states[m];
 577  572          di_states[m] = NULL;
      573 +        mutex_exit(&di_lock);
      574 +
      575 +        if (st != NULL) {
      576 +                di_freemem(st);
      577 +                kmem_free(st, sizeof (struct di_state));
      578 +        }
      579 +
 578  580          dcmn_err((CE_CONT, "di_close: thread = %p, assigned minor = %d\n",
 579  581              (void *)curthread, m + DI_NODE_SPECIES));
 580      -        mutex_exit(&di_lock);
 581  582  
 582  583          return (0);
 583  584  }
 584  585  
 585  586  
 586  587  /*ARGSUSED*/
 587  588  static int
 588  589  di_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp)
 589  590  {
 590  591          int             rv, error;
↓ open down ↓ 5 lines elided ↑ open up ↑
 596  597          char            *drv_name;
 597  598          size_t          map_size, size;
 598  599          struct di_mem   *dcp;
 599  600          int             ndi_flags;
 600  601  
 601  602          if (m < 0 || m >= di_max_opens) {
 602  603                  return (ENXIO);
 603  604          }
 604  605  
 605  606          st = di_states[m];
 606      -        ASSERT(st != NULL);
      607 +        if(st == NULL) {
      608 +                return (ENXIO);
      609 +        }
 607  610  
 608  611          dcmn_err2((CE_CONT, "di_ioctl: mode = %x, cmd = %x\n", mode, cmd));
 609  612  
 610  613          switch (cmd) {
 611  614          case DINFOIDENT:
 612  615                  /*
 613  616                   * This is called from di_init to verify that the driver
 614  617                   * opened is indeed devinfo. The purpose is to guard against
 615  618                   * sending ioctl to an unknown driver in case of an
 616  619                   * unresolved major number conflict during bfu.
↓ open down ↓ 3660 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX